Skip to content
Ricardo Lima Caratti edited this page Apr 7, 2020 · 16 revisions

Si4735 Library for Arduino API Documentation (Lagacy)

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.

MIT License

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.

Thanks

  • 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.

Your support is important.

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!

SI4735 Arduino Library Features

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.

  1. 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.
  2. Built Based on Si47XX PROGRAMMING GUIDE
  3. C++ Language and Object-oriented programming. You can easily extend the SI4735 class by adding more functionalities;
  4. Available on Arduino IDE (Manage Libraries);
  5. 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;
  6. Simplifies projects based on SI4735;
  7. I²C communication and Automatic I²C bus address detection;
  8. More than 100 functions implemented. You can customize almost every feature available on Si47XX family.
  9. RDS support(under construction...)
  10. SSB (Single Side Band) patch support

Library Installation

You can install this library on your Arduino environment using different methods. The best ways to do that are described below.

Installing via Arduino IDE

This is the easiest method to install this library.

Installing from Arduino IDE 01


Installing from Arduino IDE 02


Installing via this repository

Installing from this repository


Installing from this repository

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

See also:


Hardware Requirements and Setup

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

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.

Compatible boards

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.
  1. More about ESP boards on ESPRESSOF Development Boards.
  2. More about BlueDuino on Seed.
  3. On Arduino.cc you can see the technical specification about many board.

API Documentation

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.

API Index

Defined Data Types and Structures

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
 *****************************************************************/


/**
 * @ingroup group01
 * 
 * @brief Power Up arguments data type 
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 64 and 65
 */
typedef union {
    struct
    {
        // ARG1
        uint8_t FUNC : 4;    //!<  Function (0 = FM Receive; 1–14 = Reserved; 15 = Query Library ID)
        uint8_t XOSCEN : 1;  //!<  Crystal Oscillator Enable (0 = crystal oscillator disabled; 1 = Use crystal oscillator and and OPMODE=ANALOG AUDIO) .
        uint8_t PATCH : 1;   //!<  Patch Enable (0 = Boot normally; 1 = Copy non-volatile memory to RAM).
        uint8_t GPO2OEN : 1; //!<  GPO2 Output Enable (0 = GPO2 output disabled; 1 = GPO2 output enabled).
        uint8_t CTSIEN : 1;  //!<  CTS Interrupt Enable (0 = CTS interrupt disabled; 1 = CTS interrupt enabled).
        // ARG2
        uint8_t OPMODE; //!<  Application Setting. See page 65
    } arg; //!<  Refined powerup parameters 
    uint8_t raw[2]; //!<  Raw powerup parameters data. Same arg memory position. So, same content.
} si473x_powerup;
/**
 * @ingroup group01
 * 
 * @brief Represents how the  frequency is stored in the si4735.
 * @details It helps to convert frequency in uint16_t to two bytes (uint8_t) (FREQL and FREQH)  
 */
typedef union {
    struct
    {
        uint8_t FREQL; //!<  Tune Frequency Low byte.
        uint8_t FREQH; //!<  Tune Frequency High byte.
    } raw;             //!<  Raw data that represents the frequency stored in the Si47XX device.
    uint16_t value; //!<  frequency (integer value)
} si47x_frequency;
/**
 * @ingroup group01
 * @brief Antenna Tuning Capacitor data type manupulation 
 */
typedef union {
    struct
    {
        uint8_t ANTCAPL; //!<  Antenna Tuning Capacitor High byte
        uint8_t ANTCAPH; //!<  Antenna Tuning Capacitor Low byte
    } raw;
    uint16_t value;
} si47x_antenna_capacitor;
/**
 * @ingroup group01
 * 
 * @brief AM Tune frequency data type command (AM_TUNE_FREQ command)
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 135
 */
typedef union {
    struct
    {
        uint8_t FAST : 1;   //!<  ARG1 - FAST Tuning. If set, executes fast and invalidated tune. The tune status will not be accurate.
        uint8_t FREEZE : 1; //!<  Valid only for FM (Must be 0 to AM)
        uint8_t DUMMY1 : 4; //!<  Always set 0
        uint8_t USBLSB : 2; //!<  SSB Upper Side Band (USB) and Lower Side Band (LSB) Selection. 10 = USB is selected; 01 = LSB is selected.
        uint8_t FREQH;      //!<  ARG2 - Tune Frequency High byte.
        uint8_t FREQL;      //!<  ARG3 - Tune Frequency Low byte.
        uint8_t ANTCAPH;    //!<  ARG4 - Antenna Tuning Capacitor High byte.
        uint8_t ANTCAPL;    //!<  ARG5 - Antenna Tuning Capacitor Low byte. Note used for FM.
    } arg;
    uint8_t raw[5];
} si47x_set_frequency;
/** 
 * @ingroup group01 
 * 
 * @brief Seek frequency (automatic tuning)
 * 
 * @details Represents searching for a valid frequency data type.
 */
typedef union {
    struct
    {
        uint8_t RESERVED1 : 2;
        uint8_t WRAP : 1;   //!<  Determines whether the seek should Wrap = 1, or Halt = 0 when it hits the band limit.
        uint8_t SEEKUP : 1; //!<  Determines the direction of the search, either UP = 1, or DOWN = 0.
        uint8_t RESERVED2 : 4;
    } arg;
    uint8_t raw;
} si47x_seek;
/**  
 * @ingroup group01
 * 
 * @brief Response status command 
 * 
 * @details Response data from a query status command
 * 
 * @see Si47XX PROGRAMMING GUIDE; pages 73 and 
 */
