nobcha a
Published © GPL3+

Remodel the air band receiver kit with digital local VFOⅡ

This project is the follower of the previous project of “Remodel the air band receiver kit with digital local VFO”.

IntermediateWork in progress24 hours178
Remodel the air band receiver kit with digital local VFOⅡ

Things used in this project

Hardware components

Rotary Encoder with Push-Button
Rotary Encoder with Push-Button
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

R909-VFO circuit for debugging use

This time I had diverted the PCB as the VFO portion of R909-DSP 4732 radio.

Block Diagram

Let combine the Chinese air band receiver kit with the Si5351a digital VFO.

Code

the air band receiver kit with digital local VFO Ⅱ

C/C++
This time I had diverted the PCB as the VFO portion of R909-DSP 4732 radio. There is truncated below sketch. The full of that is "https://github.com/Nobcha/R909-VFO/blob/main/Changed%20to%20KPA-5351%20%20sketch.txt ".
// CN-AB-Radio_No3 v1.1
//
//  TO BE REVIEWD put/get freq long
//
// 2024.07.14 released
//  Si5351a library changed to <si5351.h>
// Remained issues & progress
//  1. 5351 freq correction   for future study
//  2. Not deleted FM function
//
// Based on R909-SDR-1602 radio V2.2
// si5351a ARDUINO LO  Ver3.0 (LCD&KEY, Timer)
// Rotary encoder:INT(D2,D3), RE-SW: A0, F-switch: A2, AGC:A3
// Si5351_ADDR = 0x60, CPU:Arduino pro mini or UNO, LCD:1602
//  LCD display 0123456789abcdef
//              AM 100.000000MHz
//              FUN833kHz S#####
// lcd 16x2  with 4 bit address

#define lcdTypeLCD4bit

//Libraries definition
#include <EEPROM.h>
#include <Rotary.h>
#include <si5351.h>    // <si5351JBH.h> L1204 void @20240714
#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"

Adafruit_LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

//initialise object SI5351 pll
Si5351 si5351;         // start the object for the si5351
#define XT_CAL_F 37000 //Si5351 calibration factor, adjust to get exatcly 10MHz. 
                       //Increasing this value will decreases the frequency and vice versa.

//pins assign
#define RESW A0        // Rotary encoder push switch A0 
#define REA 2          // D2 2
#define REB 3          // D3 3
#define FUNC_SW A2     // SW1:<80, SW2:<250, SW3:<430, SW4:<600  --> append
#define AGC_port A3    // A3 port connects with AGC node

// #define BANDRLY  5     // digital output to control relay
#define SQLMUTE  4     // digital output SQUELCH MUTE  - MUTE AMP WHEN NO SIGNAL 
#define led_pin A1     // Panel orange LED
#define lcd_bl  7      // LCD back light

unsigned long int startF = 78000000; // Changed to 78MHz of Japanese FM starting
unsigned long int rxclk =  10700000; // 10.7Mhz

// #define Si5351_ADDR 0x60
// #define Si4732_ADDR 0x11   // 

// Assign function number short/long pushing
// 12 modes defined 0:no,1:FR,2:ST,3:FU,4:FU,5:FU,6:MEM,7:SC,
//  8:FR_set,9:ST_set,10:Mem_put,11:SC_auto
// adding 2 MODES volume and squelch
// 
// 2024.05.05 Neglect volume, band, and squelch
#define NONE 0          //
#define FREQ 1
#define STEP 2
#define VOLUME 3
#define SQUELCH 4
#define BAND 5          // AM/FM SELECTION 
#define MEMORY 6
#define SCAN 7
#define FREQSET 8       // double push for FREQ set
#define STEPPUT 9       // double push for STEP set
#define MEMORYPUT 10    // double push for memory F set
#define SCANAUTO 11     // double push for Automatic SCAN set
#define FUNCTION 12

// EEPROM Address
#define FREQ_AD 0       // EEPROM address for FREQ data as long
#define FSTEP_AD 4      // EEPROM address for FSTEP data as long 
#define VOL_AD 400      // EEPROM ADDRESS for stored volume 
#define SQU_AD 404      // EEPROM address for squelch setting 
#define BAND_AD 406     // EEPROM ADDRESS for band 
#define previous_freqFM_AD 408 // EEPROM ADDRESS for previous_freqFM
#define previous_freqAM_AD 412 // EEPROM ADDRESS for previous_freqAM
#define MCHAN0 8        // MCHAN start ADD, MCHAN0 + 4 * chan  chan: 0- 50 

//
#define Time_elapsedRSSI 300  // RSSI check period mS

// Band AM or FM on Si4732
#define AM_FUNCTION 1
#define FM_FUNCTION 0

