Si4735 Digital AM/FM Radio Receiver
General Description
The Silicon Labs Si4735 is an IC that handles complete tuner functionality from antenna input to audio output. There are many programmable options available to the programmer, such as frequency, volume, and audio output method. The Si4735 is interfaced over one of three serial connections, 2-wire, 3-wire, and SPI.
The Si4735 is newly available from sparkfun.com as an Arduino shield, but can be adapted for use in a standard breadboard.

Interfacing with mbed
The default interface for the Si4735 is over the 2-wire serial bus, which is I2C compliant. This interface was chosen because it is the default and simplifies the power-up sequence. The interface is described in detail in the programming guide.
Problem with Arduino Buffer
Be forewarned. This shield was designed for the Arduino, which runs it's IO pins at 5V logic. The Si4735 radio IC runs at 3.3V logic, so there is a level shifter buffer (74hc4050) on the data/input lines of the shield. This buffer is mostly unidirectional, and forces the shield to be used in SPI mode, which has a difficult start-up sequence. A majority of response signals from the radio IC over the I2C bus are not transmitted to the shield pins. With this buffer, no acknowledge signal was ever observed by the mbed, and no data was ever transmitted in response to read requests. However, the radio was able to send status responses back through the buffer following every write command. This oddity incorrectly led us to believe that responses to read requests were possible.
Solution for mbed
In order to fully communicate with the radio over I2C, the buffer must be removed from the shield, and the pins for the buffer's inputs and outputs must be shorted together (i.e. short the SDIO input to the SDIO output). This buffer is unnecessary for the mbed, because the mbed already runs at 3.3V logic. Refer to the Sparkfun schematic for more information about the way this buffer is connected.