typedef union {
    struct
    {
        // Status
        uint8_t STCINT : 1; //!<  Seek/Tune Complete Interrupt; 1 = Tune complete has been triggered.
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1; //!<  Radio Data System (RDS) Interrup; 0 = interrupt has not been triggered.
        uint8_t RSQINT : 1; //!<  Received Signal Quality Interrupt; 0 = interrupt has not been triggered.
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1; //!<  Error. 0 = No error 1 = Error
        uint8_t CTS : 1; //!<  Clear to Send.
        // RESP1
        uint8_t VALID : 1; //!<  Valid Channel
        uint8_t AFCRL : 1; //!<  AFC Rail Indicator
        uint8_t DUMMY3 : 5;
        uint8_t BLTF : 1; //!<  Reports if a seek hit the band limit
        // RESP2
        uint8_t READFREQH; //!<  Read Frequency High byte.
        // RESP3
        uint8_t READFREQL; //!<  Read Frequency Low byte.
        // RESP4
        uint8_t RSSI; //!<  Received Signal Strength Indicator (dBμV)
        // RESP5
        uint8_t SNR; //!<  This byte contains the SNR metric when tune is complete (dB).
        // RESP6
        uint8_t MULT; //!<  Contains the multipath metric when tune is complete
        // RESP7
        uint8_t READANTCAP; //!<  Contains the current antenna tuning capacitor value
    } resp;
    uint8_t raw[8]; //!<  Check it
} si47x_response_status;
/**
 * @ingroup group01
 * 
 * @brief Data representation for  Firmware Information (GET_REV)
 * 
 * @details The part number, chip revision, firmware revision, patch revision and component revision numbers. 
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 66 and 131 
 */
typedef union {
    struct
    {
        // status ("RESP0")
        uint8_t STCINT : 1;
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1;
        uint8_t RSQINT : 1;
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1;
        uint8_t CTS : 1;
        uint8_t PN;       //!<  RESP1 - Final 2 digits of Part Number (HEX).
        uint8_t FWMAJOR;  //!<  RESP2 - Firmware Major Revision (ASCII).
        uint8_t FWMINOR;  //!<  RESP3 - Firmware Minor Revision (ASCII).
        uint8_t PATCHH;   //!<  RESP4 - Patch ID High byte (HEX).
        uint8_t PATCHL;   //!<  RESP5 - Patch ID Low byte (HEX).
        uint8_t CMPMAJOR; //!<  RESP6 - Component Major Revision (ASCII).
        uint8_t CMPMINOR; //!<  RESP7 - Component Minor Revision (ASCII).
        uint8_t CHIPREV;  //!<  RESP8 - Chip Revision (ASCII).
        // RESP9 to RESP15 not used
    } resp;
    uint8_t raw[9];
} si47x_firmware_information;
/**
 * @ingroup group01
 * 
 * @brief Firmware Query Library ID response. 
 * 
 * @details Used to represent the response of a power up command with FUNC = 15 (patch)
 * 
 * To confirm that the patch is compatible with the internal device library revision, the library 
 * revision should be confirmed by issuing the POWER_UP command with Function = 15 (query library ID)
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; page 12 
 */
typedef union {
    struct
    {
        // status ("RESP0")
        uint8_t STCINT : 1;
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1;
        uint8_t RSQINT : 1;
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1;
        uint8_t CTS : 1;
        uint8_t PN;        //!<  RESP1 - Final 2 digits of Part Number (HEX).
        uint8_t FWMAJOR;   //!<  RESP2 - Firmware Major Revision (ASCII).
        uint8_t FWMINOR;   //!<  RESP3 - Firmware Minor Revision (ASCII).
        uint8_t RESERVED1; //!<  RESP4 - Reserved, various values.
        uint8_t RESERVED2; //!<  RESP5 - Reserved, various values.
        uint8_t CHIPREV;   //!<  RESP6 - Chip Revision (ASCII).
        uint8_t LIBRARYID; //!<  RESP7 - Library Revision (HEX).
        // RESP9 to RESP15 not used
    } resp;
    uint8_t raw[8];
} si47x_firmware_query_library;
/**
 * @ingroup group01
 * 
 * @brief Seek station status
 * 
 * @details 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
    {
        uint8_t INTACK : 1; //!<  If set, clears the seek/tune complete interrupt status indicator.
        uint8_t CANCEL : 1; //!<  If set, aborts a seek currently in progress.
        uint8_t RESERVED2 : 6;
    } arg;
    uint8_t raw;
} si47x_tune_status;
/**
 * @ingroup group01
 * 
 * @brief Data type to deal with SET_PROPERTY command
 * 
 * @details Property Data type (help to deal with SET_PROPERTY command on si473X)
 */
typedef union {
    struct
    {
        uint8_t byteLow;
        uint8_t byteHigh;
    } raw;
    uint16_t value;
} si47x_property;
/** @defgroup group02 RDS Data types */
/** @section group02 RDS Data types */