/*
  Rotary encoder handler for arduino. v1.1
  Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3. Contact: bb@cactii.net  
  http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
  Rotary encoder test debug sketch
  PWM/3: Rotary A --> D2
  PWM/2: Rotary B --> D3
  GND: C
*/
#define HALF  // better 
Rotary r = Rotary(REA, REB);

  // functions
  void LCD_Disp ( char, char, char*);
  void Step_Disp(void);
  void Dsp_Disp(void);
  void LongToStr(long , char*);
  void Fdds_Space(char *);
  //void set_freq(unsigned long);
  void si5351_init(void);
  //void cmd_si5351(char , char);
  int function_key(void);
  int mode_define(unsigned char) ;
  void s_meter_disp(void);
  void TimerCount(void);
  void blink(long, long);
  void putFirstSettings(void) ;
  void ShowSettings(void);
  void getSettings(void);
  void Band_Disp(void);
  void send_frequency(long, int);
  void Vol_Disp(void);
  void Squ_Disp(void);
  void squ_disp(void);
  void Band_disp(void);
  void clearLCDLine (int, int, int);
  void checkVolLimits(void);
  void checkSquLimits(void);
  void checkRX2(void );
  void checkRX(void);
  void updateFreq(long);
  void setVol(void);
  void freqEEPROMput(int, long*);
  void freqEEPROMget(int, long);  
  void setVolume (uint8_t );
 
// variables
volatile boolean if_mode = 1;         //  1:LO mode 10.7MHz above
volatile unsigned char mode = FUNCTION;   //  select mode as FREQ
volatile unsigned char mode_last = FREQ;
volatile unsigned char mode_temp = FREQ;
volatile char memo_ad = 0;            //  select  memory address
unsigned char  set_sw = 1;            //  set freq on memory, or step to freq
volatile unsigned long int freq1, freq0, freq_0, freq_last;

volatile unsigned long int previous_freqFM = 80200000;   // FM802
volatile unsigned long int previous_freqAM = 118100000;  //ITM TOWER
volatile unsigned long int fstep ;
volatile unsigned long int_time = 0 ;
volatile unsigned long time0 = 0;
volatile unsigned long time1 = 0;
volatile long  Last_millis;
int Timer_LED = 1000;
int Timer_mash_i = 500;
int Timer_mash = 0;
int Timer_RESW_i = 50;
int Timer_RESW = -1;
int Timer_scan = -1;
volatile boolean j;                   // led/LCD blinking status
volatile int ADCdata;
volatile char scan_ad = 0, scan_ad_last=0;   //  scanning address counter
volatile char i = 0;
volatile unsigned char re_result = 0;    // Rotary switch active result 0x10:right,0x20:left
volatile unsigned char result;
char squdisp[4] = {0x53, 0x51, 0x55, 0}; // displays SQU SQUELCH LEVEL
char voldisp[4] = {0x56, 0x4f, 0x4c, 0}; // displays VOL
char mdisp[4] = {0x4d, 0x45, 0x4d, 0};   // displays  MEM
char stepdisp[4] = {0x53, 0x54, 0x50, 0 };   //STP
char spdisp[4] = { 0x20, 0x20, 0x20, 0 };    // SPACE
char scandisp[4] = { 0x53, 0x43, 0x4e, 0 };  //SCN
char freqdisp[4] = { 0x46, 0x52, 0x51, 0 };  //FRQ
char funcdisp[4] = { 0x46, 0x55, 0x20, 0 };  //FU
char ascandisp[4] = { 0x41, 0x53, 0x41, 0 }; // ASA
char banddisp[4] = { 0x42, 0x4e, 0x44, 0 };  // BND


boolean RESW_last = 1;
boolean RESW_value_last = 1;
boolean RESW_pending = 0;
int RESW_result_p;
volatile unsigned char SW_result = 0, SW_result0 = 0; //  no:0, pending:1, one:2, double:3
volatile unsigned int sw_value, sw_stat;

uint8_t VolumeLevel = 15;
uint8_t last_VolumeLevel = 15;   // Added 20221010

int8_t SquelchLevel = 0;
int8_t last_SquelchLevel = 0;    // Added 20221010

boolean BandSelect = false, BandSelect_last= false;      // am/fm:false
boolean last_BandSelect = true;  // am:true/fm:false

// LCD SECOND LINE DOUBLE USE
boolean valid = false;
unsigned long previousMillis = 0;
const long interval = 5000;      //5 seconds
unsigned long elapsedRSSI;


// for squelch audio detection
int val = 0;
int timer = 0;
int maxi = 0;
unsigned char s_value;
boolean  s_dot_disp = 1;         // S-Meter bargraph
unsigned char rssi, snr;

////////////////// Si4732/////////////////
#include <SI4735.h>

#define RESET_PIN 17
#define FM_STATION_FREQ 8020     // 80.2 MHz - Select FM802

// SI4735 rx;

// Rotary SW functions  Interrupt handler
ISR(PCINT2_vect) {
  re_result = r.process();       // DIR_CW=0x10,DIR_CCW=0x20
}

