-
Notifications
You must be signed in to change notification settings - Fork 173
Home
This library can be freely distributed using the MIT Free Software model. Copyright (c) 2019 Ricardo Lima Caratti
Contact: pu2clr@gmail.com
There is a facebook group called Si47XX for Radio Experimenters where the purpose is exchanging experiences with projects based on Silicon Labs SI47XX IC family. You will be welcome to the group Si47XX for Radio Experimenters.
Attention:
- You might prefer read the library documentation via this URL.
- This library has been successfully tested on Arduino Pro Mini 3.3V; Arduino UNO (using voltage converter); Arduino YÚN (using voltage converter); ESP32 (LOLIN32 WEMOS); Mega 2560 (using voltage converter); Genuino Micro/Atmega32u4 (using voltage converter) and Arduino DUE.
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;
- David Kellmer (USA) for suggesting corrections on the documentation and sketches;
- WH2Q, Morikaku Gotoh, for his suggestion about Automatic Volume Control on AM mode;
- All members of the Facebook groups "Si47XX for radio experimenters" and "Si47XX para radioescutas" for the suggestions and corrections during the development of this project.
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!
This library uses the I²C communication protocol and implements most of the functions offered by Si47XX (BROADCAST AM / FM / SW / LW RADIO RECEIVER) IC family from Silicon Labs. The main features of this library are listed below.
- Open Source. It is free. You can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software. See MIT License to know more.
- Built Based on Si47XX PROGRAMMING GUIDE
- C++ Language and Object-oriented programming. You can easily extend the SI4735 class by adding more functionalities;
- Available on Arduino IDE (Manage Libraries);
- Cross-platform. You can compile and run this library on most of board available on Arduino IDE (Examples: ATtiny85, boards based on ATmega328 and ATmega-32u4, ATmega2560, 32 ARM Cortex, Arduino DUE, ESP32 and more). See Boards where this library has been successfully tested;
- Simplifies projects based on SI4735;
- I²C communication and Automatic I²C bus address detection;
- More than 100 functions implemented. You can customize almost every feature available on Si47XX family.
- RDS support(under construction...)
- 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 many platform. See Boards where this library has been successfully tested
This library can be useful to develop a cross-platform software. So far, it has been successfully tested on the architectures shown below.
The table below shows the some boards where this library has been successfully tested.
Board | Need voltage converter | I²C Pins | Used Reset Pin | Features |
---|---|---|---|---|
Arduino Pro Mini 3.3V 8MHz | No | A4 and A5 | 12 | More... |
Mega 2560 Pro | Yes | 20 and 21 | 12 | More... |
ESP WEMOS LOLIN32 | No | 21 and 22 [ˆ4] | 25 [ˆ5] | More... |
ESP32 Dev Module | No | 21 and 22 [ˆ4] | 25 [ˆ5] | More... |
Arduino UNO | Yes | A4 and A5 | 12 | More... |
Arduino Yún / ATmega-32u4 | Yes | 2 and 3 | 12 | More... |
ATtiny85 | No | 5 and 7 | 2 (D3) | More... |
Arduino DUE | No | 2 and 3 | 12 | More... |
BlueDuino 3.3V (ATmega-32u4) | No | 2 and 3 | 10 | More... |
Arduino Mini Pro | Yes | 2 and 3 | 10 | More... |
STM32F746G-DISCO | No | - | - | More... |
STM32F103 Series | No | PB6 (SCL) and PB7(SDA) | PA12 | More... |
- [ˆ4] It seams that in some ESP32 board, the I²C bus is not configured prorpelly by default. However, you can set almost any pin on ESP32 to setup I²C capabilities. All you have to do is call Wire.begin(SDA, SCL); where SDA and SCL are the ESP32 GPIO pins. The code below shows that.
- [^5] You can use the pin 12 too.
- More about ESP boards on ESPRESSOF Development Boards.
- More about BlueDuino on Seed.
- On Arduino.cc you can see the technical specification about many board.
This item shows the SI4735 Arduino Library implemantation. Here you can find the set of functions and methods that you can use to build your radio.
- Defined Data Types and Structures
-
Public Methods
- Usual methods
- setDeviceI2CAddress
- getDeviceI2CAddress
- setup
- setPowerUp
- radioPowerUp
- powerDown
- setFrequency
- frequencyUp
- frequencyDown
- setTuneFrequencyAntennaCapacitor
- setTuneFrequencyFast
- setTuneFrequencyFreeze
- isCurrentTuneFM
- seekStation
- seekStationUp
- seekStationDown
- setSeekAmLimits
- setSeekAmSpacing
- setSeekSrnThreshold
- setSeekRssiThreshold
- setAM
- setFM
- setVolume
- setAudioMute
- getVolume
- volumeUp
- volumeDown
- getCurrentVolume
- FM Stereo and mono Control
- 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
- Digital Audio
- Filters
- SI4735 Firmware Information
- RDS
- SI4735 Patch Support for Single Side Band
The goal here is separate data from code.
The Si47XX family works with many internal data that can be represented by data structure or defined data type in C/C++. These C/C++ resources have been used widely here. This aproach made the library easier to build and maintain. Each data structure created here has its reference (name of the document and page on which it was based). In other words, to make the SI47XX device easier to deal, some defined data types were created to handle byte and bits to process commands, properties and 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 AGCIDX; // 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 AGCIDX; // 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
/*
* Sets the I2C Bus Address
* @param senPin 0 - when the pin SEN (16 on SSOP version or pin 6 on QFN version) is set to low (GND - 0V)
* 1 - when the pin SEN (16 on SSOP version or pin 6 on QFN version) is set to high (+3.3V)
*
* The default value is 0x11 (senPin = 0). In this case you have to ground the pin SEN of the SI473X.
* If you want to change this address, call this function with senPin = 1
* ATTENTION:
* The parameter senPin is not the I2C bus address. It is the SEN pin setup of the schematic (eletronic circuit).
* If it is connected to the ground, call this function with senPin = 0; else senPin = 1.
* Acctually you do not need to use this function if the SEN PIN is configured to ground (GND).
*/
inline void setDeviceI2CAddress(uint16_t senPin)
/*
* Scans for two possible addresses for the Si37XX (0x11 or 0x63 )
* This function also sets the system to the found I2C bus address of Si47XX.
*
* @param uint8_t resetPin MCU Mater (Arduino) reset pin
* @return 0x11 if the SEN pin of the Si47XX is low or 0x63 if the SEN pin of
* the Si47XX is HIGH or 0x0 if error.
*
* You do not need to use this function if the SEN PIN is configured to ground (GND). The default I2C address is 0x11.
* Use this function if you do not know how the SEN pin is configured.
*/
int16_t SI4735::getDeviceI2CAddress(uint8_t resetPin)
/*
* Starts the Si473X device.
*
* @param uint8_t resetPin Digital Arduino Pin used to RESET command
* @param uint8_t interruptPin interrupt Arduino Pin (see your Arduino pinout).
* If less than 0,iterrupt disabled
* @param uint8_t defaultFunction
* @param uint8_t audioMode default is SI473X_ANALOG_AUDIO (Analog Audio).
* Use SI473X_ANALOG_AUDIO or SI473X_DIGITAL_AUDIO
*
* ATTENTION: If the audio mode parameter is not entered, analog mode will be considered.
*/
void SI4735::setup(uint8_t resetPin, int interruptPin, uint8_t defaultFunction, uint8_t audioMode = SI473X_ANALOG_AUDIO)
/*
* 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 the radio
* You have to call setPowerUp before call this method.
* Use setPowerUp to select FM, AM or SSB (if SSB patch apllied) modes and
* audio mode (Analog or Digital)
*/
void SI4735::radioPowerUp(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);
radioPowerUp();
/*
* 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 to 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 SI4735::setTuneFrequencyFast(byte FAST)
/*
* Freeze Metrics During Alternate Frequency Jump. Only used on FM.
*/
inline void SI4735::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()
/*
* Sets the bottom and top frequency of the AM band for seek. Default is 520 to 1710.
* @param uint16_t bottom - the bottom of the AM band for seek
* @param uint16_t top - the top of the AM band for seek
*/
void SI4735::setSeekAmLimits(uint16_t bottom, uint16_t top)
/*
* Selects frequency spacingfor AM seek. Default is 10 kHz spacing.
* @param uint16_t spacing - step in KHz
*/
void SI4735::setSeekAmSpacing(uint16_t spacing)
/*
* Sets the SNR threshold for a valid AM Seek/Tune.
* If the value is zero then SNR threshold is not considered when doing a seek. Default value is 5 dB.
*/
void SI4735::setSeekSrnThreshold(uint16_t value)
/*
* Sets the RSSI threshold for a valid AM Seek/Tune.
* If the value is zero then RSSI threshold is not considered when doing a seek. Default value is 25 dBμV.
*/
void SI4735::setSeekRssiThreshold(uint16_t value)
/*
* 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);
/*
* Gets the current volume level.
*/
byte SI4735::getVolume()
/*
* 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;
.
.
.
/*
* Sets the audio on or off
* @param value if true, mute the audio; if false unmute the audio.
*/
void setAudioMute( bool value)
/*
* Returns the current volume level
*/
inline byte SI4735::getCurrentVolume()
Methods to control the Stereo and Mono behaviour of the SI47XX.
/*
* Sets RSSI threshold for stereo blend (Full stereo above threshold, blend below threshold).
* To force stereo, set this to 0. To force mono, set this to 127.
* See Si47XX PROGRAMMING GUIDE; AN332; page 90.
*/
void SI4735::setFmBlendStereoThreshold(uint8_t parameter)
/*
* Sets RSSI threshold for mono blend (Full mono below threshold, blend above threshold).
* To force stereo set this to 0. To force mono set this to 127. Default value is 30 dBμV.
* See Si47XX PROGRAMMING GUIDE; AN332; page 56.
*/
void SI4735::setFmBlendMonoThreshold(uint8_t parameter)
/*
* Sets RSSI threshold for stereo blend. (Full stereo above threshold, blend below threshold.)
* To force stereo, set this to 0. To force mono, set this to 127. Default value is 49 dBμV.
* See Si47XX PROGRAMMING GUIDE; AN332; page 59.
*/
void SI4735::setFmBlendRssiStereoThreshold(uint8_t parameter)
/*
* Sets RSSI threshold for mono blend (Full mono below threshold, blend above threshold).
* To force stereo, set this to 0. To force mono, set this to 127. Default value is 30 dBμV.
* See Si47XX PROGRAMMING GUIDE; AN332; page 59.
*/
void SI4735::setFmBLendRssiMonoThreshold(uint8_t parameter)
/*
* Sets SNR threshold for stereo blend (Full stereo above threshold, blend below threshold).
* To force stereo, set this to 0. To force mono, set this to 127. Default value is 27 dB.
* See Si47XX PROGRAMMING GUIDE; AN332; page 59.
*/
void SI4735::setFmBlendSnrStereoThreshold(uint8_t parameter)
/*
* Sets SNR threshold for mono blend (Full mono below threshold, blend above threshold).
* To force stereo, set this to 0. To force mono, set this to 127. Default value is 14 dB.
* See Si47XX PROGRAMMING GUIDE; AN332; page 59.
*/
void SI4735::setFmBLendSnrMonoThreshold(uint8_t parameter)
/*
* Sets multipath threshold for stereo blend (Full stereo below threshold, blend above threshold).
* To force stereo, set this to 100. To force mono, set this to 0. Default value is 20.
* See Si47XX PROGRAMMING GUIDE; AN332; page 60.
*/
void SI4735::setFmBlendMultiPathStereoThreshold(uint8_t parameter)
/*
* Sets Multipath threshold for mono blend (Full mono above threshold, blend below threshold).
* To force stereo, set to 100. To force mono, set to 0. The default is 60.
* See Si47XX PROGRAMMING GUIDE; AN332; page 60.
*/
void SI4735::setFmBlendMultiPathMonoThreshold(uint8_t parameter)
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 frequency of the Si4735 (AM/SSB or FM)
* The method status do it an more. See getStatus below.
* See Si47XX PROGRAMMING GUIDE; AN332; pages 73 (FM) and 139 (AM)
*/
unsigned SI4735::getFrequency()
/*
* Gets the current frequency saved in memory.
* Unlike getFrequency, this method gets the current frequency recorded after the last setFrequency command.
* This method avoids bus traffic and CI processing.
* However, you can not get others status information like RSSI.
*/
unsigned SI4735::getCurrentFrequency()
/*
* 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 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 allow you to 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,
* Call this method first and then you can call getCurrentRSSI(), getCurrentSNR() etc.
*
* @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 AGCIDX 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 AGCIDX)
/*
* Sets the maximum gain for automatic volume control.
* If no parameter is sent, it will be consider 48dB.
*
* @param uint8_t gain Select a value between 12 and 192. Defaul value 48dB.
*
*/
void SI4735::setAvcAmMaxGain( uint8_t gain)
Example :
si4735.setAvcAmMaxGain(); // For 48dB gain
.
.
si4735.setAvcAmMaxGain(16); // For 16dB gain
.
.
si4735.setAvcAmMaxGain(x); // For xdB gain if x is a value between 12 ans 192.
/*
* Gets the current Automatic Volume Control Maximum gain in dB
*/
inline uint8_t getCurrentAvcAmMaxGain()
/*
* sets soft mute max attenuation for AM
* @patam uint8_t smattn if 0 disable. Default attenuation is 8dB
*/
inline void setAmSoftMuteMaxAttenuation( uint8_t smattn)
/*
* sets soft mute max attenuation for AM to 0
*/
inline void setAmSoftMuteMaxAttenuation()
/*
* Configures the digital audio output format.
* Options: DCLK edge, data format, force mono, and sample precision.
* See Si47XX PROGRAMMING GUIDE; AN332; page 195.
* @params uint8_t OSIZE Digital Output Audio Sample Precision (0=16 bits, 1=20 bits, 2=24 bits, 3=8bits).
* @params uint8_t OMONO Digital Output Mono Mode (0=Use mono/stereo blend ).
* @params uint8_t OMODE Digital Output Mode (0=I2S, 6 = Left-justified, 8 = MSB at second DCLK after DFS pulse, 12 = MSB at first DCLK after DFS pulse).
* @params uint8_t OFALL Digital Output DCLK Edge (0 = use DCLK rising edge, 1 = use DCLK falling edge)
*/
void SI4735::digitalOutputFormat(uint8_t OSIZE, uint8_t OMONO, uint8_t OMODE, uint8_t OFALL)
/*
* Enables digital audio output and configures digital audio output sample rate in samples per second (sps).
* See Si47XX PROGRAMMING GUIDE; AN332; page 196.
* @params uint16_t DOSR Digital Output Sample Rate(32–48 ksps .0 to disable digital audio output).
*/
void SI4735::digitalOutputSampleRate(uint16_t DOSR)
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. The table below shows the features that this library implements.
The RDS functions have not yet been properly tested.
Feature | Infoirmation type | Description |
---|---|---|
PTY | Program Type | PTY is a 5-bit that indicates the program type (see table below) |
PS | Program Service Name | Station name. It has eight static caharacter with the name of the station |
RT | Radiotext (under construction...) | String with up to 64 characters with additional information about the content currently being transmitted |
CT | Clock Time (under construction...) | It provides the the current clock |
The table below shows the main group types implemented by this library
Group Type | Description |
---|---|
0A | Basic information [ˆ3] |
0B | Basic information [ˆ3] |
1A | Additional information |
3A | Setup open data application |
4A | Date and time (UTC) and Offset to convert UTC to local time |
10A | Program Type Name |
15B | Basic information |
- [ˆ3] The basic information includes the Program Service Name and it has 8 characters. It should identifie just the name of the station. However, some stations might use this resource to show other kind of messages, contradicting what is established by the RDS protocol.
RDS/RBDS Code | European Program Type | North American Program Type |
---|---|---|
0 | No program definition type | No program definition type |
1 | News News | |
2 | Current affairs | Information |
3 | Information | Sport |
4 | Sport | Talk |
5 | Education | Rock |
6 | Drama | Classic Rock |
7 | Culture | Adult Hits |
8 | Science | Soft Rock |
9 | Variable | Top 40 |
10 | Popular Music (Pop) | Country Music |
11 | Rock Music | Oldies Music |
12 | Easy Listening | Soft Music |
13 | Light Classical | Nostalgia |
14 | Serious Classical | Jazz |
15 | Other Music | Classical |
16 | Weather | Rhythm & Blues Music |
17 | Finance | Soft Rhythm & Blues Music |
18 | Children’s Programs | Language |
19 | Social Affairs | Religious Music |
20 | Religion | Religious Talk |
21 | Phone-in Talk | Personality |
22 | Travel | Public |
23 | Leisure | College |
24 | Jazz Music | Not assigned |
25 | Country Music | Not assigned |
26 | National Music | Not assigned |
27 | Oldies Music Not assigned | |
28 | Folk Music | Not assigned |
29 | Documentary | Weather |
30 | Alarm Test | Emergency Test |
31 | Alarm | Emergency |
/*
* Starts the control variables for RDS.
*/
void SI4735::RdsInit()
/*
* 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()
First of all, it is important to say that the SSB patch content is not part of this library. The paches used here were made available by Mr. Vadim Afonkin on his Dropbox repository. It is important to note that the author of this library does not encourage anyone to use the SSB patches content for commercial purposes. In other words, this library only supports SSB patches, the patches themselves are not part of this library.
In this context, a patch is a piece of software used to change the behavior of the SI4735 device.
There is little information available about patching the SI4735. The following information is the understanding of the author of this project and it is not necessarily correct.
A patch is executed internally (run by internal MCU) of the device. Usually, patches are used to fixes bugs or add improvements and new features of the firmware installed in the internal ROM of the device. Patches to the SI4735 are distributed in binary form and have to be transferred to the internal RAM of the device by the host MCU (in this case Arduino boards). Since the RAM is volatile memory, the patch stored into the device gets lost when you turn off the system. Consequently, the content of the patch has to be transferred again to the device each time after turn on the system or reset the device.
I would like to thank Mr Vadim Afonkin for making available the SSBRX patches for SI4735-D60 on his Dropbox repository. On this repository you have two files, amrx_6_0_1_ssbrx_patch_full_0x9D29.csg and amrx_6_0_1_ssbrx_patch_init_0xA902.csg. It is important to know that the patch content of the original files is constant hexadecimal representation used by the language C/C++. Actally, the original files are in ASCII format (not in binary format). If you are not using C/C++ or if you want to load the files directly to the SI4735, you must convert the values to numeric value of the hexadecimal constants. For example: 0x15 = 21 (00010101); 0x16 = 22 (00010110); 0x01 = 1 (00000001); 0xFF = 255 (11111111);
ATTENTION: The author of this project does not guarantee that procedures shown here will work in your development environment. Given this, it is at your own risk to continue with the procedures suggested here. This library works with the I²C communication protocol and it is designed to apply a SSB extension PATCH to CI SI4735-D60. Once again, the author disclaims any liability for any damage this procedure may cause to your SI4735 or other devices that you are using.
/*
Call it first if you are applying a patch on SI4735.
Used to confirm if the patch is compatible with the internal device library revision.
See Si47XX PROGRAMMING GUIDE; AN332; pages 64 and 215-220.
*/
si47x_firmware_query_library SI4735::queryLibraryId()
/*
* This method can be used to prepare the device to apply SSBRX patch
* Call queryLibraryId before call this method.
* Powerup the device by issuing the POWER_UP command with FUNC = 1 (AM/SW/LW Receive)
* See Si47XX PROGRAMMING GUIDE; AN332; pages 64 and 215-220 and
* AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE AMENDMENT FOR SI4735-D60 SSB AND NBFM PATCHES; page 7.
*
* @return a struct si47x_firmware_query_library (see it in SI4735.h)
*/
void SI4735::patchPowerUp()
/*
* Transfers the content of a patch stored in a array of bytes to the SI4735 device.
* You must mount an array as shown below and know the size of that array as well.
*
* See Si47XX PROGRAMMING GUIDE; AN332; pages 64 and 215-220.
*
* It is importante to say that patches to the SI4735 are distributed in binary form and
* have to be transferred to the internal RAM of the device by the host MCU (in this case Arduino).
* Since the RAM is volatile memory, the patch stored into the device gets lost when you turn off
* the system. Consequently, the content of the patch has to be transferred again to the device
* each time after turn on the system or reset the device.
*
* The disadvantage of this approach is the amount of memory used by the patch content.
* This may limit the use of other radio functions you want implemented in Arduino.
*
* Example of content:
* const PROGMEM byte ssb_patch_content_full[] =
* { // SSB patch for whole SSBRX full download
* 0x15, 0x00, 0x0F, 0xE0, 0xF2, 0x73, 0x76, 0x2F,
* 0x16, 0x6F, 0x26, 0x1E, 0x00, 0x4B, 0x2C, 0x58,
* 0x16, 0xA3, 0x74, 0x0F, 0xE0, 0x4C, 0x36, 0xE4,
* .
* .
* .
* 0x16, 0x3B, 0x1D, 0x4A, 0xEC, 0x36, 0x28, 0xB7,
* 0x16, 0x00, 0x3A, 0x47, 0x37, 0x00, 0x00, 0x00,
* 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x29};
*
* const int size_content_full = sizeof ssb_patch_content_full;
*
* @param ssb_patch_content point to array of bytes content patch.
* @param ssb_patch_content_size array size (number of bytes). The maximum size allowed for a patch is 15856 bytes
*
* @return false if an error is found.
*/
bool SI4735::downloadPatch(byte *ssb_patch_content, unsigned ssb_patch_content_size)
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.
/*
* 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)
/*
* Sets DSP AFC disable or enable
* 0 = SYNC mode, AFC enable
* 1 = SSB mode, AFC disable
*/
void SI4735::setSSBDspAfc(byte DSP_AFCDIS)
/*
* Sets SSB Soft-mute Based on RSSI or SNR Selection:
* 0 = Soft-mute based on RSSI (default).
* 1 = Soft-mute based on SNR.
*/
void SI4735::setSSBSoftMute(byte SMUTESEL)
/*
* sets soft mute max attenuation for SSB
* @patam uint8_t smattn if 0 disable. Default attenuation is 8dB
*/
inline void setSsbSoftMuteMaxAttenuation( uint8_t smattn)
/*
* sets soft mute max attenuation for SSB to 0
*/
inline void setSsbSoftMuteMaxAttenuation()
/*
* Sets SSB Automatic Volume Control (AVC) for SSB mode
* 0 = Disable AVC.
* 1 = Enable AVC (default).
*/
void SI4735::setSSBAutomaticVolumeControl(byte AVCEN)
/*
* Sets AVC Divider
* for SSB mode, set divider = 0
* for SYNC mode, set divider = 3 Other values = not allowed.
*/
void SI4735::setSSBAvcDivider(byte AVC_DIVIDER)
/*
* Sets SBB Sideband Cutoff Filter for band pass and low pass filters:
* 0 = Band pass filter to cutoff both the unwanted side band and high frequency components > 2.0 kHz of the wanted side band. (default)
* 1 = Low pass filter to cutoff the unwanted side band.
* Other values = not allowed.
*/
void SI4735::setSBBSidebandCutoffFilter(byte SBCUTFLT)
/*
* SSB Audio Bandwidth for SSB mode
*
* 0 = 1.2 kHz low-pass filter (default)
* 1 = 2.2 kHz low-pass filter .
* 2 = 3.0 kHz low-pass filter.
* 3 = 4.0 kHz low-pass filter.
* 4 = 500 Hz band-pass filter for receiving CW signal, i.e. [250 Hz, 750 Hz]
* with center frequency at 500 Hz when USB is selected or [-250 Hz, -750 1Hz] with center
* frequency at -500Hz when LSB is selected* .
* 5 = 1 kHz band-pass filter for receiving CW signal, i.e. [500 Hz, 1500 Hz] with center
* frequency at 1 kHz when USB is selected or [-500 Hz, -1500 1 Hz] with center frequency
* at -1kHz when LSB is selected* .
* Other values = reserved.
* Note:
* If audio bandwidth selected is about 2 kHz or below, it is recommended to set SBCUTFLT[3:0] to 0
* to enable the band pass filter for better high- cut performance on the wanted side band.
* Otherwise, set it to 1.
*
* See AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE; page 24
*/
void SI4735::setSSBAudioBandwidth(byte AUDIOBW)
/*
* Set the radio to SSB (LW/MW/SW) function.
*
* See AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE; pages 13 and 14
*
* @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
* @param usblsb SSB Upper Side Band (USB) and Lower Side Band (LSB) Selection;
* value 2 (banary 10) = USB;
* value 1 (banary 01) = LSB.
*/
void SI4735::setSSB(unsigned fromFreq, unsigned toFreq, unsigned initialFreq, byte step, byte usblsb)
- 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
- Si47XX ANTENNA, SCHEMATIC, LAYOUT, AND DESIGN GUIDELINES; AN383
-
Other implementations using Si4735 and Arduino
- This is a git fork of [Michael Kennedy's]
- Arduino Si4735 radio library
- SI4735 AM & FM Receiver Shield
- Si4735 Digital AM/FM Radio Receiver
- Ryan Owens for SparkFun Electronics
- Silicon Labs Si4737 WB/AM/FM Stereo/RDS single-chip receiver HAL library for Arduino
- Enhanced Software for Elektor DSP-Radio (Si4735)
-
I²C
- Taking The Leap Off Board: An Introduction To I²C Over Long Wires
- Difference between I²C and SPI
- Issues with the I²C (Inter-IC) Bus and How to Solve Them
- I²C Manual; Application Note; AN10216-01
- IMPROVING NOISE IMMUNITY FOR SERIAL INTERFACE; A Lattice Semiconductor White Paper; July 2014
- Bus Buffers Simplify Design of Large, Noisy I²C Systems
- Common Problems In Systems
- Forums
- "Multi-Band Receiver On A Chip Controlled By Arduino" commented by Tom Nardi on Hackaday
Here you can see some experiments using this library.
- Si4735 All in One Receiver running on Arduino Pro Mini 3.3V (8MHz) and TFT Display
- Si4735 All in One Receiver with TFT Touch Screen
- Si4735 Arduino Library example. OLED Application.
- SI4735 Arduino Library and a simple FM and AM radio implementation
- SI4735 ARDUINO LIBRARY BANDWIDTH TEST
- Si4735 Arduino Library and SSB Support (Listening to a QSO on 20 meters)
- Evaluating SSB audio from the SI4735-based radio prototype
- How to "SI4735 Arduino Library and ATtiny85"
- SI4735 Arduino Library working with ATtiny85
- NE928-10A V:01 board working with "Si4735 Arduino Library"
- Si4735 Arduino Library and Blepill STM32F103
- SI4735 SSB
- All Band Radio with a Nice Interface
- SI4735 11 ALL IN ONE TEST OLED ver from jg3pup
- New HF SSB receiver made of Si4735 is done!
- SSB DSP radio (Si4735) version 5 revision 2
- Si4735 LCD版でSSBを受信
- Wefax576 via SI4735 with audio cable fldigi
- SI4735 KIT - First FM est