/** 
 * @ingroup group02
 * 
 * @brief  Radio Signal Quality data representation 
 * 
 * @details 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")
        uint8_t STCINT : 1;
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1;
        uint8_t RSQINT : 1;
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1;
        uint8_t CTS : 1;
        // RESP1
        uint8_t RSSIILINT : 1; //!<  RSSI Detect Low.
        uint8_t RSSIHINT : 1;  //!<  RSSI Detect High.
        uint8_t SNRLINT : 1;   //!<  SNR Detect Low.
        uint8_t SNRHINT : 1;   //!<  SNR Detect High.
        uint8_t MULTLINT : 1;  //!<  Multipath Detect Low
        uint8_t MULTHINT : 1;  //!<  Multipath Detect High
        uint8_t DUMMY3 : 1;
        uint8_t BLENDINT : 1; //!<  Blend Detect Interrupt.
        // RESP2
        uint8_t VALID : 1; //!<  Valid Channel.
        uint8_t AFCRL : 1; //!<  AFC Rail Indicator.
        uint8_t DUMMY4 : 1;
        uint8_t SMUTE : 1; //!<  Soft Mute Indicator. Indicates soft mute is engaged.
        uint8_t DUMMY5 : 4;
        // RESP3
        uint8_t STBLEND : 7; //!<  Indicates amount of stereo blend in% (100 = full stereo, 0 = full mono).
        uint8_t PILOT : 1;   //!<  Indicates stereo pilot presence.
        // RESP4 to RESP7
        uint8_t RSSI;    //!<  RESP4 - Contains the current receive signal strength (0–127 dBμV).
        uint8_t SNR;     //!<  RESP5 - Contains the current SNR metric (0–127 dB).
        uint8_t MULT;    //!<  RESP6 - Contains the current multipath metric. (0 = no multipath; 100 = full multipath)
        uint8_t FREQOFF; //!<  RESP7 - Signed frequency offset (kHz).
    } resp;
    uint8_t raw[8];
} si47x_rqs_status;
/**
 * @ingroup group02
 * 
 * @brief Data type for RDS Status command and response information 
 *
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 77 and 78 
 * @see Also https://en.wikipedia.org/wiki/Radio_Data_System
 */
typedef union {
    struct
    {
        uint8_t INTACK : 1;     // Interrupt Acknowledge; 0 = RDSINT status preserved; 1 = Clears RDSINT.
        uint8_t MTFIFO : 1;     // Empty FIFO; 0 = If FIFO not empty; 1 = Clear RDS Receive FIFO.
        uint8_t STATUSONLY : 1; // Determines if data should be removed from the RDS FIFO.
        uint8_t dummy : 5;
    } arg;
    uint8_t raw;
} si47x_rds_command;
/**
 * @ingroup group02
 * 
 * @brief Response data type for current channel and reads an entry from the RDS FIFO.
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 77 and 78
 */
typedef union {
    struct
    {
        // status ("RESP0")
        uint8_t STCINT : 1;
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1;
        uint8_t RSQINT : 1;
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1;
        uint8_t CTS : 1;
        // RESP1
        uint8_t RDSRECV : 1;      //!<  RDS Received; 1 = FIFO filled to minimum number of groups set by RDSFIFOCNT.
        uint8_t RDSSYNCLOST : 1;  //!<  RDS Sync Lost; 1 = Lost RDS synchronization.
        uint8_t RDSSYNCFOUND : 1; //!<  RDS Sync Found; 1 = Found RDS synchronization.
        uint8_t DUMMY3 : 1;
        uint8_t RDSNEWBLOCKA : 1; //!<  RDS New Block A; 1 = Valid Block A data has been received.
        uint8_t RDSNEWBLOCKB : 1; //!<  RDS New Block B; 1 = Valid Block B data has been received.
        uint8_t DUMMY4 : 2;
        // RESP2
        uint8_t RDSSYNC : 1; //!<  RDS Sync; 1 = RDS currently synchronized.
        uint8_t DUMMY5 : 1;
        uint8_t GRPLOST : 1; //!<  Group Lost; 1 = One or more RDS groups discarded due to FIFO overrun.
        uint8_t DUMMY6 : 5;
        // RESP3 to RESP11
        uint8_t RDSFIFOUSED; //!<  RESP3 - RDS FIFO Used; Number of groups remaining in the RDS FIFO (0 if empty).
        uint8_t BLOCKAH;     //!<  RESP4 - RDS Block A; HIGH byte
        uint8_t BLOCKAL;     //!<  RESP5 - RDS Block A; LOW byte
        uint8_t BLOCKBH;     //!<  RESP6 - RDS Block B; HIGH byte
        uint8_t BLOCKBL;     //!<  RESP7 - RDS Block B; LOW byte
        uint8_t BLOCKCH;     //!<  RESP8 - RDS Block C; HIGH byte
        uint8_t BLOCKCL;     //!<  RESP9 - RDS Block C; LOW byte
        uint8_t BLOCKDH;     //!<  RESP10 - RDS Block D; HIGH byte
        uint8_t 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.
        uint8_t BLED : 2;
        uint8_t BLEC : 2;
        uint8_t BLEB : 2;
        uint8_t BLEA : 2;
    } resp;
    uint8_t raw[13];
} si47x_rds_status;
/**
 * @ingroup group02
 * 
 * @brief FM_RDS_INT_SOURCE property data type
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; page 103
 * @see also https://en.wikipedia.org/wiki/Radio_Data_System
 */