// Power up setting section
void setup() {
  // configure the pins
  pinMode(led_pin, OUTPUT);      // monitor LED
  digitalWrite( led_pin, 1 );    // on
  pinMode(lcd_bl, OUTPUT);       // LCD back light
  digitalWrite( lcd_bl, 1 );     // on
  
  pinMode(RESET_PIN, OUTPUT);
  digitalWrite(RESET_PIN, HIGH);

  pinMode(REA, INPUT_PULLUP);    // Rotary encoder port  
  pinMode(REB, INPUT_PULLUP);    // 
  pinMode(RESW, INPUT_PULLUP);   // Rotary encoder push SW
  //pinMode(BANDRLY, OUTPUT);    // relay band selection
  //digitalWrite (BANDRLY, LOW); //  

  pinMode(AGC_port, INPUT);
  
  pinMode(SQLMUTE, INPUT_PULLUP);  // amp mute when no signal detected

  // Initialize 4bit  LCD
  lcd.begin(16, 2);              // initialise the LCD

  // Start up message for 1602A
  lcd.setCursor( 0, 0);
  lcd.print("CN-AB-Radio_No3 ");
  lcd.setCursor( 4, 1);
  lcd.print("Version 1.10");
  
  delay(2000);
  lcd.clear();
  Serial.begin(9600);
  Serial.println("\nCN-AB-Radio_No3 V1.10");

 
  /////// Switch sence ////////////////////////////////////////////////////////
  SW_result0 = function_key();         // Freq mode set on power start
  if (SW_result0 == 0) if_mode = 1;    // When no action, set IF_mode as 10.7MHz on LO

  r.begin(true);                       // rotary encoder initialise
  Last_millis = millis();

  LCD_Disp ( 0, 0, "Loading ...") ;

  delay(50);
  
  // EEPROM data recover for clock frequency data
  // There are FREQ, FSTEP, and MCHAN0-9
  freqEEPROMget( FREQ_AD, freq1);      // FREQ data  recover from EPROM

  EEPROM.get( FSTEP_AD, fstep);        // fstep data from EEPROM Read
  
 // Newly added 2022.09.16       **********
  EEPROM.get( VOL_AD, VolumeLevel);    // volume data  recover from EPROM
  EEPROM.get( SQU_AD, SquelchLevel);   // squelch data from EEPROM Read
  EEPROM.get( BAND_AD, BandSelect);    // band data  recover from EPROM
//  Newly added 2022.10.11       **********
  EEPROM.get( previous_freqFM_AD, previous_freqFM );    // 
  EEPROM.get( previous_freqAM_AD, previous_freqAM );    // 
   

  int d = digitalRead(RESW);
  if (d == 0) {
    putFirstSettings();
    LCD_Disp ( 0, 0, "Writing Defaults to EEPROM") ;
  }

  getSettings();
  //  setVol();            // set volume with eeprom value
  // ShowSettings();
  // BandSelect = false;   // fm mode
  Dsp_Disp();              // display freq
  freq_0 = freq1 + rxclk;

  // Serial.print("\nFreq sent to SI5351 = ");
  // Serial.println(freq_0);
  si5351_init();           // initialise the si5351


  if (freq1 < 10000000 || freq1 > 200000000) { //10-200MHz
    LCD_Disp ( 0, 0, "Freq Read Error  ") ;
    Serial.println("\nFreq Read Error");
    Serial.println(freq1);
    freq1 = 118100000;
    putFirstSettings();

    EEPROM.put( FREQ_AD, freq1);      // FREQ data  100MHz for EPROM
    freq_0 =  118100000;              // changed 118.1MHz AM
    for ( memo_ad = 0 ; memo_ad < 50; memo_ad++ ) {
      EEPROM.put( FREQ_AD + 8 + memo_ad * 4, freq_0); // FREQ data  100MHz for eEPROM
    }
  }

//  digitalWrite (BANDRLY, HIGH);          //  
  delay(500);

#ifdef lcdTypeLCD

  //    lcd.PageClear() ;
  lcd.clear();                          // Once display off
#endif

  pinMode(lcd_bl, OUTPUT);              // LCD back light
  digitalWrite( lcd_bl, 1 );            // on
  
  delay(500);
  if ( fstep == 1000 || fstep == 10000 || fstep == 100000 ||
       fstep == 25000 || fstep == 1000000 || fstep == 8333) {
  }
  else {
    LCD_Disp ( 0, 1, "Step Read Error") ;
    Serial.println("\nStep Read Error");
    Serial.println(fstep);
    fstep = 100000;
    EEPROM.put( FSTEP_AD, fstep );      // fstep data 100kHz for EEPROM
    delay(500);
  }

  // Set INT for RE
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);   sei();

  // volume
  //rx.setVolume(VolumeLevel);    // Range 0-63

  // Display initializing
  Dsp_Disp();                     // Display current FREQ

  Step_Disp();                    // Display current step FREQ

  Band_Disp();                    // Display current Band

  if (if_mode == 1) freq_0 = freq1  + rxclk  ; //  On IF mode FREQ must be 21.4MHz upper tahn RX FREQ

  freq_0 = freq1 + rxclk  ;       // UPDATE the freq

  if (BandSelect == true) {       // AM mode
 //   digitalWrite (BANDRLY, HIGH);
 //   set21400kHz();              // Change to AM 21.4MHz mode
    send_frequency(freq_0, 0);    //send it to si5351
  }
  else {
//    digitalWrite (BANDRLY, LOW);
//    setFMfreq(freq1/10000);     // Change to FM mode  

    Serial.print("FM-F:");
    Serial.print(freq1/1000);    
  }

  delay(500);

  // debug print out
      Serial.print("j: ");        // LCD blinking status
      Serial.println(j);
      Serial.print("mode: ");
      Serial.println(mode);
      Serial.print("mode_temp: ");
      Serial.println(mode_temp);
      Serial.print("SW_result: ");
      Serial.println(SW_result);
      Serial.print("SW_result0: ");
      Serial.println(SW_result0);
      
      Serial.print("freq1: ");
      Serial.println(freq1);  
       
}
// End of setup


