[SOLVED] Interface with I2C-bus controlled synthesizer (TSA5511)

Thanks again, bartjenniskens
I will read again about the flags for sure as i have all the datasheet in pdf.
Correct me if i am wrong but i realise that you agree with this troubleshooting that the problem is within PIC and not the TSA5511?
Last question, if i manage to read the existing PIC memory can i come back to you for advice?
Thanks in advance for your help.
Brgds
Dimis

Indeed, I would be suspicious about the PIC than I would be about the TSA5511.

Sure, but assembly is not my strongest point.

Many thanks i will keep you posted
Brgds
Dimi

Hi again, here is my latest actions.
please be informed that programming is neither my strongest point, i have purchase PICkit 3 that i have connect and using the MPLAB software after few corrective attempts i manage to read the PIC16F628A. Within i am able to see all memory partitions like Program memory, Configuration bits, EE data memory, User ID memory and Device ID memory.
It seams all are there as i found my name that was entered during previous normal operation. After read I try a Verify action and it comes with the following message.
Readingā€¦

The following memory area(s) will be read:
program memory: start address = 0x0, end address = 0x7ff
configuration memory
EEData memory
User Id Memory
Read complete

Verifyingā€¦

The following memory areas(s) will be verified:
program memory: start address = 0x0, end address = 0x7ff
configuration memory
EEData memory
User Id Memory

Verification successful.

To my opinion it seams to be OK what do you believe?
I remain.
Dimis

Hi Dimis,

Iā€™ve got a drfs06 exciter and it looks like the pic just died. Iā€™ve got an empty pic laying around, but canā€™t find the firmware. Could you read out your pic and share the firmware?
I would really appreciate your help. Thank you!

Hi bartjenniskens,

Iā€™ve got a pll fm transmitter in which the pic died. In case I canā€™t get the original firmware for the pic, could you share your .ino code so that I can build an alternative controller? I would really appreciate your help.

Thank you very much!

Off course, Iā€™ll reply with the code to set the TSA5511

1 Like

Hi bartjenniskens, I donā€™t want to look like Iā€™m impatient, but are you still gonna share your code?

Hey @lavao; Apologies for the delayed response, here is the full code. This code includes a 16x2 LCD display and 3 buttons. On the LCD the frequency and PLL Lock of the TSA5511 is shown, the buttons are used to set the frequency.

// This #include statement was automatically added by the Particle IDE.
#include <clickButton.h>

// This #include statement was automatically added by the Particle IDE.
#include <LiquidCrystal_I2C_Spark.h>

// Display settings
LiquidCrystal_I2C *lcd;

// General definations
# define button_menu_up D2
# define button_menu_set D3
# define button_menu_down D4
const int button_menu_up_Pin2 = 2;
const int button_menu_set_Pin3 = 3;
const int button_menu_down_Pin4 = 4;
ClickButton menu_up(button_menu_up_Pin2, LOW, CLICKBTN_PULLUP);
ClickButton menu_set(button_menu_set_Pin3, LOW, CLICKBTN_PULLUP);
ClickButton menu_down(button_menu_down_Pin4, LOW, CLICKBTN_PULLUP);

int function_menu_up = 0; // Button results 
int function_menu_set = 0; // Button results 
int function_menu_down = 0; // Button results 

// TSA5511 settings
# define tsa_addr_write 0x60 // normal 0xC0 but 0x60 because of 5 bits address (read wire lib why)
# define tsa_addr_read 0x60 // normal 0xC1 but 0x61 because of 5 bits address (read wire lib why)
bool readSensors = false; //Used in the loop to disable read-out when talking to the TSA5511
bool PLLWatchdog = false; //Action reading from I2C for LOCK flag at the TSA5511
uint32_t msLastMetric;
uint32_t msLastSample;
const uint32_t msSAMPLE_INTERVAL = 300; // 4 second interval

// EEPROM storage settings
int EEPROM_freq_addr = 10;

//Start freq when nothing is stored in the EEPROM
long freq = 87500000;

void setup() {
    // Setup button
    pinMode(button_menu_up, INPUT_PULLUP);
    pinMode(button_menu_set, INPUT_PULLUP);
    pinMode(button_menu_down, INPUT_PULLUP);
    
    //Setup wire and serial
    Wire.begin();        // join i2c bus (address optional for master)
    Serial.begin(115200);  // start serial for output

    // Setup LCD
    lcd = new LiquidCrystal_I2C(0x27, 16, 2);
    lcd->init();
    lcd->backlight();
    lcd->clear();
    display(0,0);
    delay(1000);

    // Initiate TSA5511
    TSAinit();
}