typedef union {
    struct
    {
        uint8_t RDSRECV : 1;      //!<  If set, generate RDSINT when RDS FIFO has at least FM_RDS_INT_FIFO_COUNT entries.
        uint8_t RDSSYNCLOST : 1;  //!<  If set, generate RDSINT when RDS loses synchronization.
        uint8_t RDSSYNCFOUND : 1; //!<  f set, generate RDSINT when RDS gains synchronization.
        uint8_t DUMMY1 : 1;       //!<  Always write to 0.
        uint8_t RDSNEWBLOCKA : 1; //!<  If set, generate an interrupt when Block A data is found or subsequently changed
        uint8_t RDSNEWBLOCKB : 1; //!<  If set, generate an interrupt when Block B data is found or subsequently changed
        uint8_t DUMMY2 : 5;       //!<  Reserved - Always write to 0.
        uint8_t DUMMY3 : 5;       //!<  Reserved - Always write to 0.
    } refined;
    uint8_t raw[2];
} si47x_rds_int_source;
/**
 * @ingroup group02
 * 
 * @brief 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.
 *  
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 58 and 104 
 */
typedef union {
    struct
    {
        uint8_t RDSEN : 1; //!<  1 = RDS Processing Enable.
        uint8_t DUMMY1 : 7;
        uint8_t BLETHD : 2; //!<  Block Error Threshold BLOCKD
        uint8_t BLETHC : 2; //!<  Block Error Threshold BLOCKC.
        uint8_t BLETHB : 2; //!<  Block Error Threshold BLOCKB.
        uint8_t BLETHA : 2; //!<  Block Error Threshold BLOCKA.
    } arg;
    uint8_t raw[2];
} si47x_rds_config;
/**
 * @ingroup group02
 * 
 * @brief Block A data type
 */
typedef union {
    struct
    {
        uint16_t pi;
    } refined;
    struct
    {
        uint8_t highValue; // Most Significant uint8_t first
        uint8_t lowValue;
    } raw;
} si47x_rds_blocka;
/**
 * @ingroup group02
 * 
 * @brief Block B data type
 * 
 * @details For GCC on System-V ABI on 386-compatible (32-bit processors), the following stands:
 * 
 * 1) Bit-fields are allocated from right to left (least to most significant).
 * 2) A bit-field must entirely reside in a storage unit appropriate for its declared type.
 *    Thus a bit-field never crosses its unit boundary.
 * 3) Bit-fields may share a storage unit with other struct/union members, including members that are not bit-fields.
 *    Of course, struct members occupy different parts of the storage unit.
 * 4) Unnamed bit-fields' types do not affect the alignment of a structure or union, although individual 
 *    bit-fields' member offsets obey the alignment constraints.   
 * 
 * @see also Si47XX PROGRAMMING GUIDE; AN332; pages 78 and 79
 * @see also https://en.wikipedia.org/wiki/Radio_Data_System
 */
typedef union {
    struct
    {
        uint16_t address : 2;            // Depends on Group Type and Version codes. If 0A or 0B it is the Text Segment Address.
        uint16_t DI : 1;                 // Decoder Controll bit
        uint16_t MS : 1;                 // Music/Speech
        uint16_t TA : 1;                 // Traffic Announcement
        uint16_t programType : 5;        // PTY (Program Type) code
        uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
        uint16_t versionCode : 1;        // (B0) => 0=A; 1=B
        uint16_t groupType : 4;          // Group Type code.
    } group0;
    struct
    {
        uint16_t address : 4;            // Depends on Group Type and Version codes. If 2A or 2B it is the Text Segment Address.
        uint16_t textABFlag : 1;         // Do something if it chanhes from binary "0" to binary "1" or vice-versa
        uint16_t programType : 5;        // PTY (Program Type) code
        uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
        uint16_t versionCode : 1;        // (B0) => 0=A; 1=B
        uint16_t groupType : 4;          // Group Type code.
    } group2;
    struct
    {
        uint16_t content : 4;            // Depends on Group Type and Version codes.
        uint16_t textABFlag : 1;         // Do something if it chanhes from binary "0" to binary "1" or vice-versa
        uint16_t programType : 5;        // PTY (Program Type) code
        uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
        uint16_t versionCode : 1;        // (B0) => 0=A; 1=B
        uint16_t groupType : 4;          // Group Type code.
    } refined;
    struct
    {
        uint8_t lowValue;
        uint8_t highValue; // Most Significant byte first
    } raw;
} si47x_rds_blockb;
/**
 * @ingroup group02
 * 
 * Group type 4A ( RDS Date and Time)
 * When group type 4A is used by the station, it shall be transmitted every minute according to EN 50067.
 * This Structure uses blocks 2,3 and 5 (B,C,D)
 * 
 * ATTENTION: 
 * To make it compatible with 8, 16 and 32 bits platforms and avoid Crosses boundary, it was necessary to
 * split minute and hour representation. 
 */
typedef union {
    struct
    {
        uint8_t offset : 5;       // Local Time Offset
        uint8_t offset_sense : 1; // Local Offset Sign ( 0 = + , 1 = - )
        uint8_t minute1 : 2;      // UTC Minutes - 2 bits less significant (void “Crosses boundary”).
        uint8_t minute2 : 4;      // UTC Minutes - 4 bits  more significant  (void “Crosses boundary”)
        uint8_t hour1 : 4;        // UTC Hours - 4 bits less significant (void “Crosses boundary”)
        uint8_t hour2 : 1;        // UTC Hours - 4 bits more significant (void “Crosses boundary”)
        uint32_t mjd : 17;         // Modified Julian Day Code
    } refined;
    uint8_t raw[6];
} si47x_rds_date_time;
/** @defgroup group03 Receiver Status and Setup */
/** @section group03 Receiver Status and Setup */