//= =========================MAIN===================================
void loop() {
  TimerCount();

  // Basic function for timer control led on_off & LCD blink
  blink(200, 800);               // Turn on 1sec/off 0.5sec by monitor LED and FUNC on LCD on/off

  // Check SW action
  SW_result = function_key();           //  Get RESW result(on:50mS push)
  SW_result0 = mode_define(SW_result);  //  Define SW status 0:no, 1:single, 2:double

  // if (SW_result0 > 1)   Serial.println(SW_result0);    // debug
  //  RE push switch to FUNC mode, push switch again to each mode
  if (SW_result0 == 1) {
    if (mode != FUNCTION)  {    //  Go into FUNC mode
      mode_last = mode;
      mode = FUNCTION;          //0:no,1:FR,2:ST,3:ME,4:SC,5:FSet,6:STSet,7:MWrite,
                                // 8:AScan,9:vol,10 squelch , 11 band, 12 func
    }
    else {                      //  If FUNC, every click goes each FUNC defined
      mode_last = mode;
      mode = mode_temp;

    }
  }
  if ( SW_result0 == 2 ) {      //  select double click
    mode_last = mode_temp;      // double push

// To define mode by RE push switching **********
    switch (mode_temp) {
      case FREQ:{
        mode = FREQSET;         // freq, vol, squ and band set
        break;
      }
      case STEP:{
        mode = STEPPUT;         // STP set
        break; 
      }
      case MEMORY:{
        mode = MEMORYPUT;       // Memory set
        break;
      }
      case SCAN:{
        mode = SCANAUTO;        // Automatic scanning
        break;    
      }
      default:
        mode = FUNCTION;        // Go back to FUNC
    }
  }
// RE push ***************************

  //  Each function for each mode
  // clear the line
  // LCD_Disp ( 0, 1, "    ") ;
  int eachdisp;
  switch ( mode ) {
    
    case FUNCTION: {                     // function mode is 12 
        if (j == 0) {                    // boolean j led/LCD state
          switch ( mode_temp ) {    
            case FREQ: {                 //  FREQ determining mode 1
                eachdisp = freqdisp;
                break;
              }
            case STEP: {                 //  STEP select mode 2
                eachdisp = stepdisp;     
                break;
              }
           
/*            case VOLUME: {                 //  volume select mode 10
                eachdisp = voldisp;   
                break;
              }
            case SQUELCH: {                //  squelch select mode 11
                eachdisp = squdisp;              
                break;
              }
            case BAND: {                   //  band select mode 12
                eachdisp = banddisp;                   
                break;
              }
*/              
              
            case MEMORY: {                 //  MEMORY ch select mode 3
                eachdisp = mdisp ;
                break;
              }
            case SCAN: {                   //  SCAN select mode 4
                eachdisp = scandisp ;
                break;
              }
            // next were added later
            default: eachdisp =  funcdisp;  //  Function select mode 9
          }
        }    
          if (j == 1) eachdisp =  funcdisp; //  LCD blink
      }
        LCD_Disp ( 0, 1, eachdisp ) ;
        break;
      
    case FREQ: {                         //  FREQ determining mode 1
        LCD_Disp ( 0, 1, freqdisp ) ;
        Step_Disp();
        break;
      }
    case STEP: {                         //  STEP select mode 2
        LCD_Disp ( 0, 1, stepdisp ) ;
        Step_Disp();
        break;
      }

/*    case VOLUME: {                       //  volume select mode 10
        LCD_Disp ( 0, 1, voldisp ) ;
        Vol_Disp();
        break;
      }
    case SQUELCH: {                      //  squelch select mode 11
        LCD_Disp ( 0, 1, squdisp ) ;
        Squ_Disp();
        break;
      }
     band
    case BAND: {                         //  band select mode 12
        LCD_Disp ( 0, 1, banddisp ) ;
        Band_Disp();       
        break;
      }
      */

    case MEMORY: {                       //  MEMORY ch select mode 3
        LCD_Disp ( 0, 1, mdisp ) ;
        break;
      }

    case SCAN: {                         //  Manual step SCAN
      //  fm mode to be added
        LCD_Disp ( 0, 1, scandisp ) ;
        scandisp[1] = 0x30 | (scan_ad / 10) ;     //  display scan chan
        scandisp[2] = 0x30 | (scan_ad % 10) ;
        clearLCDLine(6, 1, 4);
        
        freqEEPROMget( MCHAN0 + scan_ad * 4, freq1); // read out MEM frequency
        
        if (freq_last == freq1)  break;

        if (BandSelect != BandSelect_last){
          Band_Disp();
          BandSelect_last=BandSelect;
        }
        Dsp_Disp();
        freq_0 = freq1 + rxclk  ;
        if (if_mode == 1) freq_0 = freq1  + rxclk  ; // FREQ is more than 10.7MH above on RX FREQ
 
        freq_last = freq1 ;
        if(BandSelect == false) {    // If FM mode, 
          setFMfreq(freq1/10000);    //
        }
        else send_frequency(freq_0, 0); //send it to si5351
        break;
      }

    case FREQSET: {                      //  FREQ button long push 
        LCD_Disp ( 0, 1, spdisp) ;       //  2nd line 1st character space display
        delay(500);
        LCD_Disp ( 0, 1, freqdisp) ;     //  2nd line 1st character freq display
        
        freq0 = freq1;
        if(BandSelect == false) freq0 = -freq1;  // If FM convert to negative
        EEPROM.put( FREQ_AD, freq0 );    // freq data into EEPROM

        EEPROM.put( VOL_AD, VolumeLevel);    // volume data  recover from EPROM
        EEPROM.put( SQU_AD, SquelchLevel);   // squelch data from EEPROM Read
        EEPROM.put( BAND_AD, BandSelect);    // band data  recover from EPROM

        EEPROM.put( previous_freqFM_AD, previous_freqFM );    // 
        EEPROM.put( previous_freqAM_AD, previous_freqAM );    // 


 // ***************
   
        mode = FREQ;
        break;
      }
    case STEPPUT: {                      //  STEP written  
        LCD_Disp ( 0, 1, stepdisp) ;     // 2nd line 1st character space display
        EEPROM.put( FSTEP_AD, fstep );   //  fstep data 100kHz for EEPROM
        delay(500);
        LCD_Disp ( 0, 1, spdisp) ;       //  2nd line 1st character space display
        delay(500);
        LCD_Disp ( 0, 1, stepdisp) ;     //  2nd line 1st character step display

        mode = STEP;
        break;
      }
    case MEMORYPUT: {                    //  MEMORY write  
        LCD_Disp ( 0, 1, mdisp) ;        //  line 2 first column is m
        
        freq0 = freq1;
        if( BandSelect == false) freq0 = -(freq1);
        EEPROM.put( MCHAN0 + memo_ad * 4, freq0); // Write FREQ data on defined EEPROM

        delay(500);
        LCD_Disp ( 0, 1, spdisp) ;       //  line 2 first column is space
        delay(500);
        LCD_Disp ( 0, 1, mdisp) ;        //  line 2 first column is m

        mode = MEMORY;
        break;
      }
    case SCANAUTO: {                       //  AUTO SCAN mode from M-chan
        if (Timer_scan <= 0) {             //  If timer up
          Timer_scan = 100;
          ascandisp[1] = 0x30 | (scan_ad / 10) ;   //  display scanning channel
          ascandisp[2] = 0x30 | (scan_ad % 10) ;   //  display scanning channel
          LCD_Disp ( 0, 1, ascandisp ) ;
          clearLCDLine(6, 1, 4);
         
          freqEEPROMget( MCHAN0 + scan_ad * 4, freq1); // read out MEM frequency

          scan_ad++;                        // Changed 20201013
          if (scan_ad > 49) scan_ad = 0;
                    
          if (freq1 == 118000000){          // 118mhz
            Timer_scan = 0;
            break;                          // If 118MHz, then skip.
          }
          if(BandSelect == false ){         // If FM, skip FM freq
            BandSelect = true;
            Timer_scan = 0;
            break;  
          }  
          
          Dsp_Disp();
          Band_Disp();      

          if (if_mode == 1) freq_0 = freq1 + rxclk  ; //  IFモード時は10.7MH上位を発振
          send_frequency(freq_0, 0);        //send it to si5351
          delay(300);
          
          s_meter_disp();                   // Get  voltage & change S-meter
          if ( s_value > SquelchLevel ) Timer_scan = 2000 ; // If squelch off, wait 1 sec
        }
        break;
      }
  }
  // re_result was set in ISR
  if (SW_result0 == 1) re_result = 0;       // If SW pending, depress RE function

  if (re_result  )  {                       // CW 0x20 ? CCW 0x10?

    // clean the band area
    clearLCDLine (3, 1, 6);
    Band_Disp();
    
    // mode= 0:no,1:FR,2:ST,3:ME,4:SC,5:FSet,6:STSet,7:MWrite,8:AScan,9:FU

    // Need to add 8.333kHz mode 2024.05.05
    if ((mode == FREQ) && (re_result == 0x10 ) ) {  // clockwise FREQ
      freq1 = freq1 + fstep;
      if(freq1%10 == 9) freq1=freq1+1;  // To tune 3*3=9 -> 10

            
      // limit the frequency according to the band
      if (BandSelect == false) { // fm mode
        if (freq1 > (long) 109000000) {      //  109MHz -> 76MHz
          freq1 = (long)   109000000;        //
          Dsp_Disp();
        }
      }
      if (BandSelect == true) { // am mode
        if (freq1 > (long) 136000000) {      //  136MHz -> 118MHz
          freq1 = (long)   136000000;
          Dsp_Disp();
        }
      }

      freq_0 = freq1;
      if (if_mode == 1) {
        freq_0 = freq1  + rxclk  ;           // on IF mode 10.7MH upper
      }
      //SI_setfreq(freq_0);

      //  Serial.print("freq_0 :");
      // Serial.println(freq_0);
      Dsp_Disp();
      Step_Disp();
      freq_0 = freq1 + rxclk  ;

      if (BandSelect == true) {
        set21400kHz();               // Change to AM 21.4MHz mode
        send_frequency(freq_0, 0);   //send it to si5351
      }
      else {
         setFMfreq(freq1/10000);     // Change to FM mode 
//           Serial.print("FM-F:");
//        Serial.print(freq1/1000);     
      }
    }

    // Need to add 8.333kHz mode 2024.05.05
    else if ((mode == FREQ) && (re_result == 0x20) ) { //counter clockwise FREQ
      freq1 = freq1 - fstep;
      if(freq1%10 == 1) freq1=freq1-1;  // To tune 10 - 3*3=1 -> 0
      
      if (BandSelect == false) {     // fm mode
        if (freq1 < 76000000) {      // 76MHz->118MHz
          freq1 = 76000000;

          Dsp_Disp();
          Step_Disp();
        }
      }
      if (BandSelect == true) {      // am mode
        if (freq1 < 118000000) {     // 118MHz->
          freq1 = (long)   118000000;

          Dsp_Disp();
          Step_Disp();
        }
      }
      freq_0 = freq1  + rxclk  ;     //  on IF mode 10.7MH upper
      //SI_setfreq(freq_0);
      if (BandSelect == true) {
         set21400kHz();              // Change to AM 21.4MHz mode
        send_frequency(freq_0, 0);   //send it to si5351
      }
      else {
        setFMfreq(freq1/10000);      // Change to FM mode      
//        Serial.print("FM-F:");
//        Serial.print(freq1/1000);
      }
      Dsp_Disp();
      Step_Disp();
    }
    else if ((mode == STEP) && (re_result == 0x10) ) { // clockwise STEP
      if (fstep == 25000) fstep = 8333;  // 25kHz -->8.333kHz
      else if (fstep == 8333){
        fstep = 1000;                // 8.333kHz-->1kHz
      }
      else {
        fstep = fstep * 10;          // 1kHz-->10kHz-->100kHz-->1MHz
      }
      if (fstep > 1000000)  fstep = 25000; // 1MHz-->25kHz
      Step_Disp();
    }
    else if ((mode == STEP) && (re_result == 0x20 )) { // counter clockwise STEP 
      if (fstep == 25000)  fstep = 1000000;   // 25000-->1MHz
      else if (fstep == 8333)  fstep = 25000;   // 8.333kHz-->25kHz
      else fstep = fstep / 10;
      if (fstep < 1000)  fstep = 8333; // 1kHz-->8.3335kHz     
      Step_Disp();
    }
    else if ((mode == MEMORY) && (re_result == 0x10 )) { // clockwise STEP
      memo_ad ++ ;
      if (memo_ad > 49)  memo_ad = 0;
      mdisp[1] = 0x30 | (memo_ad / 10) ;
      mdisp[2] = 0x30 | (memo_ad % 10) ;
      LCD_Disp ( 0, 1, mdisp) ;       // #13 LED on/off in turn
    }
    else if ((mode == MEMORY) && (re_result == 0x20 )) { // Counter clockwise STEP 
      memo_ad --;
      if (memo_ad < 0)  memo_ad = 49;
      mdisp[1] = 0x30 | (memo_ad / 10) ;
      mdisp[2] = 0x30 | (memo_ad % 10) ;
      LCD_Disp ( 0, 1, mdisp) ;
    }
    else if ((mode == SCAN) && (re_result == 0x10 )) {   // clockwise STEP
      scan_ad ++;
      if (scan_ad > 49)  scan_ad = 0;
      scandisp[1] = 0x30 | (scan_ad / 10) ;
      scandisp[2] = 0x30 | (scan_ad % 10) ;
      clearLCDLine(6, 1, 4);  
      LCD_Disp ( 0, 1, scandisp) ;
    }
    else if ((mode == SCAN) && (re_result == 0x20 )) {   // Counter clockwise STEP 
      scan_ad --;
      if (scan_ad < 0)  scan_ad = 49;
      scandisp[1] = 0x30 | (scan_ad / 10) ;
      scandisp[2] = 0x30 | (scan_ad % 10) ;
      clearLCDLine(6, 1, 4);
      LCD_Disp ( 0, 1, scandisp) ;
    }

     
    else if ((mode == FUNCTION) && (re_result == 0x10 )) {// clockwise VOLUME
      mode_temp ++;
      if (mode_temp > 7) mode_temp = 7; //5
      // clearLCDLine(0, 1, 15);
    }
    else if ((mode == FUNCTION) && (re_result == 0x20 )) {// Counter clockwise function
      mode_temp --;
      if (mode_temp < 1) mode_temp = 1; //4
      // clearLCDLine(0, 1, 15);
    }
  }
  re_result = 0;
  
  // S METER & squelch
  // CHECK TIMER FOR TIMEOUT
  if (( millis() - elapsedRSSI ) > Time_elapsedRSSI ){
    s_meter_disp();
    elapsedRSSI = millis();
    
  // Squelch 
    if(SquelchLevel>rssi){
      pinMode (SQLMUTE, INPUT_PULLUP);    // Mute the amp  STILL POP NOISE
      digitalWrite (led_pin, LOW);        //  LED OFF
    }
    else {
      pinMode(SQLMUTE, OUTPUT);
      digitalWrite (SQLMUTE, LOW);        // Activate the amp
      digitalWrite (led_pin, HIGH);       //  LED ON
    }
  }

  // SW1:<80, SW2:<250, SW3:<430, SW4:<600 
  // actual 0, 166, 356, 519
  if (analogRead(FUNC_SW) < 800) {
    delay(50);
    sw_value = analogRead(FUNC_SW);
    sw_stat = map(sw_value, 0, 450, 1, 4); 

    
    switch ( sw_stat){
      case 1:
        mode = FREQ;           // freq mode
        break; 
      case 2:   
        mode = STEP;           // STEP mode
        break;      
      case 3: 
        mode = SCAN;           // SCAN mode
        break;
      case 4:   
        mode = MEMORY ;        // Memory mode
        break;   
    }

    digitalWrite(led_pin, 1);

  }

}
//end of loop

