### TSA5523 Tuner Modules from PC TV Cards

Use tuners from PCI TV cards for video and FM radio reception with Arduino or other I2C interface

Some of the previous posts show methods of generating analog video with microcontrollers and RF modulation of it using ready made modules. Analog video is no longer in use in most parts of the world. TV tuner cards for analog signals are no longer manufactured and old ones are difficult or impossible to install on newer computers because there are no drivers. Despite this, analog video capture devices are cheap and widely available. Most are USB dongles, with video and audio inputs, no tuner.

Since I had some old TV tuner cards that were no longer compatible with my PC or had poor performance, I decided to take the tuners out of them. To my surprise, different tuners from different manufacturers looked pretty much the same on the inside. All of them used the same integrated circuits. The tuners I found are actually complete receivers, with included demodulator. This means you can get analog audio and video straight from the module pins. There are also modules with FM support, with stereo decoder.

In the photo below, you can see two tuners. The top one has FM radio support. You can see that it's similar to the other, but the rightmost compartment has some additional filters for FM IF.

 Tuners from TV cards
The tuners I got are Philips TCL2002MB-33F, LG TPI8PSB02P and LG TPI8PSB12P. The latter is TV only, with no radio support. Finding the pinout of these modules is not very hard if you analyze the board they came from. Anyway, further searching lead me to Philips FM1216, a similar tuner that uses the same ICs. Even without this, the datasheet for TSA5523 is available. This is the circuit that controls tuner frequency via I2C bus.

 Functional modules of the TV tuner
Let's take a look at how these modules work. The RF signal from antenna is split in three paths, then filtered and amplified for each of the frequency bands. There are three frequency bands. Band A is the lower half of VHF (this includes FM). Band B is the upper half of VHF and band C is UHF. For tuners with FM support, a switch connects FM antenna to band A input when FM mode is activated. The amplified and filtered signals are mixed with local oscillators. This happens inside TDA5737 IC. The PLL IC, TSA5523, samples frequency from the mixer and adjusts local oscillators. Coming out from the mixer, the selected IF signal is further amplified and filtered either by a TV SAW filter on 38.9 MHz or the FM IF filter on 10.7 MHz. Output from these filters enters TDA9809 or TDA9801 demodulator. The latter IC is TV demodulator only, while the other can demodulate FM radio too. If the tuner module has FM radio support, most probably it will have an extra IC, the TDA7040 for stereo decoding.

 Pinout of TV tuner module TCL2002MB-33F
Before writing the software for communicating with the tuner, let's see how to wire it up. Above is the pinout for the TCL2002MB-33F tuner. Other tuners may or may not have all pins. I chose this one because it has FM support, therefore some additional pins for radio audio. There is a MUTE pin. This is not present on all devices, because TSA5523 features a GPIO port that can be used for this purpose. AFC and VT pins are in the same situation. AFC is sometimes sampled by TSA5523 integrated ADC input and VT is only for checking if the tuning voltage is present and changes according to frequency. SCL, SDA and AS are I2C bus pins. FMR and FML can be found only on tuner modules with FM stereo decoder. MPX contains baseband video signal straight from the demodulator, without any filters. This can be used by to decode VBI (teletext) data. CVBS is analog video output and AF is mono TV audio output. Some claim that while in FM mode, AF carries multiplexed audio with embedded RDS data. The modules is powered from 5V. The ground connects to the metal case.

Basic connection requires SCL and SDA to be connected to an I2C interface of a microcontroller, CVBS and AF to be connected to a capture card inputs via RCA jacks. All that's left is to power up the module.

According to datasheet, I2C address of TSA5523 is 0xC2 is AS pin is left floating. The IC has 4 write registers and 1 read register. Here is an overview.

 Overview of TSA5523 registers (refer to datasheet)
Divider bytes (DB1 and DB2) set frequency of the local oscillators. CP sets chargepump current and RSA/RSB set divider ratio (tuning step). Port bits P7, P5 and P4 select frequency bands. P3 controls muting. P2 and P0 control operating mode. When both are 0 (not set), the tuner works in TV mode. Setting P0 to 1 forces power down mode for TV demodulator.  To switch to FM mode, set P2 to 1. Then if you want to read ADC input, you will get AFC when P0 is 1 and received IF when P0 is 0. P1 forces mono mode. P6 should be 0, because it is configured as ADC input.

Read register contains some important bits. FL is 1 when tuner is locked to frequency. I1 reads mono/stereo status (1 means stereo). A2, A1 and A0 represent ADC readout.

Let's write some Arduino compatible code. First, for tuning TV channels. Control byte is set to 0xCA. This means CP=1 (higher chargepump current, recommended in TV mode) and RSA=0; RSB=1 (resulting in 31.25kHz frequency step). Ports bytes is set according to the band in which the frequency fits. To set frequency of local oscillator, IF is added to receiving frequency and the sum is divided by tuning step (31.25 in this configuration). The number 1245 in freq_khz formula comes from IF frequency 38900 divided by 31.25.
#define TSA5523_ADDR (0xC2 >> 1)
// tuner registers
byte db1, db2, cb, pb;

void tsa5523_setTVFrequency(uint32_t freq_khz) {
// band bits
if (freq_khz < 168000) pb = 0xA0; // band A, VHF-Lo
else if (freq_khz < 448000) pb = 0x90; // band B, VHF-Hi
else pb = 0x30; // band C, UHF

// control
cb = 0xCA;

freq_khz = freq_khz / 31.25 + 1245;
db1 = (freq_khz >> 8) & 0x7F;
db2 = freq_khz & 0xFF;

Wire.write(db1);
Wire.write(db2);
Wire.write(cb);
Wire.write(pb);
Wire.endTransmission();
}

In FM mode, we're always in band A. Chargepump can use lower current to improve SNR (set CP=0) and tuning step needs to be 50kHz to cover all channels. RSA and RSB are both 0. Some changes are required for ports byte. Band A (which includes FM) requires P7 and P5 to be set. P2 also needs to be 1. IF frequency is 10.7MHz now. The sum is divided by 50 (tuning step).
#define TSA5523_ADDR (0xC2 >> 1)
// tuner registers
byte db1, db2, cb, pb;

void tsa5523_setFMFrequency(uint32_t freq_khz) {
pb = 0xa4; // band A only
cb = 0x88;

freq_khz += 10700;
freq_khz /= 50;
db1 = (freq_khz >> 8) & 0x7F;
db2 = freq_khz & 0xFF;

Wire.write(db1);
Wire.write(db2);
Wire.write(cb);
Wire.write(pb);
Wire.endTransmission();
}

To get tuner status, read one byte from the read address. If this status byte (SB) has bit 6 set, tuner is locked (SB & 0x40). Then you can assess bit 4 for stereo (SB & 0x10) and compute ADC readout (SB & 0x07). Note that ADC reads what you configured it with the ports byte.

Due to the capability of tuning to frequencies between 45 to 860 MHz, programming a button based user interface for Arduino is rather difficult. A future post will show a programming example of Windows application that uses CH341A to control this tuner.