/** 
 * @ingroup group03
 * 
 * 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")
        uint8_t STCINT : 1;
        uint8_t DUMMY1 : 1;
        uint8_t RDSINT : 1; // Not used for AM/SSB
        uint8_t RSQINT : 1;
        uint8_t DUMMY2 : 2;
        uint8_t ERR : 1;
        uint8_t CTS : 1;
        // RESP1
        uint8_t AGCDIS : 1; // This bit indicates if the AGC is enabled or disabled. 0 = AGC enabled; 1 = AGC disabled.
        uint8_t DUMMY : 7;
        // RESP2
        uint8_t 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;
    uint8_t raw[3];
} si47x_agc_status;
/** 
 * @ingroup group03
 * 
 * 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
        uint8_t AGCDIS : 1; // if set to 1 indicates if the AGC is disabled. 0 = AGC enabled; 1 = AGC disabled.
        uint8_t DUMMY : 7;
        // ARG2
        uint8_t AGCIDX; // AGC Index; If AMAGCDIS = 1, this byte forces the AGC gain index; 0 = Minimum attenuation (max gain)
    } arg;
    uint8_t raw[2];
} si47x_agc_overrride;
/** 
 * @ingroup group03
 * 
 * The bandwidth of the AM channel filter data type
 * AMCHFLT values: 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, gradual roll off
 *                 7–15 = Reserved (Do not use)
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; pages 125 and 151
 */
typedef union {
    struct
    {
        uint8_t AMCHFLT : 4; //!<  Selects the bandwidth of the AM channel filter.
        uint8_t DUMMY1 : 4;
        uint8_t AMPLFLT : 1; //!<  Enables the AM Power Line Noise Rejection Filter.
        uint8_t DUMMY2 : 7;
    } param;
    uint8_t raw[2];
} si47x_bandwidth_config; // AM_CHANNEL_FILTER
/** 
 * @ingroup group03
 * 
 * SSB - datatype for SSB_MODE (property 0x0101)
 * 
 * @see AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE; page 24 
 */
typedef union {
    struct
    {
        uint8_t AUDIOBW : 4;     //!<  0 = 1.2KHz (default); 1=2.2KHz; 2=3KHz; 3=4KHz; 4=500Hz; 5=1KHz
        uint8_t SBCUTFLT : 4;    //!<  SSB side band cutoff filter for band passand low pass filter
        uint8_t AVC_DIVIDER : 4; //!<  set 0 for SSB mode; set 3 for SYNC mode;
        uint8_t AVCEN : 1;       //!<  SSB Automatic Volume Control (AVC) enable; 0=disable; 1=enable (default);
        uint8_t SMUTESEL : 1;    //!<  SSB Soft-mute Based on RSSI or SNR
        uint8_t DUMMY1 : 1;      //!<  Always write 0;
        uint8_t DSP_AFCDIS : 1;  //!<  0=SYNC MODE, AFC enable; 1=SSB MODE, AFC disable.
    } param;
    uint8_t raw[2];
} si47x_ssb_mode;
/**
 * @ingroup group03
 * 
 * @brief Digital audio output format data structure (Property 0x0102. DIGITAL_OUTPUT_FORMAT).
 * 
 * @details Used to configure: DCLK edge, data format, force mono, and sample precision.
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; page 195. 
 */
typedef union {
    struct {    
        uint8_t OSIZE : 2; //!<  Digital Output Audio Sample Precision (0=16 bits, 1=20 bits, 2=24 bits, 3=8bits).
        uint8_t OMONO : 1; //!<  Digital Output Mono Mode (0=Use mono/stereo blend ).
        uint8_t OMODE : 4; //!<  Digital Output Mode (0000=I2S, 0110 = Left-justified, 1000 = MSB at second DCLK after DFS pulse, 1100 = MSB at first DCLK after DFS pulse).
        uint8_t OFALL : 1; //!<  Digital Output DCLK Edge (0 = use DCLK rising edge, 1 = use DCLK falling edge)
        uint8_t dummy : 8; //!<  Always 0.
    } refined; 
    uint16_t raw;
} si4735_digital_output_format;
/**
 * @ingroup group03
 * 
 * @brief Digital audio output sample structure (Property 0x0104. DIGITAL_OUTPUT_SAMPLE_RATE).
 * 
 * @details Used to enable digital audio output and to configure the digital audio output sample rate in samples per second (sps).
 * 
 * @see Si47XX PROGRAMMING GUIDE; AN332; page 196. 
 */
typedef struct {
    uint16_t DOSR; // Digital Output Sample Rate(32–48 ksps .0 to disable digital audio output).
} si4735_digital_output_sample_rate; // Maybe not necessary 



Public Methods

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


setDeviceI2CAddress

/*
 * 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)

getDeviceI2CAddress

/*
 * 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)

setup

/*
 * 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)

If you are not using interrupt use the setup method as shown below.

/*
 * 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)

Example of using setup

#include <SI4735.h>

#define INTERRUPT_PIN 2
#define RESET_PIN 12

SI4735 si4735;

void setup()
{
    si4735.setup(RESET_PIN, INTERRUPT_PIN, FM_FUNCTION);
}

See full example

setPowerUp

/*
 * 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)

radioPowerUp

/*
 * 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)

Example of using radioPowerUp

    // 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();

powerDown

/*
 * Moves the device from powerup to powerdown mode.
 * After Power Down command, only the Power Up command is accepted.
 */