// *************************************
// *************************************



//  ************************************
//   FUNCTIONs
//  ************************************

// Band select for R909(AM/FM relay change)
void Band_Disp() {
  if( last_BandSelect != BandSelect){
    if (BandSelect == true) {
//    LCD_Disp ( 13, 0, "AM");
//    switch on the band relay
//      digitalWrite (BANDRLY, HIGH);
//      set21400kHz();             // Change to AM 21.4MHz mode
    //freq1 = 118000000;

    }
    else if (BandSelect == false) {
 //     LCD_Disp ( 13, 0, "FM");
 //     switch off the relay
 //     digitalWrite (BANDRLY, LOW);
 //     setFMfreq(freq1/10000);     // Change to FM mode      

    }
    last_BandSelect = BandSelect ;
    delay(100);                     // Wait relay operating time
  }
// Pad the "s" spaces from line/col "clearLCDLine(col, line, s);"  
//  clearLCDLine(6, 1, 4);  
  Dsp_Disp();
  
}

// eeprom functions  
void getSettings() {

  freqEEPROMget( FREQ_AD, freq1);         // FREQ data  recover from EPROM
  EEPROM.get( FSTEP_AD, fstep);           // fstep data from EEPROM Read
  EEPROM.get( VOL_AD, VolumeLevel);       // volume data  recover from EPROM
  EEPROM.get( SQU_AD, SquelchLevel);      // squelch data from EEPROM Read
  EEPROM.get( BAND_AD, BandSelect);       // band data  recover from EPROM

  EEPROM.get( previous_freqFM_AD, previous_freqFM );    // 
  EEPROM.get( previous_freqAM_AD, previous_freqAM );    // 
}