void loop() {

    //Read and actions on button clicks
    menu_up.Update();
    menu_set.Update();
    menu_down.Update();

    // Save click codes in LEDfunction, as click codes are reset at next Update()
    if(menu_up.clicks != 0) function_menu_up = menu_up.clicks;
    if(menu_set.clicks != 0) function_menu_set = menu_set.clicks;
    if(menu_down.clicks != 0) function_menu_down = menu_down.clicks;
    
    //UP - SINGLE click
    if(function_menu_up == 1) { 
        menu2(1); 
    };

    //DOWN - SINGLE click
    if(function_menu_down == 1) {
        menu2(2);
    };
    
    //SET - SINGLE click
    if(function_menu_set == 1) {
        menu2(0);
    }   
 
    function_menu_up = 0;
    function_menu_set = 0;
    function_menu_down = 0;

    //TSA5511 status loop
    if (PLLWatchdog == true){
        if (millis() - msLastSample >= msSAMPLE_INTERVAL){
            bool PLLLock = readPLLLockOnly();
            if (PLLLock == 1){
                // 1: TSA5511 Output port CP LOW and rest low = 0xCE + 0x00
                byte data[2];
                data[0] = 0xCE;
                data[1] = 0x24;
                Wire.beginTransmission(tsa_addr_write);
                Wire.write(data, 2);
                Wire.endTransmission();
                
                //Write frequency again.. or not
                byte datafreq[2];
                long Xtal = 3200000; //3.2Mhz crystal attached to TSA5511
                long fRef = Xtal / 512; //Reference devider
                long fDiv = freq / 8; // RF input devider
                long divider = fDiv / fRef;
                datafreq[0] = (divider & 0xFF00) >> 8;
                datafreq[1] = divider & 0x00FF;
                byte reg_addr = 0xCE;
                //byte tsa_addr = 0x60; // normal 0xC0 but 0x60 because of 5 bits address
            
                Wire.beginTransmission(tsa_addr_write);
                Wire.write(datafreq, 2);
                Wire.endTransmission();
                PLLWatchdog = false;
            }
        }
    }

}

void menu2(int menuMode){
    switch(menuMode){
        //MENU 1 - UP pushed
        case 1:
            freqSet(freq, 1);
            //menuChange = 1;
        break;
        
        //MENU 1 - DOWN pushed
        case 2:
            freqSet(freq, 2);
            //menuChange = 1;
        break;
        
        //MENU 1 - SET pushed
        case 0:
            freqSet(0,3);
            //menuChange = 0;
        break;
    }
}

void TSAinit(){
    Serial.println("## TSAinit ##");
    
    //Get last stored frequency from EEPROM
    uint16_t value;
    EEPROM.get(EEPROM_freq_addr, value);
    if(value == 0xFFFF) {
        // EEPROM was empty -> initialize default freq value
        freqStore(freq/100000);
        Serial.print("No frequency stored, storing default: ");Serial.println(freq);
    }
    Serial.print("Initializing frequency is: ");Serial.println(value);
    freq = value*100000;

    // Initialise the TSA5511 chip
    // 1: Set CP to HIGH and the rest to LOW
    // 2: Write frequency
    // 3: Start the PLL Watchdog
    
    // 1: TSA5511 Output port CP HIGH and rest low = 0xCE + 0x00
    byte data[2];
    data[0] = 0xCE;
    data[1] = 0x00;
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(data, 2);
    Wire.endTransmission();

    // 2: Write frequency
    byte datafreq[2];
    long Xtal = 3200000; //3.2Mhz crystal attached to TSA5511
    long fRef = Xtal / 512; //Reference devider
    long fDiv = freq / 8; // RF input devider
    long divider = fDiv / fRef;
    datafreq[0] = (divider & 0xFF00) >> 8;
    datafreq[1] = divider & 0x00FF;
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(datafreq, 2);
    Wire.endTransmission();

    Serial.print("write address: "); Serial.println(tsa_addr_write,HEX);
    Serial.print("data: "); Serial.print(data[0],HEX); Serial.print(" + ");  Serial.println(data[1],HEX);
    display(99,0);
    delay(300);
    
    PLLWatchdog = true;
    readSensors = true;
}