Wiring Connections
The necessary wiring connections between the mbed and the Si4735 shield are listed in the table below. Remember that pull-up resistors are required for the I2C (sda, scl) lines.
| mbed Pin Label | mbed Pin | Si4735 Pin | Si4735 Pin Label |
|---|---|---|---|
| 3.3V Regulated Out | VOUT | +3.3V, 8, 12 | +3.3V, RAD_PWR, GPO1 |
| Ground | GND | 10, 2, GND (3), AREF | SEN, GPO2, Ground, AREF |
| sda | p28 | 11 | SDIO |
| scl | p27 | 13 | SCLK |
| Reset | p16 | 9 | RAD_RES |
When soldering header pins to the Si4735 shield for a breadboard, it is recommended that only the pins on the bottom left (pins 8-13, GND, and AREF) be soldered. The pin holes on the shield are custom fitted for the Arduino, and the shield will not fit into a breadboard if all of the pins are soldered. Instead, you can solder flexible jumper wires to the 4 remaining required pins (2, +3.3V, GND (2)). If an FM antenna is not available, a single wire can be soldered to the FM antenna input. The radio will get good reception from strong radio stations in this configuration.
Sample Program
The following demo sets up the Si4735 as described above with the MPR121 Capacitive Touch keypad and 16x2 character LCD display. The keypad is used to dial in the station frequency in 10s of KHz (e.g. 9-9-7 for 99.70 MHz FM), and then sent to the radio by pressing 10. The LCD display displays the current station and any frequency entry over/underflows. Here are the connections necessary for the keypad and LCD.
| mbed Pin | Keypad Pin | mbed Pin | LCD Pin |
|---|---|---|---|
| 3.3V Out | VCC | 5V Out | VCC |
| GND | GND | GND | GND, RW |
| p8 | IRQ | GND via 1K-ohm | VO |
| p9 | SDA | p21 | RS |
| p10 | SCL | p22 | E |
| p25,26,29,30 | D4:D7 |
Video Demo
Code
Here is the library for the Si4735 radio interface.
Import programSi4735
Si4735 Radio Library
Below is the code for the sample program.
main.cpp
// Georgia Tech ECE 4180
// Design Project for mbed
// Brett Berry and Brett Wilson
#include "mbed.h"
#include "mpr121.h"
#include "TextLCD.h"
#include "Si4735.h"
// Create the interrupt receiver object on pin 8
InterruptIn interrupt(p8);
// Setup the i2c bus on pins 9 and 10
I2C i2c(p9, p10);
// Setup the Mpr121:
// constructor(i2c object, i2c address of the mpr121)
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
// constructor for the TextLCD display
TextLCD lcd(p21, p22, p25, p26, p29, p30); // rs, e, d4-d7
// constructor for the Si4735 AM/FM radio
// Si4735(PinName sda, PinName scl, PinName RST_)
Si4735 radio(p28, p27, p16);
DigitalOut led(LED1);
DigitalOut led2(LED2);
// Initiallize USB serial connection for debugging
Serial pc(USBTX, USBRX); // tx, rx
// Initialize variables
int station = 0; // stores the calculation for the stn freq being entered
int next_stn = 0; // buffer for the station freq to be sent to the radio
bool stn_ready = false; // flag raised to send frequency to radio
bool rst_lcd = false; // flag to reset the LCD display and station entry variables
bool test_flag = false; // test flag for other functions not used in main function
int count = 0; // counter for the number of keys pressed to prevent overflow
float temp = 997; // temporary float for printing frequency to LCD display
int response; // store the response from the getFrequency method
// Key hit/release interrupt routine
// Warning: Keep code in interrupt to a minimum to prevent crash
void fallInterrupt() {
int key_code=0;
int i=0;
int value = mpr121.read(0x00);
value += mpr121.read(0x01)<<8;
// LED demo mod
// puts key number out to LEDs for demo
// scans mpr121 register bits in order to determine which key was pressed
for (i=0; i<12; i++) {
if (((value>>i)&0x01)==1) {
key_code = i + 1; // Add one to key_code to offset key release signal (0)
}
}
if ((key_code < 11) && (key_code>0)) { // add number to station frequency
station = 10*station + key_code - 1;
count++;
}
else if ((key_code == 11) && (count > 2)) { // enter station and send to radio
// raise station ready flag and copy station into temporary variable
next_stn = 10 * station;
stn_ready = true;
station = 0;
}
else if (key_code == 12){ // reset the lcd display and station calculation
// raise reset LCD flag
led2 = !led2;
rst_lcd = true;
test_flag = true;
}
}
int main() {
// define the interupt routine for the keypad
interrupt.fall(&fallInterrupt);
interrupt.mode(PullUp);
led = 1;
led2 = 0;
// Display the frequency info for the default frequency
// 99.70 MHz chosen as default since it's the strongest local frequency
lcd.cls();
lcd.printf("Current Station\n99.70 MHz FM\n");
// Power up the radio and initialize to default frequency
radio.begin(FM);
while(1) {
if (stn_ready) { // Next station ready to be sent to radio
if ((next_stn >= 8750) && (next_stn <= 10790)) { // Screen for valid FM frequencies
radio.tuneFrequency(next_stn); // Send station to radio
// tuneFrequency command sends frequency in 10s of KHz
temp = float(next_stn)/100.0; // Calculate freq float in MHz
lcd.cls(); // clear LCD screen
// display new station frequency information on LCD
lcd.printf("Current Station\n%3.2f MHz FM\n", temp);
stn_ready = false; // reset stn_ready flag
count = 0; // reset key press count
}
else if (next_stn < 8750) { // Frequency lower than minimum frequency detected
lcd.cls();
lcd.printf("Station entry\nunderflow->reset"); // display error message
count = 0;
station = 0;
stn_ready = false;
}
else { // Frequency higher than maximum frequency detected
lcd.cls();
lcd.printf("Station entry\noverflow->reset\n"); // display error message
count = 0;
station = 0;
stn_ready = false;
}
}
if (count > 4) { // too many keys pressed on the keypad
lcd.cls();
lcd.printf("Station entry\noverflow->reset\n"); // display error message
count = 0;
station = 0;
}
if (rst_lcd) { // flag for resetting LCD
lcd.cls();
// Display last valid station entry
lcd.printf("Current Station\n%3.2f MHz FM\n", temp);
count = 0;
station = 0;
rst_lcd = false;
}
if (test_flag) { // flag for testing other methods
response = radio.getFrequency();
pc.printf("Current Frequency: %d\n\r", response);
//radio.seekUp();
//radio.seekDown();
//radio.mute();
//radio.unmute();
test_flag = false;
}
led = !led;
wait(.2);
}
}
2 comments on Si4735 Digital AM/FM Radio Receiver:
Please log in to post comments.

Hi Brett,
I have a quick question. I've noticed most cell phones with built-in FM radios require you to plug in headphones, which acts as an antenna. Do you how this can be done using the Si4735? Connect the antenna directly to GND (can you quickly experiment with this please? It can't hurt)? Maybe isolate the headphone's ground wire from the ground somehow?
Thanks -Frank