void putFirstSettings() {

  freq0 = freq1;  
  if( BandSelect == false) freq0 = -(freq1);
  EEPROM.put( FREQ_AD, freq0);            // FREQ data  100MHz for EPROM

//  freqEEPROMput(FREQ_AD, freq1);        // Put freq1 + BAND on EEPROM
  EEPROM.put( FSTEP_AD, fstep);           // fstep data from EEPROM Read
  EEPROM.put( VOL_AD, VolumeLevel);       // volume data  recover from EPROM
  EEPROM.put( SQU_AD, SquelchLevel);      // squelch data from EEPROM Read
  EEPROM.put( BAND_AD, BandSelect);       // band data  recover from EPROM
//  Newly added 2022.10.11       **********
  EEPROM.put( previous_freqFM_AD, previous_freqFM );    // 
  EEPROM.put( previous_freqAM_AD, previous_freqAM );    // 
  
  freq_0 =  118000000;
  
  for ( memo_ad = 0 ; memo_ad < 50; memo_ad++ ) {
    EEPROM.put( FREQ_AD + 8 + memo_ad * 4, freq_0); // FREQ data  AM 118.1MHz for EEPROM
  }
  freq_0 =  118100000;
  EEPROM.put( FREQ_AD + 8 , freq_0);         // FREQ data  FM 118.1MHz for EEPROM #0
  
  freq_0 =  -80200000;
  EEPROM.put( FREQ_AD + 8 + 49 * 4, freq_0); // FREQ data  FM 80.2MHz for EEPROM #49
  freq_0 =  -85100000;
  EEPROM.put( FREQ_AD + 8 + 48 * 4, freq_0); // FREQ data  FM 85.1MHz for EEPROM #48
  delay(500);
}