void freqSet(long freqInput, int set){
    switch(set){
        //Counts frequency up or down by pressing buttons
        case 0:
            freq = freqInput;
            freqWrite();
            display(96,0);
        break;
        case 1:
            freq = freqInput + 50000;
            if (freq == 108050000){ freq = 87500000;}
            display(97,freq);
            display(98,0);
            readSensors = false;
        break;
        case 2:
            freq = freqInput - 50000;
            if (freq == 87450000){ freq = 108000000;}
            display(97,freq);
            display(98,0);
            readSensors = false;
        break;
        case 3:
            freqWrite();
            display(96,0);
            delay(1000);
            display(3,readPLLLock());
            writeTSA5511P5down();
            readSensors = true;
        break;
    }
}

void freqWrite(){
    // 1: TSA5511 Output port CP HIGH and rest low = 0xCE + 0x00
    byte data[2];
    data[0] = 0xCE;
    data[1] = 0x00;
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(data, 2);
    Wire.endTransmission();

    // 2: Write frequency
    byte datafreq[2];
    long Xtal = 3200000; //3.2Mhz crystal attached to TSA5511
    long fRef = Xtal / 512; //Reference devider
    long fDiv = freq / 8; // RF input devider
    long divider = fDiv / fRef;
    datafreq[0] = (divider & 0xFF00) >> 8;
    datafreq[1] = divider & 0x00FF;
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(datafreq, 2);
    Wire.endTransmission();

    Serial.print("write address: "); Serial.println(tsa_addr_write,HEX);
    Serial.print("data: "); Serial.print(data[0],HEX); Serial.print(" + ");  Serial.println(data[1],HEX);
    freqStore(freq/100000);
    delay(100);

    PLLWatchdog = true;
}

void chargePump(){
    //Reset to 1100 1110
    //Reset is used before writing frequency and waiting for lock
    Serial.print("## chargepump ##");
    byte data[2];
    //TSA5511 Output port P5 high = 0xCE + 0x20
    data[0] = 0xCE; //CP high
    data[1] = 0x00; //P5 low
    
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(data, 2);
    Wire.endTransmission();

    Serial.print("write address: "); Serial.println(tsa_addr_write,HEX);
    Serial.print("data: "); Serial.print(data[0],HEX); Serial.print(" + ");  Serial.println(data[1],HEX);
    delay(100);
}

void writeTSA5511P5down(){
    byte data[2];
    //TSA5511 Output port P5 to low
    data[0] = 0xCE; //CP high
    data[1] = 0x00; //P5 low
    
    Wire.beginTransmission(tsa_addr_write);
    Wire.write(data, 2);
    Wire.endTransmission();
}

void freqStore(uint16_t value){
    //Store frequency to internal EEPROM
    EEPROM.put(EEPROM_freq_addr, value);
}

int freqRead(){
    uint16_t value;
    EEPROM.get(EEPROM_freq_addr, value);
    return value*100000;
}

int readPLLLock(){
    int bitNumber = 6;
    int readByte = 0;
    int myBit = 0;
    
    Wire.requestFrom(tsa_addr_read, 1);    // request 1 byte from slave device
    delayMicroseconds(6);

    if (Wire.available()){  // wait for all data to arrive
        readByte = Wire.read();
        //Serial.printf("%02x ", readByte);
        Serial.print(" ");
        Serial.print(readByte, HEX);
        Serial.print("-");
        myBit = (readByte >> bitNumber) & 0x01;
        Serial.println(myBit);

        if (myBit == 1){
            //Af ther LOCK
            // - CP must be 1, T1 and T0, must be 0, OS must be 1 (HEX 0xCE)
            // - P5 must be high and turns on the LOCK LED on the PCB (Pin 8 on the TSA5511) and P2 must get high (Pin 11 on TSA5511) (HEX 0x24)
            byte data[2];
            data[0] = 0xCE;
            data[1] = 0x24;
            Wire.beginTransmission(tsa_addr_write);
            Wire.write(data, 2);
            Wire.endTransmission();
            
            //Write frequency again.. or not
            byte datafreq[2];
            long Xtal = 3200000; //3.2Mhz crystal attached to the TSA5511
            long fRef = Xtal / 512; //Reference devider
            long fDiv = freq / 8; // RF input devider
            long divider = fDiv / fRef;
            datafreq[0] = (divider & 0xFF00) >> 8;
            datafreq[1] = divider & 0x00FF;
            byte reg_addr = 0xCE;
            //byte tsa_addr = 0x60; // normal 0xC0 but 0x60 because of 5 bits address
        
            Wire.beginTransmission(tsa_addr_write);
            Wire.write(datafreq, 2);
            Wire.endTransmission();
        } else {
            chargePump();
        }
    } else {
        //nothing
    }
    return myBit;
}