void SI4735::powerDown(void)

setFrequency

/*
 * 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)

Example of using setFrequency

    si4735.setFM();
    si4735.setFrequency(fm_freq);
    showStatus(fm_freq,"MHz");

See full example

frequencyUp

/*
 *  Increments the current frequency on current band/function by using the current step.
 *  See setFrequencyStep
 */
void SI4735::frequencyUp()

frequencyDown

/*
 *  Decrements the current frequency on current band/function by using the current step.
 *  See setFrequencyStep
 */
void SI4735::frequencyDown()

setTuneFrequencyAntennaCapacitor

/*
 * 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)

setTuneFrequencyFast

/*
 * 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)

setTuneFrequencyFreeze

/*
 * Freeze Metrics During Alternate Frequency Jump. Only used on FM.
 */
inline void SI4735::setTuneFrequencyFreeze(byte FREEZE)

seekStation

/*
 * 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)

Example of using seekStation

    si4735.seekStation(1,1);

seekStationUp and seekStationDown

/*
 * Search for the next station
 */
void SI4735::seekStationUp()

/*
 * Search the previous station
 */
void SI4735::seekStationDown()

See full example

setSeekAmLimits

/*
 * 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)

setSeekAmSpacing

/*
 * Selects frequency spacingfor AM seek. Default is 10 kHz spacing.
 * @param uint16_t spacing - step in KHz
 */
void SI4735::setSeekAmSpacing(uint16_t spacing)

setSeekSrnThreshold

/*
 * 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)

setSeekRssiThreshold

/*
 * 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)

setAM

/*
 * Set the radio to AM function. It means: LW, MW and SW.
 */
void SI4735::setAM()
You can also use setAM with parameters as shown below
/*
 * 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)

setFM

/*
 * Set the radio to FM function
 */
void SI4735::setFM()
You can also use setFM with parameters as shown below
/*
 * 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)

Example of using setAM() and setFM()

    switch (key)
    {
    case 'A':
      si4735.setAM();
      si4735.setFrequency(am_freq);
      break;
    case 'F':
      si4735.setFM();
      si4735.setFrequency(fm_freq);
      break;
      .
      .
      .

See full example

isCurrentTuneFM

/*
 * Returns true if the radio is running FM (FM_TUNE_FREQ).
 */
bool SI4735::isCurrentTuneFM()

setVolume

/*
 * Set the volume level
 * @param byte volume (domain: 0 - 63)
 */
void SI4735::setVolume(byte volume)

Example of using setVolume()

  si4735.setVolume(45);

See full example

getVolume

/*
 * Gets the current volume level.
 */
byte SI4735::getVolume()

volumeUp

/*
 *  Set sound volume level Up   
 */
void SI4735::volumeUp()

volumeDown

/*
 *  Set sound volume level Down   
 */
void SI4735::volumeDown()