// Long FREQ data changes to 10 digit numerics
void LongToStr(long dat, char *fm) {
  long fmdat;
  int i;
  
  fmdat = dat;
  
  for (i = 0; i < 11; i++) {
    fm[10 - i] = ( fmdat % 10 ) | 0x30;
    fmdat = fmdat / 10;
  }
}


// Reducing preceding zero into space
void  Fdds_Space(char *fm) {
  int i;
  for (i = 0; i < 10; i++) {
    if ( fm[i] == 0x30) {
      fm[i] = 0x20;
    }
    else i = 11;
  }
}


// Function SEL determining  D4 port: RE push SW
// result 0:no key, 1:off-> on

int function_key() {
  result = 0;
  //  SW sensing to avoid chattering
  if (Timer_RESW <= 0) {
    boolean RESW_value = digitalRead(RESW);
    if ((RESW_value == 0) && (RESW_value_last == 1)) {
      Timer_RESW = Timer_RESW_i;
      RESW_value_last = 0;
      result = 1;
    }     if ((RESW_value == 1) && (RESW_value_last == 0)) {
      Timer_RESW = Timer_RESW_i;
      RESW_value_last = 1;
      result = 0;
    }
    RESW_value_last = RESW_value;
  }
  return result ;                 // Switch not settled 20201002
}

