FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

General discussion on mikroC PRO for PIC.
Author
Message
leo73
Posts: 252
Joined: 09 Jan 2014 15:45

FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

#1 Post by leo73 » 13 Mar 2021 20:22

FIRST VERSION OF CODE: USING I2C NATIVE REGISTERS LIBRARY DATASHEET 18F26K22 NO WORK CODE LOCKED IN FMfrequenc() IN PARTICUTAL IN My_i2c_Read() implementation function. SSP1STAT.BF Wait for ever singnal to read data from buffer :cry:
    Hello to every one,
    I want traslate one FM-Receiver AR1010 library wrote for pic 16x
    for my 18F26k22 pic.
    some progress has been made on the implemented i2c library. I was inspired by a certain source, the link is the following: https://deepbluembedded.com/i2c-communi ... orial-pic/
    subsequently I rewrote the library in a faithful way to the original in according whit 18F26k22 datascheet comparing whit 16F7x datasheet.
    now the i2c implementation is better written, but there is still something wrong!
    discution and files update to 14.Mar.2021 19.51 My_I2C_Read() changed for Master I2C

    Code: Select all

    ///////////////////// I2C IMPLEMENTATION for 18F26k22/////////////////////////
    // https://deepbluembedded.com/i2c-communication-protocol-tutorial-pic/
    // I2C MASTER
    //
    // _asm bsf LATA,1;
    // _asm bcf LATA,1;
    ///////////////////////////////////////////////////////////////////
    // OpenI2C( MASTER, SLEW_OFF);
     
    #define _XTAL_FREQ 64000000 // Fosc In this case i have set internal oscillator
                                // Int Osc 16Mhx x 4 PLL = 64Mhz
    #define I2C_BaudRate 400000 // I2C Baud Rate = 100 Kbps
    
    void OpenI2C(unsigned char, unsigned char);
    void My_I2C_Master_Init(void);
    void My_I2C_Idle(void);        //void I2C_Wait(void);
    void My_I2C_Start(void);
    void My_I2C_Stop(void);
    void My_I2C_Restart(void);
    void My_I2C_ACK(void);
    void My_I2C_NACK(void);
    unsigned char My_I2C_Write(unsigned char Data);
    unsigned char My_I2C_Read(void);
    
    void My_I2C_Master_Init(void)
    {
      SSP1CON1 = 0x28;  //Select and enable master mode WCOL SSPOV SSPEN CKP SSPM<3:0>
      SSP1CON2 = 0x00;   //GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN
      SSP1STAT = 0x00;   //SMP      CKE     D/A   P    S   R/W  UA  BF
      SSP1ADD = ((_XTAL_FREQ/4)/I2C_BaudRate) - 1;
      TRISC.B3 = 1; // scl pin.
      TRISC.B4 = 1; // SDA pin.
      SSP1CON1.SSPEN = 1; // added after
    
    }
    void My_I2C_Idle()
    {
      while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F));
    }
    void My_I2C_Start()
    {
      //---[ Initiate I2C Start Condition Sequence ]---
      My_I2C_Idle();
      SSP1CON2.SEN = 1;
    }
    void My_I2C_Stop()
    {
      //---[ Initiate I2C Stop Condition Sequence ]---
      My_I2C_Idle();
      SSP1CON2.PEN = 1;
    }
    void My_I2C_Restart()
    {
      //---[ Initiate I2C Restart Condition Sequence ]---
      My_I2C_Idle();
      SSP1CON2.RSEN = 1;
    }
    void My_I2C_ACK(void)
    {
      //---[ Send ACK - For Master Receiver Mode ]---
      My_I2C_Idle();
      SSP1CON2.ACKDT = 0; // 0 -> ACK, 1 -> NACK
      SSP1CON2.ACKEN = 1; // Send ACK Signal!
    }
    void My_I2C_NACK(void)
    {
      //---[ Send NACK - For Master Receiver Mode ]---
      My_I2C_Idle();
      SSP1CON2.ACKDT = 1; // 1 -> NACK, 0 -> ACK
      SSP1CON2.ACKEN = 1; // Send NACK Signal!
    }
    unsigned char My_I2C_Write(unsigned char Data)
    {
      //---[ Send Byte, Return The ACK/NACK ]---
      My_I2C_Idle();
      SSPBUF = Data;
      My_I2C_Idle();
      return SSP1CON2.ACKSTAT;
    }
    
    unsigned char My_I2C_Read(void){
      if((SSP1CON1 & 0x0F) == 0x08) SSP1CON2.RCEN = 1; // MASTER MODE ONLY
        while(!SSP1STAT.BF);  // WAIT UNTIL BYTE RECEIVED
        return SSP1BUF;       // RETURN WHIT READ BYTE
    }
    
    Fm.h:

    Code: Select all

    /*
       File: fm.h
       Project: LDPS IV FM Radio project
       Created: Spring 2014
       Created by: Lab group 8 - Josh Tyler, Vilma Wilke, Umair Hassan and Le Huy Hoang (based on skeletal code provided by RAC)
       Purpose: Provide constants and function definitions used by main.c
       Language: C (Complied with the XC8 compiler on MPLABX)
       Target: PIC16F84A
    */
    
    
    #define XS                        0                        // Exit success
    #define XF                        1                        // Exit fail
    
    #define FMI2CADR                0x20  // Address (for writes) of FM module on I2C bus
    
    
    #define DEVRD                   0x01       // Read not write an I2C device
    #define FMCHIPVERSADR           0x1C   //0x06 //0x1C   // Address of FM chip version
    #define FMCHIPIDADR             0x1B       // Address of FM chip ID
    #define FMCHIPSTSADR            0x13       // Address of FM chip status
    
    #define READCHAN_ADR            0x13
    
    #define FMASKMUTE               0x0001      // Register 1, bit 1
    #define FMASKTUNE               0x0200      // Register 2, bit 9
    #define FMASKSTATUS             0x0020      // Register 0x13, bit 5
    #define FMASKSEEK               0x4000      // Register 3, bit 14
    #define FMASKRDCHAN             0xFF80      // Register 2, channel number bits
    
    #define BUTN1                   0b00000001  // Button number one
    #define BUTN2                   0b00000010        // Button number two
    #define BUTN3                   0b00000100
    #define BUTN4                   0b00001000
    #define BUTN5                   0b00010000
    #define BUTN6                   0b00100000
    #define BUTN7                   0b01000000
    #define BUTN8                   0b10000000
    
    #define LCDSEGDP3                22                        // LCD segment for decimal point
    #define LCDSEGZ                 23                        // LCD segment for Z
    
    #define FREQMAX                 1080            // Maximum frequency
    #define FREQMIN                 875             // Minimum frequency
    
    #define FMHIGHCHAN                (1080-690)        // Highest FM channel number
    #define FMLOWCHAN                (875-690)
    #define FALSE                        0
    #define TRUE                        1
    // this part is not used because i not use display 7 segments
    /*
    #define LCD_3A                  0               // LCDDATA0
    #define LCD_3B                  1
    #define LCD_3C                  2
    #define LCD_3D                  3
    #define LCD_3E                  4
    #define LCD_3F                  5
    #define LCD_3G                  6
    #define LCD_DP1                 7
    #define LCD_2A                  8               // LCDDATA1
    #define LCD_2B                  9
    #define LCD_2C                  10
    #define LCD_2D                  11
    #define LCD_2E                  12
    #define LCD_2F                  13
    #define LCD_2G                  14
    #define LCD_DP2                 15
    #define LCD_1A                  16               // LCDDATA2
    #define LCD_1B                  17
    #define LCD_1C                  18
    #define LCD_1D                  19
    #define LCD_1E                  20
    #define LCD_1F                  21
    #define LCD_1G                  22
    #define LCD_DP3                 23
    #define LCD_K                   24
    #define LCD_COL                 25
    #define LCD_Z                   26
    */
    #define CHAR_DISP_DELAY         60              // Delay used for displaying text
    
    /* Masks used to clear volume bits */
    #define VOL1_MASK               0xF87F
    #define VOL2_MASK               0x0FFF
    
    /* Masks used to clear scan bits*/
    #define SCAN_REG3_MASK          0x1FFF
    #define SCAN_REG10_MASK         0xFFF7
    
    /* Recommended values for volume, obtained from data sheet, repackaged for actual location in memory */
    const int volumePair[2][19] = {            
        {0x0780, 0x0780, 0x0780, 0x0780, 0x0580, 0x0580, 0x0580, 0x0500, 0x0480, 0x0400, 0x0380, 0x0300, 0x0300, 0x0300, 0x0180, 0x0180, 0x0100, 0x0080, 0x0000} ,   /*  Values for R3  */
        {0x0000, 0xC000, 0xD000, 0xF000, 0xC000, 0xD000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xD000, 0xE000, 0xF000, 0xE000, 0xF000, 0xF000, 0xF000, 0xF000}    /*  Values for R14 */
    };
    
    const unsigned int station[6] = {875, 881, 903, 964, 1046, 1129};
    
    char stationName[6][15] = { "UNKNOWN", "BBC[TWO", "BBC[THREE", "EAGLE", "BBC[ONE", "UNKNOWN" };
    
    enum {                                                        // Global error numbers
            GERNONE,                                         // No error
            GERWCOL,                                        // I2C write collision
            GERFINT,                                        // Could not initialize FM module
            GERFMID                                                // Could not read chip ID (0x1010)
    };
    
    void Init();                                                                // Processor initialisation.
    void dly(int d);
    unsigned char butnEvent(unsigned char *butn);
    unsigned char testPinState(unsigned char oldPin, unsigned char newPin, unsigned char *butn);
    void setscn(unsigned char state);
    void segWrt(unsigned char segOrd,  unsigned char state);
    void charWrt(unsigned char numToDisp, unsigned char DigitNo);
    unsigned int manualTune(unsigned int freq, unsigned char dir);
    unsigned char FMread(unsigned char regAddr , unsigned int *data_);
    unsigned char FMwrite(unsigned char adr);                                // Write a new value to a register
    unsigned char FMinit();                                                                        // Initialise the chip
    unsigned char FMfrequenc(unsigned int f);
    unsigned char FMready(unsigned int *rdy);                                // Status is ready or busy
    unsigned char FMid(unsigned int *id);                                        // Obtain ID number
    unsigned char showFreq(unsigned int frequency);                                                // Display the current f in MHz
    unsigned char FMvers(unsigned int *vsn);                                // Obtain version number
    unsigned int volSet(unsigned int vol, unsigned char dir);
    unsigned int nextChan(unsigned int chan, unsigned char dir);
    void errfm(void);
    unsigned char showVol(unsigned int volume);
    unsigned char showChan(unsigned int channel);
    unsigned int setScan(unsigned char dir);
    int displayText(char str[], int pos);
    
    
    //
    // end receiveFM.h ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //
    //
    
    And the main: Uart1 is used to debug variable state control.

    Code: Select all

    /////////////////////////// AR1010 FR RECEIVER TEST ///////////////////////
    //         18F26K22  INTERNAL CLOCK 16MHZ X 4 PLL = 64MHZ
    // ORIGINAL PROGECT LINK : https://github.com/joshtyler/PIC-FM
    //
    // PIN OUT:
    // Encoder_SW3 -->  RA4 (pin6)   NEED TO CONNECT
    // Encoder_DT3 -->  RA3 (pin5)   NEED TO CONNECT
    // Encoder_CLK3 --> RA2 (pin4)   NEED TO CONNECT
    // AR 1010 FR RECEIVER ON I2C BUS
    // SSD 1306 OLED DISPLAY ON I2C BUS
    //
    // NOTES:
    // _asm bsf LATA,1;
    // _asm bcf LATA,1;
    //
    ///////////////////////////////////////////////////////////////////////////
    
    
    
    // SSD1306 OLED reset pin definition (if available)
    #define SSD1306_RST       RC5_bit    //RD4_bit
    #define SSD1306_RST_DIR   TRISC5_bit      //TRISD4_bit
    
    // SERVICE COSTANT DEFINITIONS
    #define MAX_LEN1 128
    #define MIN_LEN1 50
    #define CR 0x0D
    #define CLS 12
    
    // LINK TO EXTERNAL LIBRARY
    #include <stdbool.h>
    #include <SSD1306OLED.c>
    #include "fm.h"
    #include "i2c18f26k22.c"
    
    char txt[11];
    unsigned char count10us,count100us,count10ms,count1sec;
    unsigned char loop_time_sync;
    
    //////////////////// PIN CONNECTIONS ///////////////////
    
    sbit Encoder_SW3 at RA4_bit;
    sbit Encoder_DT3 at RA3_bit;   //(pin5)
    sbit Encoder_CLK3 at RA2_bit;  //(pin4)
    
    sbit Encoder_SW3_Direction at TRISA4_bit;
    sbit Encoder_DT3_Direction at TRISA3_bit;
    sbit Encoder_CLK3_Direction at TRISA2_bit;
    //////////////////////////////////////////////////////////
    
    
    // FM register bank default values -
    const unsigned int regDflt[18] = {
            0xFFFF,     // R0 -- the first writable register .  (disable xo_en)
            0x5B15,     // R1.
            0xD0B9,     // R2.
            0xA010,     // R3   seekTHD = 16
            0x0780,     // R4
            0x28AB,     // R5
            0x6400,     // R6
            0x1EE7,     // R7
            0x7141,     // R8
            0x007D,     // R9
            0x82C6,     // R10  disable wrap
            0x4F55,     // R11. <--- (disable xo_output)
            0x970C,     // R12.
            0xB845,     // R13
            0xFC2D,     // R14
            0x8097,     // R15
            0x04A1,     // R16
            0xDF6A      // R17
    };
    
    unsigned int regImg[18];        // FM register bank images
    
    
         ////////////////////////////////////////////////////
          /////////////// INTERRUPT SECTION ////////////////
         ////////////////////////////////////////////////////
    
     void interrupt() iv 0x0008 ics ICS_AUTO /* Receive ISR routine void interrupt ISR()*/
      {
         if (TMR0IF_bit){
             //INTERRUPT EVERY 10US
             TMR0IF_bit = 0;
             TMR0L         = 0x60;
             //Enter your code here
             count10us++;
             //if(count10us >=5) count50usBit=1;
             if(count10us >=10){  //if reached 100us
               count10us=0;
               count100us++;
               if(count100us>=100) {     //if reached 10ms
                 count100us=0;
                 loop_time_sync++;
                 count10ms++;
                 if(count10ms>=100){ //if reached 1sec
                   count10ms=0;
    
                   if(count1sec<60) {
                     count1sec++; //_asm btg LATA,1;
                     }  // btg = toggle bit  redled1
                   else count1sec=0;
                  }
                }
             } //END if(count10us.....
          } // END TIMER 1 INTERRUPT
    
      }  // END GLOBAL INTERRUPT
    
    
    void InitTimer0(){
      T0CON         = 0xC8;
      TMR0L         = 0x60;
      GIE_bit         = 1;
      TMR0IE_bit         = 1;
    }
    
         ////////////////////////////////////////////////////
           /////////// END INTERRUPT SECTION //////////////
         ////////////////////////////////////////////////////
    
    /*
     * manualTune() -  Manually tunes the channel
     *
     * @param dir Sets which way the frequency is changed, zero for up,
     *  nonzero for down.
     *
     * @param freq holds the frequency value.
     *
     * @return frequency on success or XF on error.
     *
     */
    unsigned int manualTune(unsigned int freq, unsigned char dir) {
    
    
        switch (dir)
        {
    	case TRUE : //manual up
                if(freq < FREQMAX) //checks that frequency is valid
                {
                    freq++;
                    FMfrequenc(freq); //sends incremented new value to FM chip
                } else {
                    freq = FREQMIN;
                    FMfrequenc(freq);
                }
                break;
    
    
            case FALSE : //manual down
                if(freq > FREQMIN)
                {
                    freq--;
                    FMfrequenc(freq);
                } else {
                    freq = FREQMAX;
                    FMfrequenc(freq);
                }
                break;
    
    	default :
                errfm(); // Call error subroutine
                break;
        }
    
        return freq;
    }
         
    /*
     * FMwrite() -  Write a two byte word to the FM module.  The new
     * register contents are obtained from the image bank.
     *
     * @param adr The address of the register in the FM module that needs
     * to be written.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMwrite(unsigned char adr) {
    
            char value[4];
            unsigned int  regstr;
            unsigned char firstByt;
            unsigned char secndByt;
            unsigned char rpy;
    
            firstByt = regImg[adr] >> 8;
            secndByt = regImg[adr];
    
            my_i2c_Start();                                        // Begin I2C communication
            my_i2c_Idle();
    
            // Send slave address of the chip onto the bus
            
            if (My_I2C_Write(FMI2CADR)) return XF;
            //UART1_Write_Text(" Function FmWrite Fbyte/Sbyte/Adr:");
            //byteToStr(firstByt,value);UART1_Write_Text(value);UART1_Write_Text(" ");
            //intToStr(secndByt,value);UART1_Write_Text(value);UART1_Write_Text(" ");
            //intToStr(adr,value);UART1_Write_Text(value);UART1_Write_Text("\r\n");
            My_I2C_Idle();
            My_I2C_Write(adr);                                // Adress the internal register
            My_I2C_Idle();
            My_I2C_Write(firstByt);                        // Ask for write to FM chip
            My_I2C_Idle();
            My_I2C_Write(secndByt);
            My_I2C_Idle();
            My_I2C_Stop();
            My_I2C_Idle();
            return XS;
    }
    
    
    /*
     * FMread - Read a two byte register from the FM module.
     *
     * @param regAddr The address of the register in the module that needs
     *        to be read.
     *
     * @param data Where to store the reading.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMread(unsigned char regAddr, unsigned int *data_) {
            char value[8];
            unsigned char firstByt;
            unsigned char secndByt;
            My_I2C_Start();                                        // Begin I2C communication
    
            My_I2C_Idle();                                        // Allow the bus to settle
    
            // Send address of the chip onto the bus
    
            if (My_I2C_Write(FMI2CADR)) return XF;   //  return 0
    
            My_I2C_Idle();
            My_I2C_Write(regAddr);                        // Adress the internal register
            My_I2C_Idle();
            My_I2C_Restart();                                // Initiate a RESTART command
            My_I2C_Idle();
            My_I2C_Write(FMI2CADR + DEVRD);        // Ask for read from FM chip
            My_I2C_Idle();
            firstByt = My_I2C_Read();                 // Returns the MSB byte
            My_I2C_Idle();
             My_I2C_ACK;                                        // Send back Acknowledge
            My_I2C_Idle();
            secndByt = My_I2C_Read();                // Returns the LSB of the temperature
            My_I2C_Idle();
            My_I2C_NACK();
            My_I2C_Idle();
            My_I2C_Stop();
            My_I2C_Idle();
            *data_ = firstByt;
            *data_ <<= 8;
            *data_ = *data_ | secndByt;
            //UART1_Write_Text(" Function FmRead *data_:");
            //intToStr(*data_,value);UART1_Write_Text(value);UART1_Write_Text("\r\n");
            return XS;
    }
    
    /*
     * FMready - See if the FM module is ready.
     *
     * @param rdy Where to store the busy/ready status.  Will become
     * non-zero if the chip is ready, zero if busy.
     *
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMready(unsigned int *rdy) {
    
            unsigned int sts;
    
            if (FMread(FMCHIPSTSADR, &sts)  != XS) return XF;
            //_asm bsf LATA,1;
            sts &= FMASKSTATUS;
            *rdy = sts ? TRUE : FALSE;
    
            return XS;
    }
    
    /*
     * FMinit() -  Initialise the FM module.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMinit() {
    
            unsigned char ad;
            unsigned int dat;
    
            // Copy default FM register values to the image set -
            for(ad = 0; ad < 18; ad++) regImg[ad] = regDflt[ad];
    
            dat = regImg[0];
            regImg[0] &= ~1;
            if (FMwrite(0) != XS) return  XF;
            // lo passa
            for(ad = 1; ad < 18; ad++) {
                    if (FMwrite(ad) != XS)return XF;
            }
    
            regImg[0] = dat | 1;
            if (FMwrite(0) != XS) return XF;
            // lo passa
            Delay_ms(20);//dly(20);
            while (FMready(&dat), !dat) Delay_ms(2);            //dly(2);
            // lo passa
            return XS;
    }
    
    
    /*
     * FMfrequenc(f) -  Tune the FM module to new frequency.
     *
     *
     * @param f The new frequency as a multiple of 100 kHz.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMfrequenc(unsigned int f) {
            char value[8];
            unsigned int dat;
            unsigned int cn;                // AR1010 channel number
    
            cn = f - 690;
    
            // NB AR1010 retunes on 0 to 1 transition of TUNE bit -
            regImg[2] &= ~FMASKTUNE;
            if (FMwrite(2) != XS)
                return XF;
            regImg[2] &= 0xfe00;
            regImg[2] |= (cn | FMASKTUNE);
            if (FMwrite(2) != XS)
                return XF;
    
            do {
                    Delay_ms(2); //dly(2);
                    if (FMready(&dat) != XS)  // return 0
                        return XF;
                    _asm btg LATA,1;
           //UART1_Write_Text("FMfrequenc() dat:");intToStr(dat,value);UART1_Write_Text(value);
            } while (!dat);
    
            return XF;  // Code will never get to here.
    }
    
    
    
    /*
     * FMvers - Obtain the FM chip version.
     *
     * @param vsn Where to store the version number.  Will become
     * 0x65B1 for vintage 2009 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMvers(unsigned int *vsn) {    // vsn=55
           
            char temp;
            char value[4];
    
            temp=FMread(FMCHIPVERSADR, vsn);
            UART1_Write_Text("FMread:");shortToStr(temp,value);UART1_Write_Text(value);
            if (temp  != XS) return XF;
    
            return XS;
    }
    
    
    
    /*
     * FMid - Obtain the FM chip ID.
     * * @param id Where to store the ID number.  Will become
     * 0x1010 for AR1010 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMid(unsigned int *id) {
    
            if (FMread(FMCHIPIDADR, id)  != XS) return XF;
    
            return XS;
    }
    
    /*
     * volSet() -  Changes the volume
     *
     * @param dir Sets which way the volume is changed, TRUE for up,
     *  FALSE for down.
     *
     * @param vol holds the volume value.
     *
     * @return volume on success. On failure, enter error loop.
     *
     */
    
    unsigned int volSet(unsigned int vol, unsigned char dir) {
    
    
    
        switch (dir)
        {
            case TRUE : //volume up
                if(vol < 18) //checks that new volume is valid
                {
                    vol++;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    /* OR the mask with the current regImg value */
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
    
                    FMwrite(3); /*Calls function FMwrite to write new volume values to the FM chip*/
                    FMwrite(14);
    
                }
                break;
    
            case FALSE :
                if(vol > 0)
                {
                    vol--;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
                    FMwrite(3);
                    FMwrite(14);
                }
                break;
    
    
            default :
                errfm();
                break;
        }
    
        return vol;
    }
    
    
    
    /*
     * nextChan() -  Tune to the next channel.
     *
     * @param up Set to TRUE for next channel up,
     *  FALSE for preset down.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned int nextChan(unsigned int chan, unsigned char dir) {
    
            switch (dir)
        {
            case TRUE : //manual up
                if(chan < 5) //checks that the selection is valid ***NOTE CHANGE****
                {
                    chan++;
                    FMfrequenc(station[chan]); //sends stored value to FM chip
                } else {
                    chan = 0;
                    FMfrequenc(station[chan]);
                }
                break;
    
    
            case FALSE : //manual down
                if(chan > 0)
                {
                    chan--;
                    FMfrequenc(station[chan]);
                } else {
                    chan = 5;
                    FMfrequenc(station[chan]);
                }
                break;
    
            default :
                //errfm();
                break;
        }
    
        return chan;
    
    }
    
    
    void errfm(void) {
    
        SSD1306_ClearDisplay();   // clear the buffer
        SSD1306_Color = 1;
        SSD1306_TextSize(1);
        SSD1306_GotoXY(2, 7);
        SSD1306_Print("FM Error");
        SSD1306_Display();
    }
    
    
    /*
     * setScan() -  Scan up or down
     *
     * @param dir Sets which way to scan, zero for up,
     *  nonzero for down.
     *
     * Returns the new frequency
     */
    unsigned int setScan(unsigned char dir) {
       char value[8];
       unsigned int dat;
       unsigned int chanRgstr;
       int reg3Wrd;
    
       regImg[1] |= 0x0002; // Set hmute
       FMwrite(1);
    
       regImg[2] &=0xFDFF; //Clear Tune bit
       FMwrite(2);
    
    
       regImg[3] &=0xBFFF; // Clear Seek Bit
       FMwrite(3);
    
       regImg[3] |= 0x4000; // Set SEEK bit
    
       regImg[3] |= 0x2000; // Set spacing
    
        if(dir == 1)
            regImg[3] |= 0x8000;  // If dir is 1, set SEEKUP bit
        else
            regImg[3] &= 0x7FFF; // Otherwise clear to seek down
    
       regImg[3] &= 0xE7FF; // Clear BAND
    
       regImg[3] &= 0xFF80; // Mask all but seek threshold
       regImg[3] |= 0x0040; // Set seek threshold
    
       regImg[10] |= 0x0008; // Set wrap bit
       FMwrite(10); // Write the bits to memory
    
       FMwrite(3);
    
       /* Now wait until finished scanning */
        do {
                Delay_ms(2); //dly(2);
                if (FMready(&dat) != XS) return XF;  //XS=0 XF=1
                //UART1_Write_Text(" setScan() &dat:");
                //intToStr(&dat,value);UART1_Write_Text(value);UART1_Write_Text("\r\n");
                _asm btg LATA,1;
        } while (!dat);
    
        /* Read new channel */
       if ( FMread(READCHAN_ADR, &chanRgstr) == XF)
           errfm();
    
       chanRgstr >>= 7;
       chanRgstr &= 0x01FF; // Ensure that all bits apart from READCHAN are clear
    
       regImg[2] &= 0xFE00; //Mask off CHAN
       regImg[2] |= chanRgstr; // OR with current channel
       FMwrite(2);
    
       chanRgstr += 690;
    
       regImg[1] &= 0xFFFD; // Clear hmute
       FMwrite(1);
    
       return chanRgstr;
    
    }
    
    void clear_screen(){ UART1_Write_Text("\033"); UART1_Write_Text("[2J"); }
    
    
    void SSD_Display(unsigned int value) {
      char text[8];
      SSD1306_ClearDisplay();   // clear the buffer
      SSD1306_Color = 1;
      SSD1306_TextSize(1);
      SSD1306_GotoXY(15, 30);
      intToStr(value, text);
      SSD1306_Print(text);
      SSD1306_Display();
    }
    
    // main function
    void main()
    {
      /////// IMPORTANT PROGRAM LOOPPED  EVERY TIMR IN TO FMfrequenc
      ////// IN PARTICULAR IN DO{................}while(!DAT)
      
      char value[8];
      char value2[4];
      short Temp;
      short Sw3Sel,Sw3PrevSel;
      bit position3;
      unsigned char btn = 0b00000000; // Initialise btn to no buttons being pressed.
            unsigned char evt;
            unsigned int ui;
            unsigned int freq = 875; //Stores frequency
            unsigned int vol = 10; //Stores volume
            unsigned int chan = 0; //Stores channel
            unsigned int counter = 0;
            unsigned int charDispCtr = CHAR_DISP_DELAY;
            unsigned char toggle = false;
    
            unsigned char disp = 'F'; // Stores display state
      
            int dispOfst;
      
      // internal FOSC 16MHz x 4PLL => 64MHz
       OSCCON.IRCF2=1;
       OSCCON.IRCF1=1;
       OSCCON.IRCF0=1;
       OSCTUNE.PLLEN=1;
       OSCCON2.MFIOSEL = 0;
       OSCTUNE.INTSRC = 1;
      //TRISA=0b00000000;
      //PORTA=0;
     // Disable comparators
      C1ON_bit = 0;
      C2ON_bit = 0;
      CM1CON0=0;
      CM2CON0=0;
      ANSELA = 0b00000001; // select ch0 for SpectrumAnalizer
      ANSELB = 0x00;  // configure all PORTB pins as digital
      ANSELC = 0X00; // configure all PORTc pins as digital
      TRISA = 0b00011101; // set A0 as input, A1....A7  as output
      //rb2,rb3,rb4 as Multiplexer outputs
      TRISB = 0b00000000; // set RB2,RB3,TB4 OUTPUT, Other RB5....RB77 as output
      //TRISC = 0b00000111; // set C0,C1,C2 as input, C3....C7  as output
    
      PORTA=0; PORTB=0; PORTC=1;
      Encoder_SW3_Direction=1; Encoder_DT3_Direction=1; Encoder_CLK3_Direction=1;
      ///////////////////////////// INIT TIMER 0 ///////////////////////////
       InitTimer0();   // NECESSARY IN THIS TEST
       /////////////////////////////////////////////////////////////////////
      Delay_ms(500);     // wait a second
      I2C1_Init(400000);  // initialize I2C communication with clock frequency of 400kHz
    
      // initialize the SSD1306 OLED with an I2C addr = 0x7A (default address)
      // 128*64
      SSD1306_Begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
      //SSD1306_ClearDisplay();   // clear the buffer
      //SSP1CON1.SSPEN = 1;
    
      My_I2C_Master_Init();
      Delay_ms(200);
      
      UART1_Init(9600);
      //clear_screen();
      UART1_Write(CLS);   // Erase screen terminal  :it is an option on Vbray Terminal!
      UART1_Write_Text("Start debug: \r\n");
      SSD1306_ClearDisplay();
      
            for(dispOfst=0; dispOfst<6; dispOfst++)
            {
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(2, 7);
                SSD1306_Print("hello world!");
                SSD1306_Display();
                Delay_ms(100);
            }
    
    
            FMvers(&ui);        // Check we have comms with FM chip
            /*
                         //  was this address
            if (ui != 0x1010)
                errfm();
            */
    
           if (ui != 0x10FF)  // new address 0x10FF 4351 (dec)
                errfm();
            UART1_Write_Text(" ui:"); IntToStr(ui,value);UART1_Write_Text(value);
    
            temp=FMinit();
            if (temp != XS)   //XS=0
                errfm();
            UART1_Write_Text(" FmInt:");byteToStr(temp,value2);UART1_Write_Text(value2);
            
            FMfrequenc(freq);    // Initialise frequency
    
            vol=volSet(vol,true);   // Initialise volume to 10
            freq = setScan(TRUE);
            Sw3Sel=1;
    
    
      while(1) {
        // invert the display
        //_asm btg LATA,1;
        //SSD1306_InvertDisplay(true);
        //Delay_ms(1000);
    
        //LATA.B7=1; //redled1
        //PORTA.B3=1;
        //SSD1306_InvertDisplay(false);
        //LATA.B7=1; //redled1
        //PORTA.B3=0;
        //Delay_ms(1000);
        /*
        SSD1306_ClearDisplay();   // clear the buffer
                                SSD1306_Color = 1;
                                SSD1306_TextSize(1);
                                SSD1306_GotoXY(15, 30);
                                intToStr(freq, value);
                                SSD1306_Print("out of case");
                                SSD1306_Display();
        */
                      /*
                      //  Delay_ms(20); //dly(20);    // delay to debounce switches
    
                        switch(disp)
                        {
                            case 'F':
                                //showFreq(freq);
                                SSD1306_ClearDisplay();   // clear the buffer
                                SSD1306_Color = 1;
                                SSD1306_TextSize(1);
                                SSD1306_GotoXY(15, 30);
                                intToStr(freq, value);
                                SSD1306_Print(value);
                                SSD1306_Display();
                                break;
    
                            case 'C':
                                //showChan(chan);
                                break;
    
                            case 'V':
                                //showVol(vol);
                                break;
    
                            case 'S':
                                if(charDispCtr == 0)
                                {
                                    //dispOfst = displayText(stationName[chan],dispOfst);
                                    charDispCtr = CHAR_DISP_DELAY;
    
                                    if(dispOfst == 0)
                                        disp = 'F';
                                }
                                else
                                    charDispCtr--;
                                break;
    
                            default:
                                errfm();
                                break;
                        }
    
                         if (toggle == true) // Volume counter loop
                            {
                                counter = 100;
                                toggle = false;
                            }
                            else if(disp == 'V')
                            {
                                if (counter != 0)
                                    counter--;
                                else
                                    disp = 'F';
                            }
    
    
                        //evt = butnEvent(&btn);
                        if (evt == 1) switch (btn) {
                                                                                                    case BUTN2 : //preset up
                                chan=nextChan(chan, true);
                                freq = station[chan];
                                disp = 'S';
                                //toggle = TRUE;
                                dispOfst = 0;
                                break;
    
                            case BUTN7 : // preset down
                                chan=nextChan(chan, false);
                                freq = station[chan];
                                disp = 'S';
                                //toggle = TRUE;
                                dispOfst = 0;
                                break;
    
                            case BUTN3 : //manual tuning up
                                freq=manualTune(freq, true);
                                disp = 'F';
                                break;
    
                            case BUTN6 : //manual tuning down
                                freq=manualTune(freq, false);
                                disp = 'F';
                                break;
    
                            case BUTN4 : // volume up
                                vol=volSet(vol, true);
                                disp = 'V';
                                toggle = TRUE;
                                break;
    
                            case BUTN5 : // volume down
                                vol=volSet(vol, false);
                                disp = 'V';
                                toggle = TRUE;
                                break;
    
                            case BUTN1 : // scan up
    
                                freq = setScan(true);
                                disp = 'F';
    
                                vol = volSet(vol, true); // Reset Volume
                                vol = volSet(vol, false);
    
                                break;
    
                            case BUTN8 : // Scan down
                                freq = setScan(false);
                                disp = 'F';
    
                                vol = volSet(vol, true); // Reset Volume
                                vol = volSet(vol, false);
    
                                break;
    
                            default:
                                break;
    
                        }
                        evt=0;
                    */
    
      ////////// ROTARY-3 SELECTION //////////
    
       if(Button(&PORTA,4,1000,0)) {
           if(Sw3Sel<4) { _asm bsf LATA,1; Delay_ms(100);_asm bcf LATA,1;Sw3Sel++; }
           else{
                Sw3Sel=1; //SSD1306_ClearDisplay();
              }
           }
       /*
       UART1_Write_Text(" Sw3Sel:"); byteToStr(Sw3Sel,value);UART1_Write_Text(value);
       UART1_Write_Text(" \r\n");
       */
    
    
       if(Sw3PrevSel != Sw3Sel) {
    
          switch (Sw3Sel){
             case 1:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Channel");
                SSD1306_Display();
             break;
             case 2:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Tune");
                SSD1306_Display();
             break;
             case 3:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Volume");
                SSD1306_Display();
             break;
             case 4:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Scan");
                SSD1306_Display();
             break;
             default:
             Sw3Sel=0;
             break;
    
    
             /*
             case 5:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Volume Up");
                SSD1306_Display();
             break;
             case 6:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Volume Down");
                SSD1306_Display();
             break;
             case 7:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Scan Up");
                SSD1306_Display();
             break;
             case 8:
                SSD1306_ClearDisplay();   // clear the buffer
                SSD1306_Color = 1;
                SSD1306_TextSize(1);
                SSD1306_GotoXY(15, 30);
                SSD1306_Print("Scan Down");
                SSD1306_Display();
             break;
             */
          } // end case selection
          Sw3PrevSel=Sw3Sel;
       }   // END if(Sw3PrevSel != Sw3Sel)
    
    
    
          if (Encoder_CLK3 != position3){
                //count1sec=0;  // escape from menu in if(count1sec>=5)
                  // Decrease Value
                  if (Encoder_DT3 != position3){
                        _asm bsf LATA,1; Delay_ms(100);_asm bcf LATA,1;
                        if(Sw3Sel==1) {
                          chan=nextChan(chan, false);
                          freq = station[chan];
                          SSD_Display(chan);
                          //freq=manualTune(freq, false);
                          }
                       if(Sw3Sel==2) {
                          freq=manualTune(freq, false);
                          SSD_Display(freq);
                          //freq=manualTune(freq, false);
                          }
                        if(Sw3Sel==3) {
                          vol=volSet(vol, false);
                          SSD_Display(vol);
                          }
                        if(Sw3Sel==4) {
                          freq = setScan(false);
                          SSD_Display(freq);
                          vol = volSet(vol, true); // Reset Volume
                          vol = volSet(vol, false);
                          }
                   }
                  // Increase Value
                  else{
                       _asm bsf LATA,1; Delay_ms(100);_asm bcf LATA,1;
                      if(Sw3Sel==1) {
                          chan=nextChan(chan, true);
                          freq = station[chan];
                          SSD_Display(chan);
                          //freq=manualTune(freq, true);
                        }
                      if(Sw3Sel==2) {
                          freq=manualTune(freq, true);
                          SSD_Display(freq);
                          //freq=manualTune(freq, true);
                          }
                      if(Sw3Sel==3) {
                         vol=volSet(vol, true);
                         SSD_Display(vol);
                         }
                      if(Sw3Sel==4) {
                          freq = setScan(true);
                          SSD_Display(freq);
                          vol = volSet(vol, true); // Reset Volume
                          vol = volSet(vol, false);
                          }
                  }
    
          }   // End if (Encoder_CLK3 != position)
           position3 = Encoder_CLK3;
    
          ////////// END ROTARY-2 INPUT SELECTION //////////
    
      }  // end while(1);
    
    }
    // end of code.
    
    If you want try the entire project you could find it in attachement togheder documentation I2c Protocol explained very well:
    Attachments
    TestFmRecAR1010andSSD_3.zip
    (187.57 KiB) Downloaded 74 times
    usr_attachment_PR31_DD.pdf
    (1.02 MiB) Downloaded 94 times
    I2C Communication Protocol Tutorial I2C Bus PIC MCU .pdf
    (3.94 MiB) Downloaded 85 times
    Last edited by leo73 on 17 Mar 2021 20:38, edited 7 times in total.

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <UNSOLVED>

    #2 Post by leo73 » 15 Mar 2021 19:10

    UPDATE 29.MAR.2021 18.29
    SECOND VERSION OF CODE: USING I2C MIKRO-C Lib, NOT WORK, code is the same of First Version (worked) but using MikroC I2C Library :lol:
    AR1010LIB.C

    Code: Select all

    ///////////////////////// AR1010 FM RECEIVER LIBRARY//////////////////////
    // AR1010 Non have RDS    AR1000 Have RDS
    // ORIGINAL PROGECT LINK : https://github.com/joshtyler/PIC-FM
    //
    //   File: ar1010.c
    //   Project: LDPS IV FM Radio project
    //   Revisited: Spring 2022
    //////////////////////////////////////////////////////////////////////////
    const unsigned int regDflt[18] = {
            0xFFFF,     // R0 -- the first writable register .FFFF  (disable xo_en)
            0x7B15,     // R1.7B75  5B55  (5B15 original value rds disable)
            // 7B15 -->  111101100010101  (rds_int_en=0)(stc_int_en=0)
            0xD0B9,     // R2.
            0xA010,     // R3   seekTHD = 16
            0x0780,     // R4
            0x28AB,     // R5
            0x6400,     // R6
            0x1EE7,     // R7
            0x7141,     // R8
            0x007D,     // R9
            0x82C6,     // R10  disable wrap
            0x4F55,     // R11. <--- (disable xo_output)
            0x970C,     // R12.
            0xB845,     // R13    (original value B845 1011100001000101)
            0xFC2D,     // R14
            //rds_sta_en=0, rds_mecc=10, rds_ctrl=0  (8086)
            0x8096,     // R15 80B7 (8097 original value)  1000000010100111
            0x04A1,     // R16
            0xDF6A      // R17
    };
    
    
    unsigned int version;
    unsigned int regImg[18];        // FM register bank images
    unsigned char RDS_Text[13];
    
    
    /*
     * manualTune() -  Manually tunes the channel
     *
     * @param dir Sets which way the frequency is changed, zero for up,
     *  nonzero for down.
     *
     * @param freq holds the frequency value.
     *
     * @return frequency on success or XF on error.
     *
     */
    // FM register bank default values -
    unsigned int manualTune(unsigned int freq, unsigned char dir) {
    
    
        switch (dir)
        {
            case TRUE : //manual up
                if(freq < FREQMAX) //checks that frequency is valid
                {
                    freq++;
                    FMfrequenc(freq); //sends incremented new value to FM chip
                } else {
                    freq = FREQMIN;
                    FMfrequenc(freq);
                }
                break;
    
    
            case FALSE : //manual down
                if(freq > FREQMIN)
                {
                    freq--;
                    FMfrequenc(freq);
                } else {
                    freq = FREQMAX;
                    FMfrequenc(freq);
                }
                break;
    
            default :
                errfm(); // Call error subroutine
                break;
        }
    
        return freq;
    }
         
    /*
     * FMwrite() -  Write a two byte word to the FM module.  The new
     * register contents are obtained from the image bank.
     *
     * @param adr The address of the register in the FM module that needs
     * to be written.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMwrite(unsigned char adr) {
    
            char value[4];
            unsigned int  regstr;
            unsigned char firstByt;
            unsigned char secndByt;
            unsigned char rpy;
    
            firstByt = regImg[adr] >> 8;
            secndByt = regImg[adr];
    
            I2C1_Start();                 // Begin I2C communication
            I2C1_Is_Idle();
    
            // Send slave address of the chip onto the bus
            
            if (I2C1_Wr(FMI2CADR)) return XF;
            I2C1_Is_Idle();
            I2C1_Wr(adr);                // Adress the internal register
            I2C1_Is_Idle();
            I2C1_Wr(firstByt);           // Ask for write to FM chip
            I2C1_Is_Idle();
            I2C1_Wr(secndByt);
            I2C1_Is_Idle();
            I2C1_Stop();
            I2C1_Is_Idle();
            return XS;
    }
    
    
    /*
     * FMread - Read a two byte register from the FM module.
     *
     * @param regAddr The address of the register in the module that needs
     *        to be read.
     *
     * @param data Where to store the reading.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMread(unsigned char regAddr, unsigned int *data_) {
            char value[8];
            unsigned char firstByt;
            unsigned char secndByt;
            I2C1_Start();                        // Begin I2C communication
    
            I2C1_Is_Idle();                      // Allow the bus to settle
    
            // Send address of the chip onto the bus
    
            if (I2C1_Wr(FMI2CADR)) return XF;   //  return 0
    
            I2C1_Is_Idle();
            I2C1_Wr(regAddr);              // Adress the internal register
            I2C1_Is_Idle();
            //I2C1_Stop();
            //I2C1_Is_Idle();
            
            //I2C1_Start();
            I2C1_Repeated_Start();                   // Initiate a RESTART command
            I2C1_Is_Idle();
            I2C1_Wr(FMI2CADR | DEVRD);  //(FMI2CADR + DEVRD)Ask for read from FM chip
            I2C1_Is_Idle();
            firstByt = I2C1_Rd(1);      // Returns the MSB byte Acknowledge
            I2C1_Is_Idle();
            //My_I2C1_ACK;              // Send back Acknowledge
            secndByt = I2C1_Rd(0); // Returns the LSB of the temperature NOTACK
            I2C1_Is_Idle();
            //My_I2C1_NACK();
            I2C1_Stop();
            I2C1_Is_Idle();
            *data_ = firstByt;
            *data_ <<= 8;
            *data_ = *data_ | secndByt;
            version=*data_;
            return XS;
    }
    
    /*
     * FMready - See if the FM module is ready.
     *
     * @param rdy Where to store the busy/ready status.  Will become
     * non-zero if the chip is ready, zero if busy.
     *
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMready(unsigned int *rdy) {
    
            unsigned int sts;
    
            if (FMread(FMCHIPSTSADR, &sts)  != XS) return XF;
            sts &= FMASKSTATUS;
            *rdy = sts ? TRUE : FALSE;
    
            return XS;
    }
    
    /*
     * FMinit() -  Initialise the FM module.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMinit() {
    
            unsigned char ad;
            unsigned int dat;
    
            // Copy default FM register values to the image set -
            for(ad = 0; ad < 18; ad++) regImg[ad] = regDflt[ad];
    
            dat = regImg[0];
            regImg[0] &= ~1;
            if (FMwrite(0) != XS) return  XF;
            for(ad = 1; ad < 18; ad++) {
                    if (FMwrite(ad) != XS)return XF;
            }
    
            regImg[0] = dat | 1;
            if (FMwrite(0) != XS) return XF;
            Delay_ms(20);//dly(20);
            while (FMready(&dat), !dat) Delay_ms(2);            //dly(2);
            return XS;
    }
    
    
    /*
     * FMfrequenc(f) -  Tune the FM module to new frequency.
     *
     *
     * @param f The new frequency as a multiple of 100 kHz.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMfrequenc(unsigned int f) {
            char value[8];
            unsigned int dat;
            unsigned int cn;                // AR1010 channel number
    
            cn = f - 690;
    
            // NB AR1010 retunes on 0 to 1 transition of TUNE bit -
            regImg[2] &= ~FMASKTUNE;
            if (FMwrite(2) != XS)
                return XF;
            regImg[2] &= 0xfe00;
            regImg[2] |= (cn | FMASKTUNE);
            if (FMwrite(2) != XS)
                return XF;
    
            do {
                    Delay_ms(2); //dly(2);
                    if (FMready(&dat) != XS)  // return 0
                        return XF;
            } while (!dat);
    
            return XF;  // Code will never get to here.
    }
    
    
    
    /*
     * FMvers - Obtain the FM chip version.
     *
     * @param vsn Where to store the version number.  Will become
     * 0x65B1 for vintage 2009 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMvers(unsigned int *vsn) {    // vsn=55
           
            char temp;
            //char value[4];
    
            temp=FMread(FMCHIPVERSADR, vsn);  // FMCHIPVERSADR=0x1C
            if (temp  != XS) return XF;
    
            return XS;
    }
    
    /*
     * FMstrength() -  Get the signal strength.
     *
     * @param strength Where to store the signal strength.
     * The strength is a 7 bit number.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMstrength(unsigned int *strength) {
    
            if (FMread(FMCHIPSTRNGTH, strength) != XS) return XF;
            *strength >>= 9;
            return XS;
    }
    //
    // end FMstrength
    
    
    
    /*
     * FMid - Obtain the FM chip ID.
     * * @param id Where to store the ID number.  Will become
     * 0x1010 for AR1010 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMid(unsigned int *id) {
    
            if (FMread(FMCHIPIDADR, id)  != XS) return XF;
    
            return XS;
    }
    
    /*
     * volSet() -  Changes the volume
     *
     * @param dir Sets which way the volume is changed, TRUE for up,
     *  FALSE for down.
     *
     * @param vol holds the volume value.
     *
     * @return volume on success. On failure, enter error loop.
     *
     */
    
    unsigned int volSet(unsigned int vol, unsigned char dir) {
    
    
    
        switch (dir)
        {
            case TRUE : //volume up
                if(vol < 18) //checks that new volume is valid
                {
                    vol++;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    /* OR the mask with the current regImg value */
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
    
                    FMwrite(3); /*Calls function FMwrite to write new volume values to the FM chip*/
                    FMwrite(14);
    
                }
                break;
    
            case FALSE :
                if(vol > 0)
                {
                    vol--;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
                    FMwrite(3);
                    FMwrite(14);
                }
                break;
    
    
            default :
                errfm();
                break;
        }
    
        return vol;
    }
    
    
    
    /*
     * nextChan() -  Tune to the next channel.
     *
     * @param up Set to TRUE for next channel up,
     *  FALSE for preset down.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned int nextChan(unsigned int chan, unsigned char dir) {
    
            switch (dir)
        {
            case TRUE : //manual up
                if(chan < 5) //checks that the selection is valid ***NOTE CHANGE****
                {
                    chan++;
                    FMfrequenc(station[chan]); //sends stored value to FM chip
                } else {
                    chan = 0;
                    FMfrequenc(station[chan]);
                }
                break;
    
    
            case FALSE : //manual down
                if(chan > 0)
                {
                    chan--;
                    FMfrequenc(station[chan]);
                } else {
                    chan = 5;
                    FMfrequenc(station[chan]);
                }
                break;
    
            default :
                //errfm();
                break;
        }
    
        return chan;
    
    }
    
    /*
     * setScan() -  Scan up or down
     *
     * @param dir Sets which way to scan, zero for up,
     *  nonzero for down.
     *
     * Returns the new frequency
     */
    unsigned int setScan(unsigned char dir) {
       char value[8];
       unsigned int dat;
       unsigned int chanRgstr;
       int reg3Wrd;
    
       regImg[1] |= 0x0002; // Set hmute
       FMwrite(1);
    
       regImg[2] &=0xFDFF; //Clear Tune bit
       FMwrite(2);
    
    
       regImg[3] &=0xBFFF;  // Clear Seek Bit 1011111111111111
       FMwrite(3);
    
       regImg[3] |= 0x4000; // Set SEEK bit   0100000000000000
    
       regImg[3] |= 0x2000; // Set spacing    0010000000000000
    
        if(dir == 1)
            //regImg[3] |= 0x8000; //If dir is 1, set SEEKUP bit 1000000000000000
            regImg[3] |= 0x8010; //Set SEEKUP/SEEKTH !!!TWEAK SEEKTH 1000000000010000
        else
            //regImg[3] &= 0x7FFF; //Otherwise clear to seek down.3FFF 0111111111111111
            regImg[3] &= 0x4000;
            
       regImg[3] &= 0xE7FF; // Clear BAND  E700   1110011111111111
    
       regImg[3] &= 0xFF80; // Mask all but seek threshold  FF80;  0001110000000000
       regImg[3] |= 0x0040; // Set seek threshold(soglia ricerca)  0000000001000000
    
       regImg[10] |= 0x0008; // Set wrap bit     0000000001000000
       FMwrite(10); // Write the bits to memory
    
       FMwrite(3);
    
       /* Now wait until finished scanning */
        do {
                Delay_ms(2);
                if (FMready(&dat) != XS) return XF;  //XS=0 XF=1
        } while (!dat);
    
        /* Read new channel */
       if ( FMread(READCHAN_ADR, &chanRgstr) == XF)
           errfm();
    
       chanRgstr >>= 7;
       chanRgstr &= 0x01FF; // Ensure that all bits apart from READCHAN are clear
    
       regImg[2] &= 0xFE00; //Mask off CHAN  1111111000000000
       regImg[2] |= chanRgstr; // OR with current channel
       FMwrite(2);
    
       chanRgstr += 690;
    
       regImg[1] &= 0xFFFD; // Clear hmute
       FMwrite(1);
    
       return chanRgstr;
    }
    
    
    void read_rds(void) {
     unsigned char i, lsb, msb;
     unsigned int RDSRgstr;
       //set only rds_int_en = 1 don't touch other
       // 1010 OR 0000 = 1010 no modyfy bits - 1010 OR 1111 = 1111 set 1 all bits
       // If you want set bits you must do <value> OR 1 bits.
       regImg[1] |= 0x0040;  // 0000000001000000
       FMwrite(1);
       // RDS Int respond in 5ms we wait it in do...while cicle
       //Delay_ms(5);
       do{
          if ( FMread(READRDSREADY_ADR, &RDSRgstr) == XF) //Read all STATUR Register
             errfm();
          RDSRgstr &= 0x0040;       // mask all bit but RDSR no 0000000001000000
       }while(RDSRgstr != 0x0040);  // wait until BIT RDSE became 1
       
       // Read RDS Text in 6 Blocks of 2 byte and store it in RDS_Text global vector
       for(i=1; i<11; i+=2){
          if ( FMread(RDSBuffer[i], &RDSRgstr) == XF) //Read all STATUR Register
             errfm();
             //RDS_Text[i]=RDSRgstr;
          lsb = (unsigned)RDSRgstr & 0xff; // mask the lower 8 bits
          msb = (unsigned)RDSRgstr >> 8;   // shift the higher 8 bits
          RDS_Text[i] = lsb;
          RDS_Text[i+1] = msb;
       }
       // 1010 AND 1111 = 1010 no modyfy bits - 1010 AND 0000 = 0000 clear all bits
       // If you want to clear bits you must do <value> AND 0 bits.
       regImg[1] &= 0xFF9F;  //clear rds_int_en = 0 and stc_Int_en  1111111110011111
       FMwrite(1);
    }
    
    FM.H

    Code: Select all

    ///////////////////////// AR1010 FM RECEIVER LIBRARY//////////////////////
    // AR1010 Non have RDS    AR1000 Have RDS
    // ORIGINAL PROGECT LINK : https://github.com/joshtyler/PIC-FM
    //
    //   File: fm.h
    //   Project: LDPS IV FM Radio project
    //   Revisited: Spring 2022
    //////////////////////////////////////////////////////////////////////////
    
    
    #define XS                        0       // Exit success
    #define XF                        1      // Exit fail
    
    #define FMI2CADR                0x20  // Address (for writes) of FM module on I2C bus
    
    
    #define DEVRD                   0x01   // Read not write an I2C device
    #define FMCHIPVERSADR           0x1C   //0x06 //0x1C   // Address of FM chip version
    #define FMCHIPIDADR             0x1B   // Addres
    
    #define FMCHIPIDADR             0x1B   // Address of FM chip ID
    #define FMCHIPSTSADR            0x13   // Address of FM chip status
    #define FMRDSADDR               0x15
    #define FMCHIPSTRNGTH                0x12   // Signal strength level
    
    #define READCHAN_ADR            0x13
    #define READRDSREADY_ADR        0x13
    
    #define FMASKMUTE               0x0001      // Register 1, bit 1
    #define FMASKTUNE               0x0200      // Register 2, bit 9
    #define FMASKSTATUS             0x0020      // Register 0x13, bit 5
    #define FMASKSEEK               0x4000      // Register 3, bit 14
    #define FMASKRDCHAN             0xFF80      // Register 2, channel number bits
    
    
    #define FREQMAX                 1170//1080      // Maximum frequency
    #define FREQMIN                 875             // Minimum frequency
    
    #define FMHIGHCHAN             (1080-690)   // Highest FM channel number
    #define FMLOWCHAN              (875-690)
    #define FALSE                  0
    #define TRUE                   1
    
    #define CHAR_DISP_DELAY        60          // Delay used for displaying text
    
    /* Masks used to clear volume bits */
    #define VOL1_MASK               0xF87F
    #define VOL2_MASK               0x0FFF
    
    /* Masks used to clear scan bits*/
    #define SCAN_REG3_MASK          0x1FFF
    #define SCAN_REG10_MASK         0xFFF7
    
    /* Recommended values for volume, obtained from data sheet, repackaged for actual location in memory */
    const int volumePair[2][19] = {            
        {0x0780, 0x0780, 0x0780, 0x0780, 0x0580, 0x0580, 0x0580, 0x0500, 0x0480, 0x0400, 0x0380, 0x0300, 0x0300, 0x0300, 0x0180, 0x0180, 0x0100, 0x0080, 0x0000} ,   /*  Values for R3  */
        {0x0000, 0xC000, 0xD000, 0xF000, 0xC000, 0xD000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xD000, 0xE000, 0xF000, 0xE000, 0xF000, 0xF000, 0xF000, 0xF000}    /*  Values for R14 */
    };
    
    const unsigned short RDSBuffer[8] ={0x15, 0x16, 0x17, 0x18, 0x19, 0x1A};
    const unsigned int station[6] = {875, 881, 903, 964, 1046, 1129};
    
    char stationName[6][15] = { "UNKNOWN", "BBC[TWO", "BBC[THREE", "EAGLE", "BBC[ONE", "UNKNOWN" };
    
    enum {                     // Global error numbers
            GERNONE,           // No error
            GERWCOL,           // I2C write collision
            GERFINT,           // Could not initialize FM module
            GERFMID            // Could not read chip ID (0x1010)
    };
    
    void Init();                                     // Processor initialisation.
    unsigned int manualTune(unsigned int freq, unsigned char dir);
    unsigned char FMread(unsigned char regAddr , unsigned int *data_);
    unsigned char FMwrite(unsigned char adr);           // Write a new value to a register
    unsigned char FMinit();                             // Initialise the chip
    unsigned char FMfrequenc(unsigned int f);
    unsigned char FMready(unsigned int *rdy);           // Status is ready or busy
    unsigned char FMid(unsigned int *id);               // Obtain ID number
    unsigned char showFreq(unsigned int frequency);     // Display the current f in MHz
    unsigned char FMvers(unsigned int *vsn);
    unsigned char FMstrength(unsigned int *strength);   // Obtain version number
    unsigned int volSet(unsigned int vol, unsigned char dir);
    unsigned int nextChan(unsigned int chan, unsigned char dir);
    void errfm(void);
    unsigned char showVol(unsigned int volume);
    unsigned char showChan(unsigned int channel);
    unsigned int setScan(unsigned char dir);
    
    //
    // end receiveFM.h ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //
    //
    
    MAIN:

    Code: Select all

    /////////////////////////// AR1010 FR RECEIVER TEST ///////////////////////
    //         18F26K22  INTERNAL CLOCK 16MHZ X 4 PLL = 64MHZ
    // ORIGINAL PROGECT LINK : https://github.com/joshtyler/PIC-FM
    //
    // PIN OUT:
    // Encoder_SW3 -->  RA4 (pin6)   NEED TO CONNECT
    // Encoder_DT3 -->  RA3 (pin5)   NEED TO CONNECT
    // Encoder_CLK3 --> RA2 (pin4)   NEED TO CONNECT
    // AR1010 FM RECEIFER --> SDA - SCL PINS
    // UART1              --> ON UART1 PINS
    //
    //
    // NOTES:
    // _asm bsf LATA,1;
    // _asm bcf LATA,1;
    //
    ///////////////////////////////////////////////////////////////////////////
    
    #define debug1   // coment line if no not want dedug on UART1
    
    // SERVICE COSTANT DEFINITIONS
    #define MAX_LEN1 128
    #define MIN_LEN1 50
    #define CR 0x0D
    #define CLS 12
    
    // LINK TO EXTERNAL LIBRARY
    #include <stdbool.h>
    #include "fm.h"
    #include "AR1010FM.c"
    
    
    char txt[11];
    unsigned char count10us,count100us,count10ms,count1sec;
    unsigned char loop_time_sync;
    
    
         ////////////////////////////////////////////////////
          /////////////// INTERRUPT SECTION ////////////////
         ///////////not necessary for this test/////////////
    
     void interrupt() iv 0x0008 ics ICS_AUTO /* Receive ISR routine void interrupt ISR()*/
      {
         if (TMR0IF_bit){
             //INTERRUPT EVERY 10US
             TMR0IF_bit = 0;
             TMR0L         = 0x60;
             //Enter your code here
             count10us++;
             //if(count10us >=5) count50usBit=1;
             if(count10us >=10){  //if reached 100us
               count10us=0;
               count100us++;
               if(count100us>=100) {     //if reached 10ms
                 count100us=0;
                 loop_time_sync++;
                 count10ms++;
                 if(count10ms>=100){ //if reached 1sec
                   count10ms=0;
    
                   if(count1sec<60) {
                     count1sec++; _asm btg LATA,1;
                     }  // btg = toggle bit  redled1
                   else count1sec=0;
                  }
                }
             } //END if(count10us.....
          } // END TIMER 1 INTERRUPT
    
      }  // END GLOBAL INTERRUPT
    
    
    void InitTimer0(){
      T0CON         = 0xC8;
      TMR0L         = 0x60;
      GIE_bit         = 1;
      TMR0IE_bit         = 1;
    }
    
         ////////////////////////////////////////////////////
           /////////// END INTERRUPT SECTION //////////////
         ////////////////////////////////////////////////////
    
    void clear_screen(){ UART1_Write_Text("\033"); UART1_Write_Text("[2J"); }
    
    
    void errfm(){
    UART1_Write_Text("!!!! AR1010 FM ERROR !!!!! \r\n");
    }
    
    
    // main function
    void main()
    {
      char i;
      char value[8];
      char value2[4];
      unsigned char evt, Sw3Sel, Sw3PrevSel;
      bit position3;
      unsigned int ui, strength, test;
      unsigned int freq = 1031;//875; //Stores frequency
      unsigned int vol = 4; //Stores volume
      unsigned int chan = 0; //Stores channel
      unsigned int txt;
      
      // internal FOSC 16MHz x 4PLL => 64MHz
       OSCCON.IRCF2=1;
       OSCCON.IRCF1=1;
       OSCCON.IRCF0=1;
       OSCTUNE.PLLEN=1;
        OSCTUNE.SCS1=1;   // Set interinal clk block
       //OSCCON2.MFIOSEL = 0;
       //OSCTUNE.INTSRC = 1;
       
      //TRISA=0b00000000;
      //PORTA=0;
     // Disable comparators
      C1ON_bit = 0;
      C2ON_bit = 0;
      CM1CON0=0;
      CM2CON0=0;
      ANSELA = 0b00000001; // select ch0 for SpectrumAnalizer
      ANSELB = 0x00;  // configure all PORTB pins as digital
      ANSELC = 0X00; // configure all PORTc pins as digital
      TRISA = 0b00011101; // set A0 as input, A1....A7  as output
      TRISB = 0b00000000; // set RB2,RB3,TB4 OUTPUT, Other RB5....RB77 as output
      //TRISC = 0b00000111; // set C0,C1,C2 as input, C3....C7  as output
    
      PORTA=0; PORTB=0; PORTC=1;
      
      ///////////////////////////// INIT TIMER 0 ///////////////////////////
       //InitTimer0();   // NOT NECESSARY IN THIS TEST
       /////////////////////////////////////////////////////////////////////
      Delay_ms(300);     // wait a second
      I2C1_Init(200000); // initializ I2C commun with clock frequency of 400kHz
      Delay_ms(200);
    
      Delay_ms(100);
      UART1_Init(9600);
      Delay_ms(100);
    
      
      UART1_Write(CLS);   // Erase screen terminal  :it is an option on Vbray Terminal!
      #ifdef debug1
      UART1_Write_Text("Start debug: \r\n");
      #endif
    
      FMvers(&ui);        // Check we have comms with FM chip (ver=0x10FF)
      #ifdef debug1
      IntToHex(version, value);UART1_Write_Text("Version Chip: ");
      UART1_Write_Text(value);
      IntToHex(ui, value);UART1_Write_Text(" ui: ");
      UART1_Write_Text(value);UART1_Write_Text("\r\n");
      #endif
                         //  was this address
      if (ui != 0x10FF) errfm();
            
      if (FMinit()!= XS) errfm();  //XS=0
      FMfrequenc(freq);    // Initialise frequency
      vol=volSet(vol,true);   // Initialise volume to 10
      #ifdef debug1
      UART1_Write_Text("Volume:  ");IntToStr(vol, value);
      UART1_Write_Text(value);UART1_Write_Text("\r\n");
      /*
      if ( FMread(0x0F, &test) == XF) //Read all STATUR Register
             errfm();
        IntToHex(test, value);
        UART1_Write_Text(value);UART1_Write_Text("\r\n");
      */
      /*
      test = 0xFFFF;  //1111111111111111
      IntToHex(test, value);
      UART1_Write_Text(value);UART1_Write_Text("\r\n");
      test &= 0x40;  //0000000001000000  // clear bit 7
    
      IntToHex(test, value);
      UART1_Write_Text(value);UART1_Write_Text("\r\n");
      */
      
      #endif
      //Delay_ms(1000);
      
      while(1) {
       Delay_ms(1000);
       #ifdef debug1
    
        if((count1sec==30 || count1sec==0 )&& count10ms==0){
          UART1_Write_Text("RDS Texture:  ");
          for(i=1;i<13;i++) {
            read_rds();
            ByteToStr(RDS_Text[i], value2);
            UART1_Write_Text(value2);UART1_Write_Text(" ");
           }
          UART1_Write_Text("\r\n");
         
         if (FMstrength(&strength)!= XS) errfm();
          IntToStr(strength, value);UART1_Write_Text("Signal strength:");
          UART1_Write_Text(value);UART1_Write_Text("\r\n");
    
         }
    
       #endif
       
                         //// FUNCTIONS YOU CAN USE /////
                                //showChan(chan);
                                //showVol(vol);
                                
                                // Select Channel up and return Chan number                                                                    case BUTN2 : //preset up
                                //chan=nextChan(chan, true);
                                //freq = station[chan];
                                
                                // Select Channel up and return Chan number
                                //chan=nextChan(chan, false);
                                //freq = station[chan];
                                
                                // change and return frequency turned up
                                //freq=manualTune(freq, true);
    
                                // change and return frequency turned down
                                //freq=manualTune(freq, false);
    
                                // change and return increase volume up
                                //vol=volSet(vol, true);
                                
                                // change and return decrease volume up
                                //vol=volSet(vol, false);
    
                                // scan up frequencies and return frequency
                                //freq = setScan(true);
    
                                // scan down frequencies and return frequency
                                //freq = setScan(false);
    
    
      
      }  // end while(1);
    
    }
    // end of code.
    
    Attachments
    AR1010-TEST-1-MikroC-I2C-Lib.zip
    (99.05 KiB) Downloaded 59 times
    AR1010 I2C Signal table (not want NoAck only Ack signal)
    AR1010 I2C Signal table (not want NoAck only Ack signal)
    Screenshot_20210316-105513_1.jpg (68.04 KiB) Viewed 2971 times
    AR1010-RegistryTable.jpg
    AR1010-RegistryTable.jpg (115.84 KiB) Viewed 2994 times
    Last edited by leo73 on 29 Mar 2021 18:37, edited 8 times in total.

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <UNSOLVED>

    #3 Post by leo73 » 16 Mar 2021 18:34

    SECOND VERSION OF CODE AR1010 MIKRO C I2C LIBRARY 16.MAR.2021
    BELOW THERE ARE TWO TABLES, THE FIRST QUESTING THE FM MODULE THAT ADDRESS 0x40;
    WHILE THE SECOND QUESTION IS DONE USING THE ADDRESS 0x20.
    NOTE THAT IN THE SECOND TABLE THE I2C_WRITE () FUNCTIONS RETURN FEWER ERRORS THAN THE FIRST TABLE. SO THE 0x20 ADDRESS SHOULD BE THE RIGHT ONE.
    What values do the tables show?
    They show what the writeToRegister (....) function (called by the initialize () function) tries to write into the registers of the fm ar1010 module.
    The first two columns are the default register values (register_init []) in hexadecimal.
    the other columns are the return values (in Hexadecimal) of the functions respectively:
    I2C1_Start (); I2C1_Wr (AR1010_ADDRESS); I2C1_Wr ((uint8_t) ((data_ & 0xFF00) >> 8 )); I2C1_Wr ((uint8_t) (data_ & 0x00FF)); contained inside the writeToRegister (.....) function.
    110 / 5000
    Risultati della traduzione
    can someone or can tell me why the first setting on the first register of the FM AR1010 module fails? thank you.
    PS: refer to the second project above.

    AR1010 FM RECEIVER CHIP ADDRESS TO WRITE IN CODE IS 0x20
    because using other address functions I2C_wr return errors (not 0 but other value)
    How can see below:

    Code: Select all

    ///////////// USING AR1010_ADDRESS  0x20
    Start debug:
    Initialize() function :				    I2C1_Start();   I2C1_Wr(AR1010_ADDRESS);   I2C1_Wr((uint8_t)((data_ & 0xFF00)>>8));
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 5B 15 	00 		02 <-- ERROR		02 <-- ERROR 				02 <-- ERROR
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): D0 B9 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): A0 10 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 07 80 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 28 AB 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 64 00 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 1E E7 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 71 41 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 00 7D 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 82 C6 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 4F 55 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 97 0C 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): B8 45 	00 		00			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): FC 2D 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 80 97 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 04 A1 	00 		00 			00 					00
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): DF 6A 	00 		00 			00 					00
    

    Code: Select all

    ////////// USING AR1010_ADDRESS  0x40
    Start debug:
    Initialize() function :	    			    I2C1_Start();   I2C1_Wr(AR1010_ADDRESS);   I2C1_Wr((uint8_t)((data_ & 0xFF00)>>8)); I2C1_Wr((uint8_t)(data_ & 0x00FF));
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 5B 15 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): D0 B9 	00 		02 <-- ERROR returned	02 <-- ERROR returned""			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): A0 10 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 07 80 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 28 AB 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned	
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 64 00 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned	
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 1E E7 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 71 41 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 00 7D 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 82 C6 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 4F 55 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned""
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 97 0C 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): B8 45 	00 		02 <-- ERROR returned	02 <-- ERROR returned			02 <-- ERROR returned
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): FC 2D 	00 		02 	""		02 	""				02	""
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 80 97 	00 		02	""		02	"" 				02	""
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): 04 A1 	00 		02	""		02	"" 				02	""
    Initialize() function :
    (datatest & 0xFF00)>>8 and (data_ & 0x00FF): DF 6A 	00 		02	""		02	"" 				02	""
    
    
    Last edited by leo73 on 29 Mar 2021 17:38, edited 1 time in total.

    paulfjujo
    Posts: 1558
    Joined: 24 Jun 2007 19:27
    Location: 01800 St Maurice de Gourdans France
    Contact:

    Re: FM Receiver AR1010 I2C problem <UNSOLVED> update:16.Mar.2021

    #4 Post by paulfjujo » 17 Mar 2021 10:51

    hello,

    did you read the previous post
    i2c Master How can request (to slave) 2 data using I2c_Read() in line?

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1st ver SOLVED> update:16.Mar.2021

    #5 Post by leo73 » 17 Mar 2021 20:32

    FIRST VERSION OF CODE AR1010 NATIVE (using pic registers) I2C LIBRARY IMPLEMENTATION DONE AND WORK
    BELOW THE CODE.(for 18F26k22 mcu)
    !!!!! AR1010 FM CHIP DEVICE WORK AT 100.000 K/B until at 200.000 K/b speed bus !!!!!!
    AR1010 Manual wrote max i2c bus speed is 400khz. Probability using a tape bus !! (low cacacity bus)
    18.Mar.2021 register data corridge in to setScan() function
    27.MAr.2021 added function FMstrength(&strength);
    2IC18F26k22 Lib:

    Code: Select all

    ///////////////////// I2C IMPLEMENTATION for 18F26k22/////////////////////////
    // https://deepbluembedded.com/i2c-communication-protocol-tutorial-pic/
    // I2C MASTER
    //
    // _asm bsf LATA,1;
    // _asm bcf LATA,1;
    ///////////////////////////////////////////////////////////////////
    // OpenI2C( MASTER, SLEW_OFF);
     
    #define _XTAL_FREQ 16000000 // Fosc In this case i have set internal oscillator
                                // Int Osc 16Mhx x 4 PLL = 64Mhz
    #define I2C_BaudRate 100000 // I2C Baud Rate = 100 Kbps
    
    //void OpenI2C1(unsigned char, unsigned char);
    void My_I2C1_Master_Init(void);
    void My_I2C1_Idle(void);        //void I2C_Wait(void);
    void My_I2C1_Start(void);
    void My_I2C1_Stop(void);
    void My_I2C1_Restart(void);
    void My_I2C1_ACK(void);
    void My_I2C1_NACK(void);
    unsigned char My_I2C1_Write(unsigned char);
    unsigned char My_I2C1_Read(unsigned char);
    
    void My_I2C1_Master_Init(void)
    {
      SSP1CON1 = 0x28;  //Select and enable master mode WCOL SSPOV SSPEN CKP SSPM<3:0>
      SSP1CON2 = 0x00;   //GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN
      SSP1STAT = 0x00;   //SMP      CKE     D/A   P    S   R/W  UA  BF
      SSP1ADD = ((_XTAL_FREQ/4)/I2C_BaudRate) - 1; //((_XTAL_FREQ/4)/I2C_BaudRate) - 1;
      TRISC.B3 = 1; // scl pin.
      TRISC.B4 = 1; // SDA pin.
      SSP1CON1.SSPEN = 1; // added after
    
    }
    void My_I2C1_Idle()
    {
      while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F));
    }
    void My_I2C1_Start()
    {
      //---[ Initiate I2C Start Condition Sequence ]---
      My_I2C1_Idle();
      SSP1CON2.SEN = 1;
    }
    void My_I2C1_Stop()
    {
      //---[ Initiate I2C Stop Condition Sequence ]---
      My_I2C1_Idle();
      SSP1CON2.PEN = 1;
    }
    void My_I2C1_Restart()
    {
      //---[ Initiate I2C Restart Condition Sequence ]---
      My_I2C1_Idle();
      SSP1CON2.RSEN = 1;
    }
    void My_I2C1_ACK(void)
    {
      //---[ Send ACK - For Master Receiver Mode ]---
      My_I2C1_Idle();
      SSP1CON2.ACKDT = 0; // 0 -> ACK, 1 -> NACK
      SSP1CON2.ACKEN = 1; // Send ACK Signal!
    }
    void My_I2C1_NACK(void)
    {
      //---[ Send NACK - For Master Receiver Mode ]---
      My_I2C1_Idle();
      SSP1CON2.ACKDT = 1; // 1 -> NACK, 0 -> ACK
      SSP1CON2.ACKEN = 1; // Send NACK Signal!
    }
    unsigned char My_I2C1_Write(unsigned char data_)
    {
      //---[ Send Byte, Return The ACK/NACK ]---
      My_I2C1_Idle();
      SSPBUF = data_;
      My_I2C1_Idle();
      return SSP1CON2.ACKSTAT;
    }
    
    unsigned char My_I2C1_Read(void){
      if((SSP1CON1 & 0x0F) == 0x08) SSP1CON2.RCEN = 1; // MASTER MODE ONLY
        while(!SSP1STAT.BF);  // WAIT UNTIL BYTE RECEIVED
        return SSP1BUF;       // RETURN WHIT READ BYTE
    }
    
    AR1010FM.h

    Code: Select all

    /*
       File: fm.h
       Project: LDPS IV FM Radio project
       Revisited: Spring 2021
       for 18F26k22
    */
    
    
    #define XS                        0                        // Exit success
    #define XF                        1                        // Exit fail
    
    #define FMI2CADR                0x20  // Address (for writes) of FM module on I2C bus
    
    
    #define DEVRD                   0x01       // Read not write an I2C device
    #define FMCHIPVERSADR           0x1C   //0x06 //0x1C   // Address of FM chip version
    #define FMCHIPIDADR             0x1B       // Address of FM chip ID
    #define FMCHIPSTSADR            0x13       // Address of FM chip status
    #define FMCHIPSTRNGTH	        0x12      // Signal strength level
    
    #define READCHAN_ADR            0x13
    
    #define FMASKMUTE               0x0001          // Register 1, bit 1
    #define FMASKTUNE               0x0200          // Register 2, bit 9
    #define FMASKSTATUS             0x0020         // Register 0x13, bit 5
    #define FMASKSEEK               0x4000          // Register 3, bit 14
    #define FMASKRDCHAN             0xFF80      // Register 2, channel number bits
    
    #define LCDSEGDP3                22              // LCD segment for decimal point
    #define LCDSEGZ                 23                // LCD segment for Z
    
    #define FREQMAX                 1080           // Maximum frequency
    #define FREQMIN                 875             // Minimum frequency
    
    #define FMHIGHCHAN                (1080-690)        // Highest FM channel number
    #define FMLOWCHAN                (875-690)
    #define FALSE                        0
    #define TRUE                        1
    
    #define CHAR_DISP_DELAY         60              // Delay used for displaying text
    
    /* Masks used to clear volume bits */
    #define VOL1_MASK               0xF87F
    #define VOL2_MASK               0x0FFF
    
    /* Masks used to clear scan bits*/
    #define SCAN_REG3_MASK          0x1FFF
    #define SCAN_REG10_MASK         0xFFF7
    
    /* Recommended values for volume, obtained from data sheet, repackaged for actual location in memory */
    const int volumePair[2][19] = {            
        {0x0780, 0x0780, 0x0780, 0x0780, 0x0580, 0x0580, 0x0580, 0x0500, 0x0480, 0x0400, 0x0380, 0x0300, 0x0300, 0x0300, 0x0180, 0x0180, 0x0100, 0x0080, 0x0000} ,   /*  Values for R3  */
        {0x0000, 0xC000, 0xD000, 0xF000, 0xC000, 0xD000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xD000, 0xE000, 0xF000, 0xE000, 0xF000, 0xF000, 0xF000, 0xF000}    /*  Values for R14 */
    };
    
    const unsigned int station[6] = {875, 881, 903, 964, 1046, 1129};
    
    char stationName[6][15] = { "UNKNOWN", "BBC[TWO", "BBC[THREE", "EAGLE", "BBC[ONE", "UNKNOWN" };
    
    enum {                                                     // Global error numbers
            GERNONE,                                       // No error
            GERWCOL,                                      // I2C write collision
            GERFINT,                                        // Could not initialize FM module
            GERFMID                                        // Could not read chip ID (0x1010)
    };
    
    void Init();                                            // Processor initialisation.
    unsigned int manualTune(unsigned int freq, unsigned char dir);
    unsigned char FMread(unsigned char regAddr , unsigned int *data_);
    unsigned char FMwrite(unsigned char adr);                                // Write a new value to a register
    unsigned char FMinit();                                                             // Initialise the chip
    unsigned char FMfrequenc(unsigned int f);
    unsigned char FMready(unsigned int *rdy);                              // Status is ready or busy
    unsigned char FMid(unsigned int *id);                                     // Obtain ID number
    unsigned char FMstrength(unsigned int *strength); 		    // Signal strength level
    unsigned char showFreq(unsigned int frequency);                   // Display the current f in MHz
    unsigned char FMvers(unsigned int *vsn);                                // Obtain version number
    unsigned int volSet(unsigned int vol, unsigned char dir);
    unsigned int nextChan(unsigned int chan, unsigned char dir);
    void errfm(void);
    unsigned char showVol(unsigned int volume);
    unsigned char showChan(unsigned int channel);
    unsigned int setScan(unsigned char dir);
    
    //
    // end receiveFM.h ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //
    //
    
    AR1010FM.C

    Code: Select all

    #include "i2c18f26k22.c"
    
    const unsigned int regDflt[18] = {
            0xFFFF,     // R0 -- the first writable register .  (disable xo_en)
            0x5B15,     // R1.
            0xD0B9,     // R2.
            0xA010,     // R3   seekTHD = 16
            0x0780,     // R4
            0x28AB,     // R5
            0x6400,     // R6
            0x1EE7,     // R7
            0x7141,     // R8
            0x007D,     // R9
            0x82C6,     // R10  disable wrap
            0x4F55,     // R11. <--- (disable xo_output)
            0x970C,     // R12.
            0xB845,     // R13
            0xFC2D,     // R14
            0x8097,     // R15
            0x04A1,     // R16
            0xDF6A      // R17
    };
    
    unsigned int regImg[18];        // FM register bank images
    unsigned int version;
    
    /*
     * manualTune() -  Manually tunes the channel
     *
     * @param dir Sets which way the frequency is changed, zero for up,
     *  nonzero for down.
     *
     * @param freq holds the frequency value.
     *
     * @return frequency on success or XF on error.
     *
     */
    // FM register bank default values -
    unsigned int manualTune(unsigned int freq, unsigned char dir) {
    
    
        switch (dir)
        {
            case TRUE : //manual up
                if(freq < FREQMAX) //checks that frequency is valid
                {
                    freq++;
                    FMfrequenc(freq); //sends incremented new value to FM chip
                } else {
                    freq = FREQMIN;
                    FMfrequenc(freq);
                }
                break;
    
    
            case FALSE : //manual down
                if(freq > FREQMIN)
                {
                    freq--;
                    FMfrequenc(freq);
                } else {
                    freq = FREQMAX;
                    FMfrequenc(freq);
                }
                break;
    
            default :
                errfm(); // Call error subroutine
                break;
        }
    
        return freq;
    }
         
    /*
     * FMwrite() -  Write a two byte word to the FM module.  The new
     * register contents are obtained from the image bank.
     *
     * @param adr The address of the register in the FM module that needs
     * to be written.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMwrite(unsigned char adr) {
    
            char value[4];
            unsigned int  regstr;
            unsigned char firstByt;
            unsigned char secndByt;
            unsigned char rpy;
    
            firstByt = regImg[adr] >> 8;
            secndByt = regImg[adr];
    
            My_I2C1_Start();                                        // Begin I2C communication
            My_I2C1_Idle();
    
            // Send slave address of the chip onto the bus
            
            if (My_I2C1_Write(FMI2CADR)) return XF;
            My_I2C1_Idle();
            My_I2C1_Write(adr);                                // Adress the internal register
            My_I2C1_Idle();
            My_I2C1_Write(firstByt);                        // Ask for write to FM chip
            My_I2C1_Idle();
            My_I2C1_Write(secndByt);
            My_I2C1_Idle();
            My_I2C1_Stop();
            My_I2C1_Idle();
            return XS;
    }
    
    
    /*
     * FMread - Read a two byte register from the FM module.
     *
     * @param regAddr The address of the register in the module that needs
     *        to be read.
     *
     * @param data Where to store the reading.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMread(unsigned char regAddr, unsigned int *data_) {
            char value[8];
            unsigned char firstByt;
            unsigned char secndByt;
            My_I2C1_Start();                                        // Begin I2C communication
    
            My_I2C1_Idle();                                        // Allow the bus to settle
    
            // Send address of the chip onto the bus
    
            if (My_I2C1_Write(FMI2CADR)) return XF;   //  return 0
    
            My_I2C1_Idle();
            My_I2C1_Write(regAddr);              // Adress the internal register
            My_I2C1_Idle();
            My_I2C1_Restart();                   // Initiate a RESTART command
            My_I2C1_Idle();
            My_I2C1_Write(FMI2CADR | DEVRD);  //(FMI2CADR + DEVRD)Ask for read from FM chip
            My_I2C1_Idle();        
            firstByt = My_I2C1_Read();           // Returns the MSB byt      e
            My_I2C1_Idle();
            My_I2C1_ACK;                          // Send back Acknowledge
            My_I2C1_Idle();
            secndByt = My_I2C1_Read();           // Returns the LSB of the temperature
            My_I2C1_Idle();
            My_I2C1_NACK();
            My_I2C1_Idle();
            My_I2C1_Stop();
            My_I2C1_Idle();
            *data_ = firstByt;
            *data_ <<= 8;
            *data_ = *data_ | secndByt;
            version=*data_;
            return XS;
    }
    
    /*
     * FMready - See if the FM module is ready.
     *
     * @param rdy Where to store the busy/ready status.  Will become
     * non-zero if the chip is ready, zero if busy.
     *
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMready(unsigned int *rdy) {
    
            unsigned int sts;
    
            if (FMread(FMCHIPSTSADR, &sts)  != XS) return XF;
            sts &= FMASKSTATUS;
            *rdy = sts ? TRUE : FALSE;
    
            return XS;
    }
    
    /*
     * FMinit() -  Initialise the FM module.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMinit() {
    
            unsigned char ad;
            unsigned int dat;
    
            // Copy default FM register values to the image set -
            for(ad = 0; ad < 18; ad++) regImg[ad] = regDflt[ad];
    
            dat = regImg[0];
            regImg[0] &= ~1;
            if (FMwrite(0) != XS) return  XF;
            for(ad = 1; ad < 18; ad++) {
                    if (FMwrite(ad) != XS)return XF;
            }
    
            regImg[0] = dat | 1;
            if (FMwrite(0) != XS) return XF;
            Delay_ms(20);//dly(20);
            while (FMready(&dat), !dat) Delay_ms(2);            //dly(2);
            return XS;
    }
    
    
    /*
     * FMfrequenc(f) -  Tune the FM module to new frequency.
     *
     *
     * @param f The new frequency as a multiple of 100 kHz.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMfrequenc(unsigned int f) {
            char value[8];
            unsigned int dat;
            unsigned int cn;                // AR1010 channel number
    
            cn = f - 690;
    
            // NB AR1010 retunes on 0 to 1 transition of TUNE bit -
            regImg[2] &= ~FMASKTUNE;
            if (FMwrite(2) != XS)
                return XF;
            regImg[2] &= 0xfe00;
            regImg[2] |= (cn | FMASKTUNE);
            if (FMwrite(2) != XS)
                return XF;
    
            do {
                    Delay_ms(2); //dly(2);
                    if (FMready(&dat) != XS)  // return 0
                        return XF;
            } while (!dat);
    
            return XF;  // Code will never get to here.
    }
    
    
    
    /*
     * FMvers - Obtain the FM chip version.
     *
     * @param vsn Where to store the version number.  Will become
     * 0x65B1 for vintage 2009 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMvers(unsigned int *vsn) {    // vsn=55
           
            char temp;
            char value[4];
    
            temp=FMread(FMCHIPVERSADR, vsn);  // FMCHIPVERSADR=0x1C
            if (temp  != XS) return XF;
    
            return XS;
    }
    
    /*
     * FMstrength() -  Get the signal strength.
     *
     * @param strength Where to store the signal strength.
     * The strength is a 7 bit number.
     *
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned char FMstrength(unsigned int *strength) {
    
    	if (FMread(FMCHIPSTRNGTH, strength) != XS) return XF;
    	*strength >>= 9;
    	return XS;
    }
    //
    // end FMstrength
    
    
    /*
     * FMid - Obtain the FM chip ID.
     * * @param id Where to store the ID number.  Will become
     * 0x1010 for AR1010 devices.
     *
     * @return XS on success or XF on error. *
     */
    unsigned char FMid(unsigned int *id) {
    
            if (FMread(FMCHIPIDADR, id)  != XS) return XF;
    
            return XS;
    }
    
    /*
     * volSet() -  Changes the volume
     *
     * @param dir Sets which way the volume is changed, TRUE for up,
     *  FALSE for down.
     *
     * @param vol holds the volume value.
     *
     * @return volume on success. On failure, enter error loop.
     *
     */
    
    unsigned int volSet(unsigned int vol, unsigned char dir) {
    
    
    
        switch (dir)
        {
            case TRUE : //volume up
                if(vol < 18) //checks that new volume is valid
                {
                    vol++;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    /* OR the mask with the current regImg value */
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
    
                    FMwrite(3); /*Calls function FMwrite to write new volume values to the FM chip*/
                    FMwrite(14);
    
                }
                break;
    
            case FALSE :
                if(vol > 0)
                {
                    vol--;
    
                    /* Clear the volume bits but leave other bits intact */
                    regImg[3] &= VOL1_MASK;
                    regImg[14] &= VOL2_MASK;
    
                    regImg[3] |= volumePair[0][vol];
                    regImg[14] |= volumePair[1][vol];
                    FMwrite(3);
                    FMwrite(14);
                }
                break;
    
    
            default :
                errfm();
                break;
        }
    
        return vol;
    }
    
    
    
    /*
     * nextChan() -  Tune to the next channel.
     *
     * @param up Set to TRUE for next channel up,
     *  FALSE for preset down.
     *
     * @return XS on success or XF on error.
     *
     */
    unsigned int nextChan(unsigned int chan, unsigned char dir) {
    
            switch (dir)
        {
            case TRUE : //manual up
                if(chan < 5) //checks that the selection is valid ***NOTE CHANGE****
                {
                    chan++;
                    FMfrequenc(station[chan]); //sends stored value to FM chip
                } else {
                    chan = 0;
                    FMfrequenc(station[chan]);
                }
                break;
    
    
            case FALSE : //manual down
                if(chan > 0)
                {
                    chan--;
                    FMfrequenc(station[chan]);
                } else {
                    chan = 5;
                    FMfrequenc(station[chan]);
                }
                break;
    
            default :
                //errfm();
                break;
        }
    
        return chan;
    
    }
    
    /*
     * setScan() -  Scan up or down
     *
     * @param dir Sets which way to scan, zero for up,
     *  nonzero for down.
     *
     * Returns the new frequency
     */
    unsigned int setScan(unsigned char dir) {
       char value[8];
       unsigned int dat;
       unsigned int chanRgstr;
       int reg3Wrd;
    
       regImg[1] |= 0x0002; // Set hmute
       FMwrite(1);
    
       regImg[2] &=0xFDFF; //Clear Tune bit
       FMwrite(2);
    
    
       regImg[3] &=0xBFFF;  // Clear Seek Bit 1011111111111111
       FMwrite(3);
    
       regImg[3] |= 0x4000; // Set SEEK bit   0100000000000000
    
       regImg[3] |= 0x2000; // Set spacing    0010000000000000
    
        if(dir == 1)
            //regImg[3] |= 0x8000; //If dir is 1, set SEEKUP bit 1000000000000000
            regImg[3] |= 0x8010; //Set SEEKUP/SEEKTH !!!TWEAK SEEKTH 1000000000010000
        else
            //regImg[3] &= 0x7FFF; //Otherwise clear to seek down.3FFF 0111111111111111
            regImg[3] &= 0x4000;
            
       regImg[3] &= 0xE7FF; // Clear BAND  E700   1110011111111111
    
       regImg[3] &= 0xFF80; // Mask all but seek threshold  FF80;  0001110000000000
       regImg[3] |= 0x0040; // Set seek threshold(soglia ricerca)  0000000001000000
    
       regImg[10] |= 0x0008; // Set wrap bit     0000000001000000
       FMwrite(10); // Write the bits to memory
    
       FMwrite(3);
    
       /* Now wait until finished scanning */
        do {
                Delay_ms(2);
                if (FMready(&dat) != XS) return XF;  //XS=0 XF=1
        } while (!dat);
    
        /* Read new channel */
       if ( FMread(READCHAN_ADR, &chanRgstr) == XF)
           errfm();
    
       chanRgstr >>= 7;
       chanRgstr &= 0x01FF; // Ensure that all bits apart from READCHAN are clear
    
       regImg[2] &= 0xFE00; //Mask off CHAN
       regImg[2] |= chanRgstr; // OR with current channel
       FMwrite(2);
    
       chanRgstr += 690;
    
       regImg[1] &= 0xFFFD; // Clear hmute
       FMwrite(1);
    
       return chanRgstr;
    }
    
    

    little Main:
    Interrupt Timer0 not important you can delete it !!

    Code: Select all

    /////////////////////////// AR1010 FR RECEIVER TEST ///////////////////////
    //         18F26K22  INTERNAL CLOCK 16MHZ X 4 PLL = 64MHZ
    // ORIGINAL PROJECT LINK : https://github.com/joshtyler/PIC-FM
    //
    // PIN OUT:
    // AR1010 FM RECEIVER --> SDA - SCL PINS
    // UART1              --> ON UART1 PINS
    //
    //
    // NOTES:
    // _asm bsf LATA,1;
    // _asm bcf LATA,1;
    //
    ///////////////////////////////////////////////////////////////////////////
    
    #define debug1   // coment line if no not want dedug on UART1
    
    // SSD1306 OLED reset pin definition (if available)
    #define SSD1306_RST       RC5_bit    //RD4_bit
    #define SSD1306_RST_DIR   TRISC5_bit      //TRISD4_bit
    
    // SERVICE COSTANT DEFINITIONS
    #define MAX_LEN1 128
    #define MIN_LEN1 50
    #define CR 0x0D
    #define CLS 12
    
    // LINK TO EXTERNAL LIBRARY
    #include <stdbool.h>
    #include "fm.h"
    #include "AR1010FM.c"
    
    
    char txt[11];
    unsigned char count10us,count100us,count10ms,count1sec;
    unsigned char loop_time_sync;
    
    
         ////////////////////////////////////////////////////
          /////////////// INTERRUPT SECTION ////////////////
         ///////////not necessary for this test/////////////
    
     void interrupt() iv 0x0008 ics ICS_AUTO /* Receive ISR routine void interrupt ISR()*/
      {
         if (TMR0IF_bit){
             //INTERRUPT EVERY 10US
             TMR0IF_bit = 0;
             TMR0L         = 0x60;
             //Enter your code here
             count10us++;
             //if(count10us >=5) count50usBit=1;
             if(count10us >=10){  //if reached 100us
               count10us=0;
               count100us++;
               if(count100us>=100) {     //if reached 10ms
                 count100us=0;
                 loop_time_sync++;
                 count10ms++;
                 if(count10ms>=100){ //if reached 1sec
                   count10ms=0;
    
                   if(count1sec<60) {
                     count1sec++; //_asm btg LATA,1;
                     }  // btg = toggle bit  redled1
                   else count1sec=0;
                  }
                }
             } //END if(count10us.....
          } // END TIMER 1 INTERRUPT
    
      }  // END GLOBAL INTERRUPT
    
    
    void InitTimer0(){
      T0CON         = 0xC8;
      TMR0L         = 0x60;
      GIE_bit         = 1;
      TMR0IE_bit         = 1;
    }
    
         ////////////////////////////////////////////////////
           /////////// END INTERRUPT SECTION //////////////
         ////////////////////////////////////////////////////
    
    
    
    void clear_screen(){ UART1_Write_Text("\033"); UART1_Write_Text("[2J"); }
    
    void errfm(){
    UART1_Write_Text("!!!! AR1010 FM ERROR !!!!! \r\n");
    }
    
    
    // main function
    void main()
    {
      char value[8];
      char value2[4];
      unsigned char evt;
      unsigned int ui, strength;
      unsigned int freq = 930;//875; //Stores frequency
      unsigned int vol = 10; //Stores volume
      unsigned int chan = 0; //Stores channel
    
      // internal FOSC 16MHz x 4PLL => 64MHz
       OSCCON.IRCF2=1;
       OSCCON.IRCF1=1;
       OSCCON.IRCF0=1;
       OSCTUNE.PLLEN=1;
        OSCTUNE.SCS1=1;   // Set interinal clk block
       //OSCCON2.MFIOSEL = 0;
       //OSCTUNE.INTSRC = 1;
       
      //TRISA=0b00000000;
      //PORTA=0;
     // Disable comparators
      C1ON_bit = 0;
      C2ON_bit = 0;
      CM1CON0=0;
      CM2CON0=0;
      ANSELA = 0b00000001; // select ch0 for SpectrumAnalizer
      ANSELB = 0x00;  // configure all PORTB pins as digital
      ANSELC = 0X00; // configure all PORTc pins as digital
      TRISA = 0b00011101; // set A0 as input, A1....A7  as output
      TRISB = 0b00000000; // set RB2,RB3,TB4 OUTPUT, Other RB5....RB77 as output
      //TRISC = 0b00000111; // set C0,C1,C2 as input, C3....C7  as output
    
      PORTA=0; PORTB=0; PORTC=1;
    
      ///////////////////////////// INIT TIMER 0 ///////////////////////////
       InitTimer0();   // NOT NECESSARY IN THIS TEST
       /////////////////////////////////////////////////////////////////////
      Delay_ms(500);     // wait a second
      My_I2C1_Master_Init();// initializ I2C commun with clock frequency of 400kHz
      Delay_ms(200);
      UART1_Init(9600);
      //clear_screen();
      UART1_Write(CLS);   // Erase screen terminal  :it is an option on Vbray Terminal!
      #ifdef debug1
      UART1_Write_Text("Start debug: \r\n");
      #endif
    
      FMvers(&ui);        // Check we have comms with FM chip (ver=0x10FF)
      #ifdef debug1
      IntToHex(version, value);UART1_Write_Text("Value: ");
      UART1_Write_Text(value);
      IntToHex(ui, value);UART1_Write_Text(" ui: ");
      UART1_Write_Text(value);UART1_Write_Text("\r\n");
      #endif
                         //  was this my version chip address
      if (ui != 0x10FF) errfm();
            
      if (FMinit()!= XS) errfm();  //XS=0
      
       if (FMstrength(&strength)!= XS) errfm();
          IntToStr(strength, value);
          UART1_Write_Text(value);UART1_Write_Text("\r\n");
                   
      FMfrequenc(freq);    // Initialise frequency
      vol=volSet(18,true);   // Initialise volume to 10
      #ifdef debug1
      UART1_Write_Text("Volume:  ");IntToStr(vol, value);
      UART1_Write_Text(value);
      #endif
      while(1) {
                         //// FUNCTIONS YOU CAN USE /////
                                //FMstrength(&strength);	// strength=FM Signal Level.
                                
                                //showChan(chan);
                                //showVol(vol);
                                
                                // Select Channel up and return Chan number                                                                    case BUTN2 : //preset up
                                //chan=nextChan(chan, true);
                                //freq = station[chan];
                                
                                // Select Channel up and return Chan number
                                //chan=nextChan(chan, false);
                                //freq = station[chan];
                                
                                // change and return frequency turned up
                                //freq=manualTune(freq, true);
    
                                // change and return frequency turned down
                                //freq=manualTune(freq, false);
    
                                // change and return increase volume up
                                //vol=volSet(vol, true);
                                
                                // change and return decrease volume up
                                //vol=volSet(vol, false);
    
                                // scan up frequencies and return frequency
                                //freq = setScan(true);
    
                                // scan down frequencies and return frequency
                                //freq = setScan(false);
    
      }  // end while(1);
    
    }
    // end of code.
    
    UART1 OUTUT:

    Code: Select all

    Start debug:
    Version Chip: 10FF ui: 10FF
    Volume:      18
    
    .......enjoy........
    Attachments
    AR1010-TEST-UART1.zip
    (89.1 KiB) Downloaded 62 times
    Last edited by leo73 on 29 Mar 2021 17:39, edited 8 times in total.

    paulfjujo
    Posts: 1558
    Joined: 24 Jun 2007 19:27
    Location: 01800 St Maurice de Gourdans France
    Contact:

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #6 Post by paulfjujo » 18 Mar 2021 12:27

    Hello,


    Bravo,
    Plus1.jpg
    Plus1.jpg (9 KiB) Viewed 2910 times
    Good job ..

    Question:
    could this device cover range 107 to 110 MHz ( for Aviation , or other specifique usage ) ?

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #7 Post by leo73 » 18 Mar 2021 19:58

    Hello paulfjujo,
    Yes i tried now to change

    Code: Select all

     #define FREQMAX                 1100
    but to understand if it really works :D
    we must stop a bad noise (like ambulance) over all frequencies (in audio signal), i think could be I2C bus, but i don't any idea how filter it. I tried to mounted 100nF between gnd and v+ of fm module but noise not stop!!!!
    How can i do ?
    Attachments
    My test board, the long wires green and white between 2 breadboard are the I2C bus
    My test board, the long wires green and white between 2 breadboard are the I2C bus
    P_20210318_200116_1.jpg (1.91 MiB) Viewed 2905 times
    Last edited by leo73 on 20 Mar 2021 18:15, edited 3 times in total.

    paulfjujo
    Posts: 1558
    Joined: 24 Jun 2007 19:27
    Location: 01800 St Maurice de Gourdans France
    Contact:

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #8 Post by paulfjujo » 19 Mar 2021 08:26

    Hello,

    i think you have too much wires , and 2 breadboard !
    => difficult to get a good common GROUND ..for all devices and power supply

    Try to add 100nF accross all devices , and 100µF + 220nF+ 100pF accross main power supply. ( 3 different capactors to cover larger spectre of frequency)
    Use a thicker wires to link GND and +Vcc on Breadboards ( or more than wire ) to reduce line impedance ..

    and with breadboard, take care about parasite capacitor existing between 2 colums of breadboard contacts
    mesured ~1,5pF
    => mixing signal between 2 concomitant pins of MCU or other devices .

    maybe you can have also a too hig gain amplifier on FM receiver => oscillations .

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #9 Post by leo73 » 19 Mar 2021 18:22

    I put all the capacitors you told me on the main power supply and on all the devices, enlarged the sections of the power cables between the two breadboards but the ambulance sound doesn't stop. Come to think of it, the sound is similar to that of the beep of a clock radio. Is this sound expected in the register of the module? Maybe you can disable this beep on the log! but what is the name of this parameter in the registry?

    paulfjujo
    Posts: 1558
    Joined: 24 Jun 2007 19:27
    Location: 01800 St Maurice de Gourdans France
    Contact:

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #10 Post by paulfjujo » 19 Mar 2021 18:45

    leo73 wrote:
    19 Mar 2021 18:22
    ... but what is the name of this parameter in the registry?

    i don't know if a register like this exist ...


    Has your FM receiver an antenna ?
    are you hearing a VOR balise or ILS station ( Aviation range 108,00 MHz et 117,95 MHz in France) ?

    A low frequency amplifier ( Ampli BF) can produce bips, if enter in oscillation mode ..
    coupling output to input trough wire proximity or via parasite capacitor ( like breadboard colums!)
    you can reduce the gain , or reduce pass Band ( any pF accross on feeback loop amplifier ).

    do you have a global schematic with all components used in your application ?
    you can also try to use 2 power supply , one for MCU and Logic
    One for Analog amplifier .. and Ground (OV linked )

    IF your power supply is a DC/DC converter, use instead a classic linear power supply or a battery ..

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #11 Post by leo73 » 19 Mar 2021 20:16

    Has your FM receiver an antenna ? yes, i made it using one thin wire 1,5 meters, my antanna stay inside my house on my table.

    are you hearing a VOR balise or ILS station ( Aviation range 108,00 MHz et 117,95 MHz in France) ? No only Noise for this frequencies, probabily because my antenna stay inside house !!! , NO?

    do you have a global schematic with all components used in your application ?] No i did for a moment, only a block diagram of the project (the part of the mcu and the preamps is missing). Schematic and pcb only main board Mcu. (MCU, voltage regulator, connectors, rotary encoder and display), I did not draw schematic of signals IC yet (Fm module, stand alone bluetooth audio receiver, rca connectors, sound processor audio ctrl PT2322).

    you can also try to use 2 power supply , one for MCU and Logic One for Analog amplifier .. and Ground (OV linked )
    I used a 9v battery as TL082 aop power but noise no stop.

    If I disconnect the amplifier input the noise (beep) stops.
    I noticed something about the noise (beep), if I turn up the volume of the FM module the amplitude of the noise (beep) is constant and it no longer covers the music !!!
    The amplifier has a fixed gain of 20x, the maximum amplitude audio output of the module is 100mv.
    The amplifier (TL082) according to these tests is fine !! do not you think?

    I attach the noise audio file, then I turn up the volume and the music will cover the noise after I return off volume and noise return. The recording is not good because I could only connect a pair of headphones to the preamp (TL082). Then I held the headphones close to the phone's microphone:
    Attachments
    NoiseVoce.zip
    (351.26 KiB) Downloaded 76 times
    Last edited by leo73 on 24 Mar 2021 20:58, edited 1 time in total.

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #12 Post by leo73 » 20 Mar 2021 11:22

    To remove the background noise I found, on web a diagram of the AR1010 module, putting a 2.2uF capacitor and a 47uH inductance in series with the headphone output, the noise (beep) goes away.
    I tried and it works !!!!!!!
    UPDATE: 20.MAR.2021 10:30
    Anyway I guess the problem is the headphone amplifier wobbling (as Pauljujo said), I have to make one on printed circuit board.
    Two doubts:
    1) I have to check the cutoff frequency of the filter because I want to be sure that some frequencies in the audio signal are not removed.
    2) I want to be sure that the filter works even if I connect an amplifier to the output of it instead of headphones. (Headphones have a lower input inductance than an amplifier input)
    UPDATE: 20.MAR.2021 13.00
    I used a preamplifier for headphones on printed circuit (without using the filter shown in the picture), the noise is now very slight it is perceived only at zero volume. Anyone have other suggestions?
    Attachments
    do not take the diagram as a reference for a possible connection between the devices. it's not very reliable.
    do not take the diagram as a reference for a possible connection between the devices. it's not very reliable.
    AR1010_NO-Noise.jpg (119.26 KiB) Viewed 2796 times
    Last edited by leo73 on 21 Mar 2021 22:31, edited 3 times in total.

    paulfjujo
    Posts: 1558
    Joined: 24 Jun 2007 19:27
    Location: 01800 St Maurice de Gourdans France
    Contact:

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #13 Post by paulfjujo » 21 Mar 2021 16:48

    hello,

    is there a mistake on schematic ?

    why antenna input is linked to commun headphones connector ..
    GND must be connected directly to Gnd Headphones
    you can also add some 100nf accros IN and OUT of ASM117 3,3V regulator

    if you have only 3,7V ( because battery connected) as voltage input for regulator 3,3V
    is is not enough to get a good control of Output voltage 3,3V for OLED and FM receiver ..
    you need a minimum of 4V or 5 V Dc.

    what is the board TP4056 ?? (difficult to read details) used for ??
    is it an USB power supply ?
    a discharged battery can consume many mA !

    leo73
    Posts: 252
    Joined: 09 Jan 2014 15:45

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #14 Post by leo73 » 21 Mar 2021 21:38

    Paulfjujo wrote:
    why antenna input is linked to commun headphones connector ..
    Because this connection is for use hear phone cable as Antenna.

    Do not worry !! it's not my circuit diagram, it was just an example to understand how to filter out the noise better. Now I write it in the forum. Tomorrow I will try to use a ribbon bus for the i2c signal (low parasitic capacity).
    Last edited by leo73 on 24 Mar 2021 20:47, edited 2 times in total.

    Sparky1039
    Posts: 1179
    Joined: 24 Nov 2005 20:07
    Location: Colorado, USA

    Re: FM Receiver AR1010 I2C problem <1ST VER SOLVED> update:17.Mar.2021

    #15 Post by Sparky1039 » 23 Mar 2021 18:14

    Tomorrow I will try to use a ribbon bus for the i2c signal (low parasitic capacity).

    This will help. You should also try placing ground on each side of I2C lines as you wire the ribbon cable (i.e. 3 ground lines). Lastly, you might try placing a small amount of resistance in series with the I2C lines at the master (PIC). 10-22 ohms resistance range should suffice. With that huge rats nest of wires all that stray inductance is ringing out rich in harmonics that will cause more noise to couple into other circuits. The added resistance will help dampen the ringing a bit on the fast I2C pulses. Just make sure you place them after the I2C pull-up resistors.

    Post Reply

    Return to “mikroC PRO for PIC General”