Going through some old electronics I discovered I had an old PCI tv card for analog TV. These are preety much useless now that DVB-T has turned TV broadcasts to a digital format. I remembered though that it had a classic FM radio tuner as well. So I hooked it up to the PC and after downloading a bunch of drivers I still couldn’t get it to work, most probably because the Win OS I was using was unsupported after so many years. So…in frustration and in lack of better things to do I decided to proceed with the following hack…

I removed the tuner module from the card. But before doing that, while it was still plugged into the powered PC, I measured the voltages on the pins between the tuner module and the PCB. My suspicion was that this module, like many others, communicate via a serial protocol. Most times the protocol is I2C, which is an “inter-chip” communication bus consisting of just clock and data lines. All chips are connected to the same I2C bus, so each device is selected by refering to it with a special address that it responds to. Compare this to the SPI protocol were no addresses are used, but the desired chip is selected with an extra pin, the “chip select” (CS) pin.

The position of the SDA, SCL lines was determined by opening the metalic cover of the tuner and making notes of the chip numbers, especially the ones close to the pins. Some of the chips noted were:

TDA9809 – Single standard multimedia IF-PLL and FM radio demodulator

(T)SA5523-1.4 GHz I2C-bus controlled multimedia synthesizer (pin3/4 are SDA,SCL)

TDA5737 – hyperband and UHF mixers/oscillators for TV and VCR 3-band tuners

TDA7040 – Low voltage PLL stereo decoder (MPX pin 8, pin 5/6 are left/right audio)

The existence of a chip capable of I2C was the guarantee that the tuner module is indeed controlled by this protocol. By following the PCB lines from SA5523 above it was relatively easy to determine what pins were connected to the tuner module and made accessible to the outside world.

The pin numbers of the tuner module were determined to be as follows. The ones marked with bold are the ones actually used for something on our project:

The pin numbers of the tuner module were determined to be as follows. The ones marked with bold are the ones actually used for something on our project:

  • (NC)
  • (NC)
  • VT (Tuning voltage readout?)
  • 5V
  • SCL – Serial CLock
  • SDA – Serial DAta
  • AS – Address Select
  • (NC)
  • Right Audio channel
  • Left Audio channel
  • 2nd IF AF
  • Video out
  • 5V
  • Multiplexed stereo + RDS etc

In order to make the tuner module usable for this project we had to establish communication with it. First we need to know what I2C address this tuner module “listens to”. For this the Raspberry PI was used which as native support for I2C.

So by hooking up the Raspberry to the tuner module and the now known I2C lines( SDA, SCL) and 5V, GND we were ready to do that. Recall that Raspberry’s GPIO section has a pair of pins specially dedicated to I2C.

There is a very useful command available through the Raspberry terminal command line called i2cdetect which allows us to discover the address of any such chip on the lines. The tuner responded with “61“!

So now that we established the address, we can continue to determine the commands that will actually place the tuner in various modes, select desired frequency etc. Beware that pin number 7 (Address Select) can be set low or high to change the tuner I2C address in case there happens to be another device using exactly this one (since they are not unique).

The master (Raspberry) is initially in master transmit mode by sending a START followed by the 7-bit address of the slave it wishes to communicate with, which is finally followed by a single bit representing whether it wishes to write (0) to or read (1) from the slave.

Example: Suppose we want to tune to 101.300 MHz. We do 101.3 + 10.7 = 112.000.
Divide this with 0.050 = 2240 or ….0x8c0 in hexadecimal.
The byte sequence to command the tuner would be:

<address><freq upper byte><freq lower byte><controlbyte1><controlbyte2>
0x61,0x08,0xC0,0x88,0xA4

The address byte 0x61 is actually shifted left to fit the write(0) bit, so 0xC2 is actually sent.

The control bytes set various things like internal mixers, stereo/mono settings etc. They were found with a bit of experimentation and consulting online documentation for similar modules.

Extra functions for FM tuner mode are :

FM Stereo/Mono toggling mode by toggling bit 2 of controlbyte 2

Mute on/off toggling by toggling bit 4 of controlbyte 2

For displaying the currently tuned frequency a 7 segment, 4 digit display is used. Internally this module is made up of a pair of 74HC595 shift registers.
Beware that this code is written for the variant with just TWO such chips for the 4 digit segments. The code required to run the FOUR chip version is different. These buttons will trigger our code on the falling edge, so to prevent spurious interrupts by noise etc each one will be pulled up by a 10k resistor.

The SPI protocol will be used to talk to this unit.

For tuning up and tuning down we need at least two buttons, I decided to add two more in order to control Stereo/Mono and Mute/Unmute functions. That is a total of 4 buttons that will be configured as interrupt driven. We could use simple polling but I decided to use interrupts.

In the tune up/down callback functions the frequency global variable will be checked that it is within bounds (87.5-108) and tuning below 87.5 will take you immediately to 108. Similarly if you surpass 108 MHz, you will find yourself at 87.5 MHz.

The left and right channel pins from the tuner will be connected to a normal 3.5mm jack (dont forget ground pin) and we will use a 3.5mm audio jack cable to feed this to an existing pair of speakers, or existing WIFI with AUX/LineIn input.

Dont forget to connect the tuner module to an external antenna, preferably an FM antenna for best reception!

Tune your favorite station now and enjoy the music!