// After key result(RESW_click), wait timer_mash. Then decide single/double
// result 0:no key, 1:off-> on pending, 2:single click, 3:double click
int mode_define(unsigned char keyresult) {
  char result = 0;
  // To detect double click  Detect double within a cirtain second
  // After keyresult = 1;
  // waiting double click  (Timer_mash > 0): mash pending
  if ((Timer_mash > 0) && (keyresult == 1)) {       // Double RESW pushed
    RESW_result_p = 2;
  }
  else if ((Timer_mash <= 0) && (keyresult == 1)) { // Firstly RESW pushed
    Timer_mash = Timer_mash_i;     // Mash timer set
    RESW_result_p = 1;             // Once set single click
  }
  // waiting timer end
  else if (( Timer_mash <= 0 ) && (RESW_result_p >= 1)) {
    result = RESW_result_p;        // Stop to wait & report result
    RESW_result_p = 0;
  }
  return result;
}

// Timing managing function: When Time_value <= 0, timer expired
void TimerCount(void) {
  long Current_millis = millis();
  long time_dif = Current_millis - Last_millis;   // Calculate how many millis after last call
  Last_millis = Current_millis;                   // Remember current time
  if (Timer_mash > 0) Timer_mash = Timer_mash - time_dif; // To wait double click timing
  if (Timer_RESW > 0) Timer_RESW = Timer_RESW - time_dif; // To avoid chattering
  if (Timer_LED > 0) Timer_LED = Timer_LED - time_dif;    // To turn on/off for #13 LED
  if (Timer_scan > 0) Timer_scan = Timer_scan - time_dif;
}

//  LED#13 on/off & LCD blink:j
void blink(long on_time, long off_time) {  // #13 LED monit on_off, j effects FUNC on/off
  if ((Timer_LED <= 0) && (j == 1)) {
...

This file has been truncated, please download it to see its full contents.

Credits

nobcha a
7 projects • 3 followers
I'm interested in designing a radio with Si4732 and Si5351a.

Comments