int readPLLLockOnly(){
    int bitNumber = 6;
    int readByte = 0;
    int myBit = 0;
    
    Wire.requestFrom(tsa_addr_read, 1);    // request 1 byte from slave device
    delayMicroseconds(6);

    if (Wire.available()){  // wait for all data to arrive
        readByte = Wire.read();
        myBit = (readByte >> bitNumber) & 0x01;
        display(3,myBit);
    }
    return myBit;
}

void display(int mode, int data) {
    switch(mode){
        //Startup TSA5511
        case 1:
            lcd->clear();
            lcd->setCursor(0,0);
            lcd->print("Initializing TSA5511");
        break;
        //frequency change 
        case 2:
            freq = data;
            freqStore(freq/100000);
            
            //Display frequency
            lcd->setCursor(0,1);
            float displFreq;
            displFreq = (float)freq / 1000000.00;
            lcd->print(displFreq);
            if (displFreq > 99.95){ lcd->setCursor(6,1); } else { lcd->setCursor(5,1); }
            lcd->print("Mhz");
        break;
        
        //PLL lock
        case 3:
            lcd->setCursor(0,1);
            lcd->print("PLL:");
            lcd->setCursor(4,1);;
            if (data == 1){
                lcd->print("yes");
            } else {
                lcd->print("no ");
            }
        break;
        
        case 4:
            lcd->setCursor(14,1);
            lcd->print(data);
        break;
        
        //Menu 1 - frequence set
        case 11:
            lcd->clear();
            lcd->setCursor(6,0);
            lcd->print("PARTICLE-FM");
            lcd->setCursor(0,1);
            lcd->print("Menu: 1 - set freq");
            lcd->setCursor(0,1);
            displFreq = (float)freq / 1000000.00;
            lcd->print(displFreq);
            if (displFreq > 99.95){ lcd->setCursor(6,1); } else { lcd->setCursor(5,1); }
            lcd->print("Mhz ");
        break;
        
        //Menu 2 - Menu set
        case 12:
            lcd->clear();
            lcd->setCursor(6,0);
            lcd->print("PARTICLE-FM");
            lcd->setCursor(0,1);
            lcd->print("Menu: 2 - set");
        break;

        //removing changed note
        case 96:
            display(99,0);
        break;

        case 97:
            lcd->clear();
            //Line 1
            lcd->setCursor(0,0);
            lcd->print("Setting freq..");
            
            //Line 2
            //Display frequency
            lcd->setCursor(0,1);
            lcd->print("Freq: ");
            lcd->setCursor(6,1);
            displFreq = (float)freq / 1000000.00;
            lcd->print(displFreq);
            if (displFreq > 99.95){ lcd->setCursor(12,1); } else { lcd->setCursor(11,1); }
            lcd->print("Mhz");
        break;
        
        //setting changed note
        case 98:
            lcd->setCursor(15,0);
            lcd->print("*");
        break;
        
        //Home screen
        case 99:
            lcd->clear();

            //Line 1
            //Display frequency
            lcd->setCursor(0,0);
            lcd->print("Freq: ");
            lcd->setCursor(6,0);
            displFreq = (float)freq / 1000000.00;
            lcd->print(displFreq);
            if (displFreq > 99.95){ lcd->setCursor(12,0); } else { lcd->setCursor(11,0); }
            lcd->print("Mhz");

            //Line 2
            lcd->setCursor(0,1);
            lcd->print("PLL:");
            lcd->setCursor(5,1);
            lcd->print(readPLLLock());
        break;    
        case 0:
            //default (sets display after boot)
            lcd->setCursor(0,0);
            lcd->print("Starting...");
            lcd->setCursor(3,1);
            lcd->print("PARTICLE-FM");
        break;
    }
}```

hello with what program is compiled, is it for arduino?

No, it is for Particle products using their toolchains.

1 Like