Leia este documento em Português
This is an Arduino library for the SI4735, BROADCAST AM/FM/SW RADIO RECEIVER IC from Silicon Labs. This library is intended to provide an easier interface for controlling the SI4735 by using Arduino platform. The communication used by this library is I2C.
This library can be freely distributed using the MIT Free Software model. Copyright (c) 2019 Ricardo Lima Caratti
Contact: [email protected]
Attention:
- Documentation under construction.
- The SI4735 is a 3.3V part. If you are not using a 3.3V version of Arduino, you have to use a kind of 5V to 3.3V converter.
- License Copyright
- Thanks
- Your support is important
- About the SI4735
- Terminology
- Labrary Features
- Library Installation
- Hardware Requirements and Setup
- API Documentation
- Defined Data Types and Structures
- Public Methods
- Usual methods
- Si4735 current status
- SI4735 Received Signal Quality
- getCurrentReceivedSignalQuality
- getCurrentRSSI
- getCurrentSNR
- getCurrentRssiDetectLow
- getCurrentRssiDetectHigh
- getCurrentSnrDetectLow
- getCurrentSnrDetectHigh
- getCurrentValidChannel
- getCurrentAfcRailIndicator
- getCurrentSoftMuteIndicator
- getCurrentStereoBlend
- getCurrentPilot
- getCurrentMultipath
- getCurrentSignedFrequencyOffset
- getCurrentMultipathDetectLow
- getCurrentMultipathDetectHigh
- getCurrentBlendDetectInterrupt
- Current AGC Status
- Filters
- SI4735 Firmware Information
- RDS
- Single Side Band (SSB) Support
Copyright (c) 2019 Ricardo Lima Caratti
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
I would like to thank Mr. Francisco Scaramella for the suggestions and contributions provided in the electronics field as well as for the testing of the functions implemented in this library.
I would like to thank Mr Vadim Afonkin for making available the SSBRX patches for SI4735-D60 on his Dropbox repository.
If you would like to support this library development, consider joining this project via Github. Alternatively, make suggestions on features you would like available in this library. Thank you!
The Si4735 is DSP radio receiver IC from Silcon Labs. It has great performance on AM (LW/MW/SW) and local FM station. The SI4735 can be programmed by using commands and responses. You can contron it via a microcontroller like Arduino. To make the SI4735 perform an action, the microccontroller have to send a set of bytes (command and arguments) tha the device interpret it and executes the given command.
- FM band support (64–108 MHz)
- AM (MW) band support (520–1710 kHz)
- SW band support (2.3–26.1 MHz)
- LW band support (153–279 kHz)
- Allows firmware upgrade. Including the possibility of adjustments to demodulate SSB.
- Advanced AM/FM seek tuning
- Automatic frequency control (AFC)
- Automatic gain control (AGC)
- Digital FM stereo decoder
- AM/FM/SW/LW digital tuning
- RDS/RBDS processor
- Digital audio out
- I2C and SPI interface
- Great Programming Guide and additional documentation to deal with the device
Term | Description |
---|---|
Arduino Libraries | Libraries are files written in C or C++ (.c, .cpp) which provide your sketches with extra functionality. The SI4735 Library provides extra functionalities to make easier the Arduino deal with Si4735 device |
IDE | Integrated Development Environment |
Sketch | Name that Arduino environment uses for a program |
interrupt | In this context, it is a Arduino Resource. Allows important tasks to be performed regardless of the flow of your program |
C++ | A object-oriented programming (OOP) language. It is a superset of the C language with an additional concept of "classes." |
programming guide | In this context it refers to Si47XX PROGRAMMING GUIDE |
POC | Proof of Concept |
SEN | Serial enable pin, active low; used as device select in 3-wire and SPI operation and address selection in 2-wire operation |
SDIO | Serial data in/data out pin |
SCLK | Serial clock pin |
RST | Also RSTb—Reset pin, active low |
RCLK | External reference clock |
GPO | General purpose output |
CTS | Clear to send |
STC | Seek/Tune Complete |
NVM | Non-volatile internal device memory |
CMD | Command byte |
COMMANDn | Command register (16-bit) in 3-Wire mode (n = 1 to 4) |
ARGn | Argument byte (n = 1 to 7) |
STATUS | Status byte |
RESP | Response byte (n = 1 to 15) |
RESPONSEn | Response register (16-bit) in 3-Wire mode (n = 1 to 8) |
This library uses the I2C communication protocol and implements most of the functions offered by Si4735 (BROADCAST AM / FM / SW / LW RADIO RECEIVER).
- Open Source
- Built Based on Si47XX PROGRAMMING GUIDE
- C++ Lenguage and Object-oriented programming
- Available on Arduino IDE (Manage Libraries)
- Simplifies projects based on SI4735
- I2C communication
- More than 60 SI4735 functions implemented
- RDS support
- SSB (Single Side Band) patch support
You can install this library on your Arduino environment using different methods. The best ways to do that are described below.
This is the easiest method to install this library.
First, you have to download this library in zip format. Click here to download.
Unzip the SI4735.zip file in your Arduino Library folder.
- On Windows: "My Documents\Arduino\libraries"
- On MAC OS: ˜/Documents/Arduino/libraries
- On Linux: ˜/Documents/Arduino/libraries
This library has been written for the Arduino platform and has been successfully tested on Pro Mini. I beleave it will work on any other Arduino with I2C support.
The SI4735 device works with 3.3V only. If you are not using a 3.3V version of Arduino, you have to use a kind of converter. This includes the Arduino operating pins.
The main porpuse of this prototype is to test de Si4735 Arduino Library. It does not intend to be a real radio for exigent listener. However, it is possible to start with it and after include some devices to improve, for example, its sensibility, beyond other desired features.
The image bellow shows a version of Slicon Labs SSOP Typical Application Schematic. The basic difference are the pull-up resitors on I2C bus.
THE SI4735 IS A 3.3V PART. IF YOU ARE NOT USING A 3.3V VERSION OF ARDUINO, YOU HAVE TO USE A KIND OF 5V TO 3.3V CONVERTER.
The table below shows the component parts used to build the radio prototype based on Si4735 and used the Slicon Labs SSOP Typical Application Schematic as main source. However, some parts were included by the author of this project.
Part | Description |
---|---|
C1 | 22nF Monolithic Multilayer Chip Ceramic non polarized capacitor (Place it close to VA pin) |
C2 | 100pF Monolithic Multilayer Chip Ceramic non polarized capacitor |
C3 | 470nF Monolithic Multilayer Chip Ceramic non polarized capacitor |
C4 | 100nF Monolithic Multilayer Chip Ceramic non polarized capacitor (Place it close to VD pin) |
C5 and C6 | 22pF (Crystal load capacitors) |
C7 and C8[ˆ1] | 4.7uF Monolithic Multilayer Chip Ceramic non polarized capacitor |
R3 | 2.2K |
(R4 and R5)[ˆ2] | 10K (pull-up resistors) |
L1 | Ferrite loop stick (about 500 μH) |
X1 | 32.768 kHz crystal |
- [ˆ1]: C7 and C8 are ceramic capacitors included by the author of this project. They are not present on original Silicon Labs schematic.
- [ˆ2]: R4 and R5 are pull-up resistor included by the author of this project. They are not present on original Silicon Labs schematic.
Notes from Silicon Labs Broadcast AM/FM/SW/LW Radio Receiver documentation (page 12):
- Place C1 close to VA and C4 close to VD pin.
- All grounds connect directly to GND plane on PCB.
- Pins 6 and 7 are no connects, leave floating.
- Pins 10 and 11 are unused. Tie these pins to GND.
- To ensure proper operation and receiver performance, follow the guidelines in “AN383: Si47xx Antenna, Schematic,
- Layout, and Design Guidelines.” Silicon Laboratories will evaluate schematics and layouts for qualified customers.
- Pin 8 connects to the FM antenna interface, and pin 12 connects to the AM antenna interface.
- Place Si473x-D60 as close as possible to antenna and keep the FMI and AMI traces as short as possible.
It was a bit hard to solder the kind of CI on adapter. However, by using a electronic magnifier it was possible.
Si4735 on Adapter | Si4735 on Adapter |
---|---|
![]() |
![]() |
Si4735 on Adapter | Si4735 on Adapter |
---|---|
![]() |
![]() |
The basic circuit built on protoboard is based on the “SSOP Typical Application Schematic”, suggested by the Silicon Labs Documentation (Si4730/31/34/35-D60-BROADCAST AM/FM/SW/LW RADIO RECEIVER; page 19). Two pull-up 10K resistors were added on I2C bus. Also, it is recomended to add two 4.7uF capacitors between the CI audio output and audio amplifier. The photos below do not show these capacitors. See C7 and C8 on schematic.
To make the SI4735 device easier to deal, some defined data types were built to handle byte and bits responses.
/*****************************************************************
* SI473X data types
* These data types will be usefull to deal with SI473X
*****************************************************************/
/*
* Power Up arguments data type
* See Si47XX PROGRAMMING GUIDE; AN332; pages 64 and 65
*/
typedef union {
struct
{
// ARG1
byte FUNC : 4; // Function (0 = FM Receive; 1–14 = Reserved; 15 = Query Library ID)
byte XOSCEN : 1; // Crystal Oscillator Enable (0 = crystal oscillator disabled; 1 = Use crystal oscillator and and OPMODE=ANALOG AUDIO) .
byte PATCH : 1; // Patch Enable (0 = Boot normally; 1 = Copy non-volatile memory to RAM).
byte GPO2OEN : 1; // GPO2 Output Enable (0 = GPO2 output disabled; 1 = GPO2 output enabled).
byte CTSIEN : 1; // CTS Interrupt Enable (0 = CTS interrupt disabled; 1 = CTS interrupt enabled).
// ARG2
byte OPMODE; // Application Setting. See page 65
} arg;
byte raw[2]; // same arg memory position, so same content.
} si473x_powerup;
/*
* Represents how the frequency is stored in the si4735.
* It helps to convert frequency in unsigned int to two bytes (FREQL and FREQH)
*/
typedef union {
struct
{
byte FREQL; // Tune Frequency High Byte.
byte FREQH; // Tune Frequency Low Byte.
} raw;
unsigned value;
} si47x_frequency;
/*
* Represents searching for a valid frequency data type.
*/
typedef union {
struct
{
byte RESERVED1 : 2;
byte WRAP : 1; // Determines whether the seek should Wrap = 1, or Halt = 0 when it hits the band limit.
byte SEEKUP : 1; // Determines the direction of the search, either UP = 1, or DOWN = 0.
byte RESERVED2 : 4;
} arg;
byte raw;
} si47x_seek;
/*
* Response status command
* See Si47XX PROGRAMMING GUIDE; pages 73 and
*/
typedef union {
struct
{
// Status
byte STCINT : 1; // Seek/Tune Complete Interrupt; 1 = Tune complete has been triggered.
byte DUMMY1 : 1;
byte RDSINT : 1; // Radio Data System (RDS) Interrup; 0 = interrupt has not been triggered.
byte RSQINT : 1; // Received Signal Quality Interrupt; 0 = interrupt has not been triggered.
byte DUMMY2 : 2;
byte ERR : 1; // Error. 0 = No error 1 = Error
byte CTS : 1; // Clear to Send.
// RESP1
byte VALID : 1; // Valid Channel
byte AFCRL : 1; // AFC Rail Indicator
byte DUMMY3 : 5;
byte BLTF : 1; // Reports if a seek hit the band limit
// RESP2
byte READFREQH; // Read Frequency High Byte.
// RESP3
byte READFREQL; // Read Frequency Low Byte.
// RESP4
byte RSSI; // Received Signal Strength Indicator (dBμV)
// RESP5
byte SNR; // This byte contains the SNR metric when tune is complete (dB).
// RESP6
byte MULT; // Contains the multipath metric when tune is complete
// RESP7
byte READANTCAP; // Contains the current antenna tuning capacitor value
} resp;
byte raw[7];
} si47x_response_status;
/*
* Firmware Information
*/
typedef union {
struct
{
// status ("RESP0")
byte STCINT : 1;
byte DUMMY1 : 1;
byte RDSINT : 1;
byte RSQINT : 1;
byte DUMMY2 : 2;
byte ERR : 1;
byte CTS : 1;
byte PN; // RESP1 - Final 2 digits of Part Number (HEX).
byte FWMAJOR; // RESP2 - Firmware Major Revision (ASCII).
byte FWMINOR; // RESP3 - Firmware Minor Revision (ASCII).
byte PATCHH; // RESP4 - Patch ID High Byte (HEX).
byte PATCHL; // RESP5 - Patch ID Low Byte (HEX).
byte CMPMAJOR; // RESP6 - Component Major Revision (ASCII).
byte CMPMINOR; // RESP7 - Component Minor Revision (ASCII).
byte CHIPREV; // RESP8 - Chip Revision (ASCII).
// RESP9 to RESP15 not used
} resp;
byte raw[9];
} si47x_firmware_information;
/*
* Status of FM_TUNE_FREQ or FM_SEEK_START commands or
* Status of AM_TUNE_FREQ or AM_SEEK_START commands.
*
* See Si47XX PROGRAMMING GUIDE; AN332; pages 73 and 139
*/
typedef union {
struct
{
byte INTACK : 1; // If set, clears the seek/tune complete interrupt status indicator.
byte CANCEL : 1; // If set, aborts a seek currently in progress.
byte RESERVED2 : 6;
} arg;
byte raw;
} si47x_tune_status;
/*
* Property Data type (help to deal with SET_PROPERTY command on si473X)
*/
typedef union {
struct
{
byte byteLow;
byte byteHigh;
} raw;
unsigned value;
} si47x_property;
/*
********************** RDS Data types *******************************
*/
/*
* Data type for status information about the received signal quality
* FM_RSQ_STATUS and AM_RSQ_STATUS
* See Si47XX PROGRAMMING GUIDE; AN332; pages 75 and
*/
typedef union {
struct
{
// status ("RESP0")
byte STCINT : 1;
byte DUMMY1 : 1;
byte RDSINT : 1;
byte RSQINT : 1;
byte DUMMY2 : 2;
byte ERR : 1;
byte CTS : 1;
// RESP1
byte RSSIILINT : 1; // RSSI Detect Low.
byte RSSIHINT : 1; // RSSI Detect High.
byte SNRLINT : 1; // SNR Detect Low.
byte SNRHINT : 1; // SNR Detect High.
byte MULTLINT : 1; // Multipath Detect Low
byte MULTHINT : 1; // Multipath Detect High
byte DUMMY3 : 1;
byte BLENDINT : 1; // Blend Detect Interrupt.
// RESP2
byte VALID : 1; // Valid Channel.
byte AFCRL : 1; // AFC Rail Indicator.
byte DUMMY4 : 1;
byte SMUTE : 1; // Soft Mute Indicator. Indicates soft mute is engaged.
byte DUMMY5 : 4;
// RESP3
byte STBLEND : 7; // Indicates amount of stereo blend in% (100 = full stereo, 0 = full mono).
byte PILOT : 1; // Indicates stereo pilot presence.
// RESP4 to RESP7
byte RSSI; // RESP4 - Contains the current receive signal strength (0–127 dBμV).
byte SNR; // RESP5 - Contains the current SNR metric (0–127 dB).
byte MULT; // RESP6 - Contains the current multipath metric. (0 = no multipath; 100 = full multipath)
byte FREQOFF; // RESP7 - Signed frequency offset (kHz).
} resp;
byte raw[8];
} si47x_rqs_status;
/*
* FM_RDS_STATUS (0x24) command
* Data type for command and response information
* See Si47XX PROGRAMMING GUIDE; AN332; pages 77 and 78
*/
// Command data type
typedef union {
struct
{
byte INTACK : 1; // Interrupt Acknowledge; 0 = RDSINT status preserved; 1 = Clears RDSINT.
byte MTFIFO : 1; // Empty FIFO; 0 = If FIFO not empty; 1 = Clear RDS Receive FIFO.
byte STATUSONLY : 1; // Determines if data should be removed from the RDS FIFO.
byte dummy : 5;
} arg;
byte raw;
} si47x_rds_command;
```cpp
// Response data type for current channel and reads an entry from the RDS FIFO.
typedef union {
struct
{
// status ("RESP0")
byte STCINT : 1;
byte DUMMY1 : 1;
byte RDSINT : 1;
byte RSQINT : 1;
byte DUMMY2 : 2;
byte ERR : 1;
byte CTS : 1;
// RESP1
byte RDSRECV : 1; // RDS Received; 1 = FIFO filled to minimum number of groups set by RDSFIFOCNT.
byte RDSSYNCLOST : 1; // RDS Sync Lost; 1 = Lost RDS synchronization.
byte RDSSYNCFOUND : 1; // RDS Sync Found; 1 = Found RDS synchronization.
byte DUMMY3 : 1;
byte RDSNEWBLOCKA : 1; // RDS New Block A; 1 = Valid Block A data has been received.
byte RDSNEWBLOCKB : 1; // RDS New Block B; 1 = Valid Block B data has been received.
byte DUMMY4 : 2;
// RESP2
byte RDSSYNC : 1; // RDS Sync; 1 = RDS currently synchronized.
byte DUMMY5 : 1;
byte GRPLOST : 1; // Group Lost; 1 = One or more RDS groups discarded due to FIFO overrun.
byte DUMMY6 : 5;
// RESP3 to RESP11
byte RDSFIFOUSED; // RESP3 - RDS FIFO Used; Number of groups remaining in the RDS FIFO (0 if empty).
byte BLOCKAH; // RESP4 - RDS Block A; HIGH byte
byte BLOCKAL; // RESP5 - RDS Block A; LOW byte
byte BLOCKBH; // RESP6 - RDS Block B; HIGH byte
byte BLOCKBL; // RESP7 - RDS Block B; LOW byte
byte BLOCKCH; // RESP8 - RDS Block C; HIGH byte
byte BLOCKCL; // RESP9 - RDS Block C; LOW byte
byte BLOCKDH; // RESP10 - RDS Block D; HIGH byte
byte BLOCKDL; // RESP11 - RDS Block D; LOW byte
// RESP12 - Blocks A to D Corrected Errors.
// 0 = No errors;
// 1 = 1–2 bit errors detected and corrected;
// 2 = 3–5 bit errors detected and corrected.
// 3 = Uncorrectable.
byte BLED : 2;
byte BLEC : 2;
byte BLEB : 2;
byte BLEA : 2;
} resp;
byte raw[13];
} si47x_rds_status;
/*
* FM_RDS_INT_SOURCE property data type
* See Si47XX PROGRAMMING GUIDE; AN332; page 103
*/
typedef union {
struct
{
byte RDSRECV : 1; // If set, generate RDSINT when RDS FIFO has at least FM_RDS_INT_FIFO_COUNT entries.
byte RDSSYNCLOST : 1; // If set, generate RDSINT when RDS loses synchronization.
byte RDSSYNCFOUND : 1; // f set, generate RDSINT when RDS gains synchronization.
byte DUMMY1 : 1; // Always write to 0.
byte RDSNEWBLOCKA : 1; // If set, generate an interrupt when Block A data is found or subsequently changed
byte RDSNEWBLOCKB : 1; // If set, generate an interrupt when Block B data is found or subsequently changed
byte DUMMY2 : 10; // Reserved - Always write to 0.
} refined;
byte raw[2];
} si47x_rds_int_source;
/*
* Data type for FM_RDS_CONFIG Property
*
* IMPORTANT: all block errors must be less than or equal the associated block error threshold for the group
* to be stored in the RDS FIFO.
* 0 = No errors; 1 = 1–2 bit errors detected and corrected; 2 = 3–5 bit errors detected and corrected; 3 = Uncorrectable.
* Recommended Block Error Threshold options:
* 2,2,2,2 = No group stored if any errors are uncorrected.
* 3,3,3,3 = Group stored regardless of errors.
* 0,0,0,0 = No group stored containing corrected or uncorrected errors.
* 3,2,3,3 = Group stored with corrected errors on B, regardless of errors on A, C, or D.
*
*/
typedef union {
struct
{
byte RDSEN : 1; // 1 = RDS Processing Enable.
byte DUMMY1 : 7;
byte BLETHD : 2; // Block Error Threshold BLOCKD
byte BLETHC : 2; // Block Error Threshold BLOCKC.
byte BLETHB : 2; // Block Error Threshold BLOCKB.
byte BLETHA : 2; // Block Error Threshold BLOCKA.
} arg;
byte raw[2];
} si47x_rds_config;
/*
* Block A data type
*/
typedef union {
struct
{
unsigned pi;
} refined;
struct
{
byte lowValue;
byte highValue; // Most Significant byte first
} raw;
} si47x_rds_blocka;
/*
* Block B data type
* More about Group Type Contents see: https://github.com/pu2clr/SI4735/tree/master/examples/SI4735_RDS
* See also Si47XX PROGRAMMING GUIDE; AN332; pages 78 and 79
*/
typedef union {
struct
{
byte content : 5; // Depends on Group Type and Version codes.
byte programType : 5; // PTY (Program Type) code
byte trafficProgramCode : 1; // 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
byte versionCode : 1; // 0=A; 1=B
byte groupType : 4; // Group Type code.
} refined;
struct
{
byte lowValue;
byte highValue; // Most Significant Byte first
} raw;
} si47x_rds_blockb;
typedef union {
struct
{
byte offset : 5;
byte offset_sense : 1; //
byte minute : 6; //
byte hour : 4; //
unsigned mjd;
} refined;
byte raw[4];
} si47x_rds_date_time;
/* AGC data types
* FM / AM and SSB structure to AGC
* See Si47XX PROGRAMMING GUIDE; AN332; For FM page 80; for AM page 142
* See AN332 REV 0.8 Universal Programming Guide Amendment for SI4735-D60 SSB and NBFM patches; page 18.
*/
typedef union {
struct {
// status ("RESP0")
byte STCINT : 1;
byte DUMMY1 : 1;
byte RDSINT : 1; // Not used for AM/SSB
byte RSQINT : 1;
byte DUMMY2 : 2;
byte ERR : 1;
byte CTS : 1;
// RESP1
byte AGCDIS : 1; // This bit indicates if the AGC is enabled or disabled. 0 = AGC enabled; 1 = AGC disabled.
byte DUMMY:7;
// RESP2
byte AGCDX; // For FM (5 bits - READ_LNA_GAIN_INDEX - 0 = Minimum attenuation (max gain)). For AM (8 bits). This byte reports the current AGC gain index.
} refined;
byte raw[3];
} si47x_agc_status;
/*
* If FM, Overrides AGC setting by disabling the AGC and forcing the LNA to have a certain gain that ranges between 0
* (minimum attenuation) and 26 (maximum attenuation).
* If AM, overrides the AGC setting by disabling the AGC and forcing the gain index that ranges between 0
* See Si47XX PROGRAMMING GUIDE; AN332; For FM page 81; for AM page 143
*/
typedef union {
struct {
// ARG1
byte AGCDIS : 1; // if set to 1 indicates if the AGC is disabled. 0 = AGC enabled; 1 = AGC disabled.
byte DUMMY : 7;
// ARG2
byte AGCDX; // AGC Index; If AMAGCDIS = 1, this byte forces the AGC gain index; 0 = Minimum attenuation (max gain)
} arg;
byte raw[2];
} si47x_agc_overrride;
To use the methods below you have to declare the class SI4735 in your sketch. The folder examples has some examples that show how to use these methods. For example: see Proof of Concept for SI4735 Arduino Library
/*
* Starts the Si473X device.
*
* @param byte resetPin Digital Arduino Pin used to RESET command
* @param byte interruptPin interrupt Arduino Pin (see your Arduino pinout). If less than 0, iterrupt disabled
* @param byte defaultFunction
*/
void SI4735::setup(byte resetPin, byte interruptPin, byte defaultFunction)
/*
* Starts the Si473X device.
* Use this setup if you are not using interrupt resource
*
* @param byte resetPin Digital Arduino Pin used to RESET command
* @param byte defaultFunction
*/
void SI4735::setup(byte resetPin, byte defaultFunction)
#include <SI4735.h>
#define INTERRUPT_PIN 2
#define RESET_PIN 12
SI4735 si4735;
void setup()
{
si4735.setup(RESET_PIN, INTERRUPT_PIN, FM_FUNCTION);
}
/*
* Set the Power Up parameters for si473X.
* Use this method to chenge the defaul behavior of the Si473X. Use it before PowerUp()
* See Si47XX PROGRAMMING GUIDE; AN332; pages 65 and 129
* @param byte CTSIEN sets Interrupt anabled or disabled (1 = anabled and 0 = disabled )
* @param byte GPO2OEN sets GP02 Si473X pin enabled (1 = anabled and 0 = disabled )
* @param byte PATCH Used for firmware patch updates. Use it always 0 here.
* @param byte XOSCEN byte XOSCEN set external Crystal enabled or disabled
* @param byte FUNC sets the receiver function have to be used [0 = FM Receive; 1 = AM (LW/MW/SW) and SSB (if SSB patch apllied)]
* @param byte OPMODE set the kind of audio mode you want to use.
*/
void SI4735::setPowerUp(byte CTSIEN, byte GPO2OEN, byte PATCH, byte XOSCEN, byte FUNC, byte OPMODE)
/*
* Powerup in Analog Mode
* You have to call setPowerUp before call analogPowerUp.
* Use setPowerUp to select FM, AM or SSB (if SSB patch apllied) mode.
*/
void SI4735::analogPowerUp(void)
// Set the initial SI473X behavior
// CTSIEN 1 -> Interrupt anabled;
// GPO2OEN 1 -> GPO2 Output Enable;
// PATCH 0 -> Boot normally;
// XOSCEN 1 -> Use external crystal oscillator;
// FUNC defaultFunction = 0 = FM Receive; 1 = AM (LW/MW/SW) Receiver.
// OPMODE SI473X_ANALOG_AUDIO = 00000101 = Analog audio outputs (LOUT/ROUT).
setPowerUp(1, 1, 0, 1, defaultFunction, SI473X_ANALOG_AUDIO);
analogPowerUp();
/*
* Moves the device from powerup to powerdown mode.
* After Power Down command, only the Power Up command is accepted.
*/
void SI4735::powerDown(void)
/*
* Set the frequency to the corrent function of the Si4735 (AM or FM)
* You have to call setup or setPowerUp before call setFrequency.
*
* @param unsigned freq Is the frequency to change. For example, FM => 10390 = 103.9 MHz; AM => 810 = 810 KHz.
*/
void SI4735::setFrequency(unsigned freq)
si4735.setFM();
si4735.setFrequency(fm_freq);
showStatus(fm_freq,"MHz");
/*
* Increments the current frequency on current band/function by using the current step.
* See setFrequencyStep
*/
void SI4735::frequencyUp()
/*
* Decrements the current frequency on current band/function by using the current step.
* See setFrequencyStep
*/
void SI4735::frequencyDown()
/*
* Selects the tuning capacitor value.
* For FM, Antenna Tuning Capacitor is valid only when using TXO/LPI pin as the antenna input.
* See Si47XX PROGRAMMING GUIDE; AN332; pages 71 and 136
*
* @param capacitor If zero, the tuning capacitor value is selected automatically.
* If the value is set to anything other than 0:
* AM - the tuning capacitance is manually set as 95 fF x ANTCAP + 7 pF. ANTCAP manual range is 1–6143;
* FM - the valid range is 0 to 191.
* According to Silicon Labs, automatic capacitor tuning is recommended (value 0).
*/
void SI4735::setTuneFrequencyAntennaCapacitor(unsigned capacitor)
/*
* If set, executes fast and invalidated tune. The tune status will not be accurate
* @param FAST if 1 executes fast and invalidated tune. Defult value is 0.
*/
inline void setTuneFrequencyFast(byte FAST)
/*
* Freeze Metrics During Alternate Frequency Jump. Only used on FM.
*/
inline void setTuneFrequencyFreeze(byte FREEZE)
/*
* Look for a station
* See Si47XX PROGRAMMING GUIDE; AN332; page 72
*
* @param SEEKUP Seek Up/Down. Determines the direction of the search, either UP = 1, or DOWN = 0.
* @param Wrap/Halt. Determines whether the seek should Wrap = 1, or Halt = 0 when it hits the band limit.
*/
void SI4735::seekStation(byte SEEKUP, byte WRAP)
si4735.seekStation(1,1);
/*
* Search for the next station
*/
void SI4735::seekStationUp()
/*
* Search the previous station
*/
void SI4735::seekStationDown()
/*
* Set the radio to AM function. It means: LW, MW and SW.
*/
void SI4735::setAM()
/*
* Set the radio to AM (LW/MW/SW) function.
*
* @param fromFreq minimum frequency for the band
* @param toFreq maximum frequency for the band
* @param initialFreq initial frequency
* @param step step used to go to the next channel
*/
void SI4735::setAM(unsigned fromFreq, unsigned toFreq, unsigned initialFreq, byte step)
/*
* Set the radio to FM function
*/
void SI4735::setFM()
/*
* Set the radio to FM function.
*
* @param fromFreq minimum frequency for the band
* @param toFreq maximum frequency for the band
* @param initialFreq initial frequency (default frequency)
* @param step step used to go to the next channel
*/
void SI4735::setFM(unsigned fromFreq, unsigned toFreq, unsigned initialFreq, byte step)
switch (key)
{
case 'A':
si4735.setAM();
si4735.setFrequency(am_freq);
break;
case 'F':
si4735.setFM();
si4735.setFrequency(fm_freq);
break;
.
.
.
/*
* Returns true if the radio is running FM (FM_TUNE_FREQ).
*/
bool SI4735::isCurrentTuneFM()
/*
* Set the volume level
* @param byte volume (domain: 0 - 63)
*/
void SI4735::setVolume(byte volume)
si4735.setVolume(45);
/*
* Set sound volume level Up
*/
void SI4735::volumeUp()
/*
* Set sound volume level Down
*/
void SI4735::volumeDown()
switch (key)
{
case '+':
si4735.volumeUp();
break;
case '-':
si4735.volumeDown();
break;
.
.
.
/*
* Returns the current volume level
*/
inline byte SI4735::getCurrentVolume()
Allows to query the current frequency, RSSI, SNR, multipath, and the antenna tuning capacitance value (0-191). You have to call getStatus before any method to get the information about SI4735 status
/*
* Gets the current status of the Si4735 (AM or FM)
* See Si47XX PROGRAMMING GUIDE; AN332; pages 73 (FM) and 139 (AM)
*
*/
void SI4735::getStatus()
/*
* Gets the current status of the Si4735 (AM or FM)
* See Si47XX PROGRAMMING GUIDE; AN332; pages 73 (FM) and 139 (AM)
*
* @param byte INTACK Seek/Tune Interrupt Clear. If set, clears the seek/tune complete interrupt status indicator;
* @param byte CANCEL Cancel seek. If set, aborts a seek currently in progress;
*
*/
void SI4735::getStatus(byte INTACK, byte CANCEL) {
/*
* Tune complete has been triggered (STCINT)
*/
inline bool SI4735::getTuneCompleteTriggered()
/*
* Gets Received Signal Quality Interrupt(RSQINT)
*
*/
inline bool SI4735::getSignalQualityInterrup()
/*
* Gets Radio Data System (RDS) Interrupt
*/
inline bool SI4735::getRadioDataSystemInterrupt()
/*
* Return the Error flag (true or false) of status of the least Tune or Seek
* See Si47XX PROGRAMMING GUIDE; AN332; pages 63
* @return true or false
*/
inline bool SI4735::getStatusError()
/*
* Gets the Error flag of status response
* See Si47XX PROGRAMMING GUIDE; AN332; pages 63
*/
inline bool SI4735::getStatusCTS()
/*
* Returns true if the AFC rails (AFC Rail Indicator).
*/
inline bool SI4735::getACFIndicator()
/*
* Returns true if a seek hit the band limit (WRAP = 0 in FM_START_SEEK) or
* wrapped to the original frequency (WRAP = 1).
*/
inline bool SI4735::getBandLimit()
/*
* Received Signal Strength Indicator.
* This byte contains the receive signal strength when tune is complete (dBμV).
*/
inline byte SI4735::getReceivedSignalStrengthIndicator()
/*
* SNR.
* This byte contains the SNR metric when tune is complete (dB).
*/
inline byte SI4735::getStatusSNR()
/*
* Multipath.
* This byte contains the multipath metric when tune is complete.
* Multipath indi- cator is available only for Si474x, Si4706-C30 and later and
* Si4704/05/30/31/34/35/84/85-D50 and later.
*/
inline byte SI4735::getStatusMULT()
/*
* Read Antenna Tuning Capacitor (Si4704/05/06/2x only).
* Returns a byte that contains the current antenna tuning capacitor value.
*/
inline byte SI4735::getAntennaTuningCapacitor()
/*
* Returns true if the channel is currently valid as determined by the seek/tune properties (0x1403, 0x1404, 0x1108)
* and would have been found during a Seek.
* See Si47XX PROGRAMMING GUIDE; AN332; pages 63
*/
inline bool SI4735::getStatusValid()
You have a set o methods that allowto get some information about Received Signal Quality. See Si47XX PROGRAMMING GUIDE; AN332; pages 75 and 141
/*
* Queries the status of the Received Signal Quality (RSQ) of the current channel. The methods getCurrentRSSI(), getCurrentSNR() etc,
* depend on this method. So, it have to be called first. However, this method is called internally by getFrequency(). In this case,
* you do not need to use getCurrentReceivedSignalQuality if you are using getFrequency.
* In other words, you can call getCurrentRSSI(), getCurrentSNR() etc, after call getFrequency().
*
* @param INTACK Interrupt Acknowledge; 0 = Interrupt status preserved; 1 = Clears RSQINT, SNRHINT, SNRLINT, RSSIHINT, RSSILINT
*/
void getCurrentReceivedSignalQuality(byte INTACK)
/*
* Gets current receive signal strength (0–127 dBμV).
* AM and FM
*/
inline byte SI4735::getCurrentRSSI()
/*
* Gets current SNR metric (0–127 dB).
* AM and FM
*/
inline byte SI4735::getCurrentSNR()
/*
* Returns true if RSSI Detect Low.
* AM and FM
*/
inline bool SI4735::getCurrentRssiDetectLow()
/*
* Return true if RSSI Detect High
* AM and FM
*/
inline bool SI4735::getCurrentRssiDetectHigh()
/*
* Returns true if SNR Detect Low.
*/
inline bool SI4735::getCurrentSnrDetectLow()
/*
* Returns true if SNR Detect High
*/
inline bool SI4735::getCurrentSnrDetectHigh()
/*
* Returns true if Valid Channel.
*/
inline bool SI4735::getCurrentValidChannel()
/*
* Returns true AFC (Automatic Frequency Control) Rail Indicator.
*/
inline bool SI4735::getCurrentAfcRailIndicator()
/*
* Returns true if soft mute is engaged.
*/
inline bool SI4735::getCurrentSoftMuteIndicator()
/*
* Returns the amount of stereo blend in% (100 = full stereo, 0 = full mono).
*/
inline byte SI4735::getCurrentStereoBlend()
/*
* Returns true if stereo pilot presence.
*/
inline bool SI4735::getCurrentPilot()
/*
* Returns the current multipath metric. (0 = no multipath; 100 = full multipath)
*/
inline byte SI4735::getCurrentMultipath()
/*
* Returns Signed frequency offset (kHz).
*/
inline byte SI4735::getCurrentSignedFrequencyOffset()
/*
* Returns true if Multipath Detect Low.
*/
inline bool SI4735::getCurrentMultipathDetectLow()
/*
* Returns true if Multipath Detect High
*/
inline bool SI4735::getCurrentMultipathDetectHigh()
/*
* Returns true if Blend Detect Interrupt
*/
inline bool SI4735::getCurrentBlendDetectInterrupt()
Methods to query AGC status. Returns whether the AGC is enabled or disabled and it returns the gain index. You have to call getAutomaticGainControl before isAgcEnabled and getAgcGainIndex.
/*
* Queries AGC STATUS
* See Si47XX PROGRAMMING GUIDE; AN332; For FM page 80; for AM page 142.
* See AN332 REV 0.8 Universal Programming Guide Amendment for SI4735-D60 SSB and NBFM patches; page 18.
* After call this method, you can call isAgcEnabled to know the AGC status and getAgcGainIndex to know the gain index value.
*/
void SI4735::getAutomaticGainControl()
/*
* Returns true if the AGC is enabled
*/
inline bool isAgcEnabled()
/*
* Returns the current AGC gain index.
*/
inline byte getAgcGainIndex()
/*
* If FM, overrides AGC setting by disabling the AGC and forcing the LNA to have a certain gain that ranges between 0
* (minimum attenuation) and 26 (maximum attenuation);
* If AM/SSB, Overrides the AM AGC setting by disabling the AGC and forcing the gain index that ranges between 0
* (minimum attenuation) and 37+ATTN_BACKUP (maximum attenuation);
*
* @param byte AGCDIS This param selects whether the AGC is enabled or disabled (0 = AGC enabled; 1 = AGC disabled);
* @param byte AGCDX AGC Index (0 = Minimum attenuation (max gain); 1 – 36 = Intermediate attenuation);
* > 37 - Maximum attenuation (min gain) ).
*
* See Si47XX PROGRAMMING GUIDE; AN332; For FM page 81; for AM page 143
*/
void SI4735::setAutomaticGainControl(byte AGCDIS, byte AGCDX)
Si4735 filters configuration
/*
* Selects the bandwidth of the channel filter for AM reception. The choices are 6, 4, 3, 2, 2.5, 1.8, or 1 (kHz).
* The default bandwidth is 2 kHz.
* Works only in AM / SSB (LW/MW/SW)
* @param AMCHFLT the choices are: 0 = 6 kHz Bandwidth;
* 1 = 4 kHz Bandwidth;
* 2 = 3 kHz Bandwidth;
* 3 = 2 kHz Bandwidth;
* 4 = 1 kHz Bandwidth;
* 5 = 1.8 kHz Bandwidth;
* 6 = 2.5 kHz Bandwidth.
* @param AMPLFLT Enables the AM Power Line Noise Rejection Filter.
*/
void setBandwidth(byte AMCHFLT, byte AMPLFLT)
Allows to query the part number, chip revision, firmware revision, patch revision and component revision numbers.
/*
* Returns the final 2 digits of Part Number (HEX)
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwarePN()
/*
* Returns the Firmware Major Revision (ASCII).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwareFWMAJOR()
/*
* Returns the Firmware Minor Revision (ASCII).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwareFWMINOR()
/*
* Returns the Patch ID High Byte (HEX).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwarePATCHH()
/*
* Returns the Patch ID Low Byte (HEX).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwarePATCHL()
/*
* Returns the Component Major Revision (ASCII).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwareCMPMAJOR()
/*
* Returns the Component Minor Revision (ASCII).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66.
*/
inline byte SI4735::getFirmwareCMPMINOR()
/*
* Returns the Chip Revision (ASCII).
* See Si47XX PROGRAMMING GUIDE; AN332; page 66
*/
inline byte SI4735::getFirmwareCHIPREV()
This library implements some RDS features of the SI4735.
/*
* Configures interrupt related to RDS
* Use this method if want to use interrupt
* See Si47XX PROGRAMMING GUIDE; AN332; page 103
*
* @param RDSRECV If set, generate RDSINT when RDS FIFO has at least FM_RDS_INT_FIFO_COUNT entries.
* @param RDSSYNCLOST If set, generate RDSINT when RDS loses synchronization.
* @param RDSSYNCFOUND set, generate RDSINT when RDS gains synchronization.
* @param RDSNEWBLOCKA If set, generate an interrupt when Block A data is found or subsequently changed
* @param RDSNEWBLOCKB If set, generate an interrupt when Block B data is found or subsequently changed
*/
void SI4735::setRdsIntSource(byte RDSNEWBLOCKB, byte RDSNEWBLOCKA, byte RDSSYNCFOUND, byte RDSSYNCLOST, byte RDSRECV)
/*
* Set RDS property
*
* @param byte RDSEN RDS Processing Enable; 1 = RDS processing enabled.
* @param byte BLETHA Block Error Threshold BLOCKA.
* @param byte BLETHB Block Error Threshold BLOCKB.
* @param byte BLETHC Block Error Threshold BLOCKC.
* @param byte BLETHD Block Error Threshold BLOCKD.
*
* IMPORTANT:
* All block errors must be less than or equal the associated block error threshold
* for the group to be stored in the RDS FIFO.
* 0 = No errors.
* 1 = 1–2 bit errors detected and corrected.
* 2 = 3–5 bit errors detected and corrected.
* 3 = Uncorrectable.
* Recommended Block Error Threshold options:
* 2,2,2,2 = No group stored if any errors are uncorrected.
* 3,3,3,3 = Group stored regardless of errors.
* 0,0,0,0 = No group stored containing corrected or uncorrected errors.
* 3,2,3,3 = Group stored with corrected errors on B, regardless of errors on A, C, or D.
*/
void SI4735::setRdsConfig(byte RDSEN, byte BLETHA, byte BLETHB, byte BLETHC, byte BLETHD)
/*
* RDS COMMAND FM_RDS_STATUS
* See Si47XX PROGRAMMING GUIDE; AN332; pages 77 and 78
* @param INTACK Interrupt Acknowledge; 0 = RDSINT status preserved. 1 = Clears RDSINT.
* @param MTFIFO 0 = If FIFO not empty, read and remove oldest FIFO entry; 1 = Clear RDS Receive FIFO.
* @param STATUSONLY Determines if data should be removed from the RDS FIFO.
*/
void SI4735::getRdsStatus(byte INTACK, byte MTFIFO, byte STATUSONLY)
/*
* Gets RDS Status.
* Call getRdsStatus(byte INTACK, byte MTFIFO, byte STATUSONLY) if you want other behaviour
* same getRdsStatus(0,0,0)
*/
void SI4735::getRdsStatus()
/*
* Returns true if the number of the groups is filled.
* (1 = FIFO filled to minimum number of groups)
* You have to call getRdsStatus before.
*/
inline bool getRdsReceived()
/*
* Returns true if when the RDS synchronization status is lost (1 = Lost RDS synchronization)
* You have to call getRdsStatus before.
*/
inline bool getRdsSyncLost()
/*
* Returns true when RDS synchronization status is found (Found RDS synchronization)
* You have to call getRdsStatus before.
*/
inline bool getRdsSyncFound()
/*
* Returns true when a valid Block A data has been received.
* You have to call getRdsStatus before.
*/
inline bool getRdsNewBlockA()
/*
* Returns true when a valid Block B data has been received.
* You have to call getRdsStatus before.
*/
inline bool getRdsNewBlockB()
/*
* Returns true when RDS currently synchronized.
* You have to call getRdsStatus before.
*/
inline bool getRdsSync()
/*
* Returns true when One or more RDS groups discarded due to FIFO overrun.
* You have to call getRdsStatus before.
*/
inline bool getGroupLost()
/*
* Returns the number of groups remaining in the RDS FIFO (0 if empty).
* You have to call getRdsStatus before.
*/
inline byte getNumRdsFifoUsed()
/*
* Returns the programa type.
* Read the Block A content
*/
unsigned SI4735::getRdsPI(void)
/*
* Returns the Group Type (extracted from the Block B)
*/
unsigned SI4735::getRdsGroupType(void)
/*
* Gets the version code (extracted from the Block B)
* Returns 0=A or 1=B
*/
unsigned SI4735::getRdsVersionCode(void)
/*
* Returns the Program Type (extracted from the Block B)
*/
unsigned SI4735::getRdsProgramType(void)
/*
* Gets the RDS Text when the message is of the Group Type 2 version A
*/
String SI4735::getRdsText(void)
/*
* Gets the RDS time and date when the Group type is 4
*/
String SI4735::getRdsTime()
This library module is still under development.
This feature will work only on SI4735-D60. To use this feature, you have to apply a specific SSB patch. Importantly, Silicon Labs only provides support and documentation on this content to some customers. Also it is important to say that the functions available here have not been tested yet.
To date, I can't apply SSB patches following the very little information I have found on the internet. Due to the lack of more accurate information, my work has been using the trial and error approach. This may take some time.
If you have more information about how to apply patches on Si4735, please, let me know.
If you use a Si4735 with these patches applied, good luck.
/*
* Sets the SSB Beat Frequency Offset (BFO).
* @param offset 16-bit signed value (unit in Hz). The valid range is -16383 to +16383 Hz.
*/
void SI4735::setSsbBfo(int offset)
/*
* Set the SSB receiver mode details:
* 1) Enable or disable AFC track to carrier function for receiving normal AM signals;
* 2) Set the audio bandwidth;
* 3) Set the side band cutoff filter;
* 4) Set soft-mute based on RSSI or SNR;
* 5) Enable or disbable automatic volume control (AVC) function.
*
* See AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE; page 24
*
* @param AUDIOBW SSB Audio bandwidth; 0 = 1.2KHz (default); 1=2.2KHz; 2=3KHz; 3=4KHz; 4=500Hz; 5=1KHz.
* @param SBCUTFLT SSB side band cutoff filter for band passand low pass filter
* if 0, the band pass filter to cutoff both the unwanted side band and high frequency
* component > 2KHz of the wanted side band (default).
* @param AVC_DIVIDER set 0 for SSB mode; set 3 for SYNC mode.
* @param AVCEN SSB Automatic Volume Control (AVC) enable; 0=disable; 1=enable (default).
* @param SMUTESEL SSB Soft-mute Based on RSSI or SNR.
* @param DSP_AFCDIS DSP AFC Disable or enable; 0=SYNC MODE, AFC enable; 1=SSB MODE, AFC disable.
*/
void SI4735::setSsbConfig(byte AUDIOBW, byte SBCUTFLT, byte AVC_DIVIDER, byte AVCEN, byte SMUTESEL, byte DSP_AFCDIS)
- Silicon Labs Si4737 WB/AM/FM Stereo/RDS single-chip receiver HAL library for Arduino
- BROADCAST AM/FM/SW/LW RADIO RECEIVER
- SI47XX PROGRAMMING GUIDE
- AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE AMENDMENT FOR SI4735-D60 SSB AND NBFM PATCHES
- Installing Additional Arduino Libraries
- Specification of the radio data system (RDS) for VHF/FM sound broadcasting in the frequency range from 87,5 to 108,0 MHz
- Radio Data System
- RDS Encoder
- RDS in Europe, RBDS in the USA –What are the differences and how canreceivers cope with both systems?
- RBDS & RDS PTY Codes and Program Types
- Using RDS/RBDS with the Si4701/03