Example of using volumeUp() and volumeDown()

    switch (key)
    {
    case '+':
        si4735.volumeUp();
        break;
    case '-':
        si4735.volumeDown();
        break;
    .
    .
    .    

See full example

setAudioMute

/*
 * Sets the audio on or off
 * @param value if true, mute the audio; if false unmute the audio.
 */
void setAudioMute( bool value)

getCurrentVolume

/*
 * Returns the current volume level
 */
inline byte SI4735::getCurrentVolume()


FM Stereo and Mono Control

Methods to control the Stereo and Mono behaviour of the SI47XX.

setFmBlendStereoThreshold

/*
 * 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)

setFmBlendMonoThreshold

/*
 * 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)

setFmBlendRssiStereoThreshold

/*
 * 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)

setFmBLendRssiMonoThreshold

/*
 * 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)

setFmBlendSnrStereoThreshold

/*
 * 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)

setFmBLendSnrMonoThreshold

/*
 * 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)

setFmBlendMultiPathStereoThreshold

/*
 * 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)

setFmBlendMultiPathMonoThreshold

/*
 * 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)



SI4735 Current Status

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


getFrequency

/*
 * 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()

getCurrentFrequency

/*
 * 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()

getStatus

/*
 * 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) {

getTuneCompleteTriggered

/*
 * Tune complete has been triggered (STCINT)
 */
inline bool SI4735::getTuneCompleteTriggered()

getSignalQualityInterrup

/*
 * Gets Received Signal Quality Interrupt(RSQINT)
 *
 */
inline bool SI4735::getSignalQualityInterrup()

getRadioDataSystemInterrupt

/*
 * Gets Radio Data System (RDS) Interrupt
 */
inline bool getRadioDataSystemInterrupt()

getStatusError

/*
 * 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()

getStatusCTS

/*
 * Gets the Error flag of status response
 * See Si47XX PROGRAMMING GUIDE; AN332; pages 63
 */
inline bool SI4735::getStatusCTS()

getACFIndicator

/*
 * Returns true if the AFC rails (AFC Rail Indicator).
 */
inline bool SI4735::getACFIndicator()

getBandLimit

/*
 * 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()

getReceivedSignalStrengthIndicator

/*
 * Received Signal Strength Indicator.
 * This byte contains the receive signal strength when tune is complete (dBμV).
 */
inline byte SI4735::getReceivedSignalStrengthIndicator()

getStatusSNR

/*
 * SNR.
 * This byte contains the SNR metric when tune is complete (dB).
 */
inline byte SI4735::getStatusSNR()

getStatusMULT

/*
 * 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()

getAntennaTuningCapacitor

/*
 * Read Antenna Tuning Capacitor (Si4704/05/06/2x only).
 * Returns a byte that contains the current antenna tuning capacitor value.
 */
inline byte SI4735::getAntennaTuningCapacitor()

getStatusValid

/*
 * 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()



SI4735 Received Signal Quality

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

getCurrentReceivedSignalQuality

/*  
 * 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)

getCurrentRSSI

/*
 * Gets current receive signal strength (0–127 dBμV).
 * AM and FM
 */
inline byte SI4735::getCurrentRSSI()

getCurrentSNR

/*
 * Gets current SNR metric (0–127 dB).
 * AM and FM
 */
inline byte SI4735::getCurrentSNR()

getCurrentRssiDetectLow

/*
 * Returns true if RSSI Detect Low.
 * AM and FM
 */
inline bool SI4735::getCurrentRssiDetectLow()

getCurrentRssiDetectHigh

/*
 * Return true if RSSI Detect High
 * AM and FM
 */
inline bool SI4735::getCurrentRssiDetectHigh()

getCurrentSnrDetectLow

/*
 * Returns true if SNR Detect Low.
 */
inline bool SI4735::getCurrentSnrDetectLow()

getCurrentSnrDetectHigh

/*
 * Returns true if SNR Detect High
 */
inline bool SI4735::getCurrentSnrDetectHigh()

getCurrentValidChannel

/*
 *  Returns true if Valid Channel.
 */
inline bool SI4735::getCurrentValidChannel()

getCurrentAfcRailIndicator

/*
 *  Returns true AFC (Automatic Frequency Control) Rail Indicator.
 */
inline bool SI4735::getCurrentAfcRailIndicator()

getCurrentSoftMuteIndicator

/*
 * Returns true if soft mute is engaged.
 */
inline bool SI4735::getCurrentSoftMuteIndicator()

getCurrentStereoBlend

/*
 *  Returns the amount of stereo blend in% (100 = full stereo, 0 = full mono).
 */
inline byte SI4735::getCurrentStereoBlend()

getCurrentPilot

/*
 * Returns true if stereo pilot presence.
 */
inline bool SI4735::getCurrentPilot()

getCurrentMultipath

/*
 * Returns the current multipath metric. (0 = no multipath; 100 = full multipath)
 */
inline byte SI4735::getCurrentMultipath()

getCurrentSignedFrequencyOffset

/*
 * Returns Signed frequency offset (kHz).
 */
inline byte SI4735::getCurrentSignedFrequencyOffset()

getCurrentMultipathDetectLow

/*
 * Returns true if Multipath Detect Low.
 */
inline bool SI4735::getCurrentMultipathDetectLow()  

getCurrentMultipathDetectHigh

/*
 * Returns true if Multipath Detect High
 */
inline bool SI4735::getCurrentMultipathDetectHigh()   

getCurrentBlendDetectInterrupt

/*
 * Returns true if Blend Detect Interrupt
 */
inline bool SI4735::getCurrentBlendDetectInterrupt()  



Current AGC Status

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.

getAutomaticGainControl

/*
 * 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()

isAgcEnabled

/*
 *  Returns true if the AGC is enabled
 */
inline bool isAgcEnabled()

getAgcGainIndex

/*
 *  Returns the current AGC gain index.
 */
inline byte getAgcGainIndex()

setAutomaticGainControl

/*
 * 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)

setAvcAmMaxGain

/*
 * 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.

getCurrentAvcAmMaxGain()

/*
 * Gets the current Automatic Volume Control Maximum gain in dB
 */
inline uint8_t getCurrentAvcAmMaxGain()

setAmSoftMuteMaxAttenuation

/*
 * 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()



Digital Audio

digitalOutputFormat

/*
 * 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)

digitalOutputSampleRate

/*
 * 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)

Filters

Si4735 filters configuration

setBandwidth

/*
 * 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)



SI4735 Firmware Information

Allows to query the part number, chip revision, firmware revision, patch revision and component revision numbers.


getFirmwarePN

/*
 * Returns the final 2 digits of Part Number (HEX)
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwarePN()

getFirmwareFWMAJOR

/*
 * Returns the Firmware Major Revision (ASCII).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwareFWMAJOR()

getFirmwareFWMINOR

/*
 * Returns the Firmware Minor Revision (ASCII).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwareFWMINOR()

getFirmwarePATCHH

/*
 * Returns the Patch ID High Byte (HEX).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwarePATCHH()

getFirmwarePATCHL

/*
 * Returns the Patch ID Low Byte (HEX).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwarePATCHL()

getFirmwareCMPMAJOR

/*
 * Returns the Component Major Revision (ASCII).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwareCMPMAJOR()

getFirmwareCMPMINOR

/*
 * Returns the Component Minor Revision (ASCII).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66.
 */
inline byte SI4735::getFirmwareCMPMINOR()

getFirmwareCHIPREV

/*
 * Returns the Chip Revision (ASCII).
 * See Si47XX PROGRAMMING GUIDE; AN332; page 66
 */
inline byte SI4735::getFirmwareCHIPREV()



RDS

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.



RDS Features implemented

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 Program type description

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


RdsInit

/*
 * Starts the control variables for RDS.
 */  
void SI4735::RdsInit()

setRdsIntSource

/*
 * 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)

setRdsConfig

/*
 * 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)

getRdsStatus

/*
 * 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)
You can also use getRdsStatus with no parameters as shown below
/*
 * Gets RDS Status.
 * Call getRdsStatus(byte INTACK, byte MTFIFO, byte STATUSONLY) if you want other behaviour
 * same getRdsStatus(0,0,0)
 */
void SI4735::getRdsStatus()

getRdsReceived

/*
 * 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()       

getRdsSyncLost

/*
 * Returns true if when the RDS synchronization status is lost (1 = Lost RDS synchronization)
 * You have to call getRdsStatus before.
 */
inline bool getRdsSyncLost()  

getRdsSyncFound

/*
 * Returns true when RDS synchronization status is found (Found RDS synchronization)
 * You have to call getRdsStatus before.
 */
inline bool getRdsSyncFound()

getRdsNewBlockA

/*
 * Returns true when a valid Block A data has been received.
 * You have to call getRdsStatus before.
 */
inline bool getRdsNewBlockA()

getRdsNewBlockB

/*
 * Returns true when a valid Block B data has been received.
 * You have to call getRdsStatus before.
 */
inline bool getRdsNewBlockB()

getRdsSync

/*
 * Returns true when RDS currently synchronized.
 * You have to call getRdsStatus before.
 */
inline bool getRdsSync()

getGroupLost

/*
 * Returns true when One or more RDS groups discarded due to FIFO overrun.
 * You have to call getRdsStatus before.
 */
 inline bool getGroupLost()          

getNumRdsFifoUsed

/*
 * Returns the number of groups remaining in the RDS FIFO (0 if empty).
 * You have to call getRdsStatus before.   
 */
inline byte getNumRdsFifoUsed()

getRdsPI

/*
 * Returns the programa type.
 * Read the Block A content
 */  
unsigned SI4735::getRdsPI(void)

getRdsGroupType

/*
 * Returns the Group Type (extracted from the Block B)
 */
unsigned SI4735::getRdsGroupType(void)

getRdsVersionCode

/*
 * Gets the version code (extracted from the Block B)
 * Returns  0=A or 1=B
 */
unsigned SI4735::getRdsVersionCode(void)

getRdsProgramType

/*
 * Returns the Program Type (extracted from the Block B)
 */
unsigned SI4735::getRdsProgramType(void)

getRdsText

/*
 * Gets the RDS Text when the message is of the Group Type 2 version A
 */  
String SI4735::getRdsText(void)

getRdsTime

/*
 * Gets the RDS time and date when the Group type is 4
 */  
String SI4735::getRdsTime()


SI4735 Patch Support for Single Side Band

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.

What does SSB patch means?

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.

queryLibraryId

/*
   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()

patchPowerUp

/*
 *  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()

downloadPatch

/*
 *  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)



Single Side Band (SSB) Methods

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.

setSSBBfo

/*
 * 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)

setSSBConfig

/*
 * 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)

setSSBDspAfc

/*
 * Sets DSP AFC disable or enable
 * 0 = SYNC mode, AFC enable
 * 1 = SSB mode, AFC disable
 */
void SI4735::setSSBDspAfc(byte DSP_AFCDIS)

setSSBSoftMute

/*
 * 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)

setSsbSoftMuteMaxAttenuation

/*
 * 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()

setSSBAutomaticVolumeControl

/*
 * Sets SSB Automatic Volume Control (AVC) for SSB mode
 * 0 = Disable AVC.
 * 1 = Enable AVC (default).
 */
void SI4735::setSSBAutomaticVolumeControl(byte AVCEN)

setSSBAvcDivider

/*
 * 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)

setSBBSidebandCutoffFilter

/*
 * 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)

setSSBAudioBandwidth

/*
 * 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)

setSSB

/*
 * 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)

References

  1. Silicon Labs Si4737 WB/AM/FM Stereo/RDS single-chip receiver HAL library for Arduino
  2. BROADCAST AM/FM/SW/LW RADIO RECEIVER
  3. SI47XX PROGRAMMING GUIDE
  4. AN332 REV 0.8 UNIVERSAL PROGRAMMING GUIDE AMENDMENT FOR SI4735-D60 SSB AND NBFM PATCHES
  5. Installing Additional Arduino Libraries
  6. Specification of the radio data system (RDS) for VHF/FM sound broadcasting in the frequency range from 87,5 to 108,0 MHz
  7. Radio Data System
  8. RDS Encoder
  9. RDS in Europe, RBDS in the USA –What are the differences and how canreceivers cope with both systems?
  10. RBDS & RDS PTY Codes and Program Types
  11. Using RDS/RBDS with the Si4701/03
  12. Si47XX ANTENNA, SCHEMATIC, LAYOUT, AND DESIGN GUIDELINES; AN383
  13. Other implementations using Si4735 and Arduino
  14. I²C
  15. Forums
  16. "Multi-Band Receiver On A Chip Controlled By Arduino" commented by Tom Nardi on Hackaday

Videos

Here you can see some experiments using this library.

Project examples made by the author

Third-party projects using this library

Join us on Facebook group "Si47XX for Radio Experimenters".

 
SI47XX For Radio Listeners
Grupo Público · 36 membros
Participar do grupo
Intended for hobbyists, experimenters, hams and radio enthusiasts who use SIlicon Labs SI47XX based radios. The purpose of this group is to present an...
 
Clone this wiki locally