nobcha a
Published

To widen the Si4732/35 radio coverage Ver1: airband

Si4732/35 are a cool device. To widen its frequency coverage and sensitivity, I will add the TA2003 mixer.

IntermediateWork in progress24 hours327
To widen the Si4732/35 radio coverage Ver1: airband

Things used in this project

Hardware components

ATmega328
Microchip ATmega328
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Panel portion for debugging

ATmega328P, the rotary encoder, 1602A, and OLED

RF circuit diagram

circuit diagram

Code

R909-DSP-1602 version

C/C++
// SNR,RSSI SQU ok 2023.12.18
// R909-SDR-1602 radio V2.2  
// 4 function key added 2023.12.18
//
//
// R909OLED_test1 to be  202310.29 pending
//  1. 5351 freq tune 8.333    for future study
//  2. VOL from FM62429 to Si4732  OK
//  3. S-meter from AGC to Si4732 RSSI
//  4. AM set for 21.4MHz/AM on Si4732  AM mode
//  5. FM tune  If FM call FM tune  F display
//  6. signal band width change  for future
//
// Issues & progress
//  1. 5351 freq tune 8.333    for future study
//  2. Band width change  for future
//
// 
// si5351a ARDUINO LO  Ver3.0 (LCD&KEY, i2c SSD1306 LCD, Timer
// Rotary switch:INT(D2,D3), Function switch: D4 port, Squelch:A3
// Si5351_ADDR = 0x60, CPU:Arduino PRO mini, LCD: SSD1306:
//           Nextly replace Arduino into PRO MINI and case in
//  LCD display 0123456789abcdef
//  SSD1306     FRQ  100.000MHz
//              ATS00 STP100kHz
//              S**********  IF

// lcd 16x2  with 4 bit address

#define lcdTypeLCD4bit

//Libraries definition
#include <EEPROM.h>
#include <Rotary.h>
#include <si5351JBH.h>
#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 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
#define FUNC_SW A2     // SW1:<80, SW2:<250, SW3:<430, SW4:<600  

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

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

// Assign function number short/long pushing
// 8 modes defined 0:no,1:FR,2:ST,3:ME,4:SC,5:FS,6:STS,7:MS,8:ASC,9:FU
// adding 2 MODES volume 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 );
  void set21400kHz (void);
  void set802MHz (void);
  void setFMfreq (uint16_t );
  
// variables
volatile boolean if_mode = 1;         //  1LO 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 = 0;
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(SQLMUTE, INPUT_PULLUP);       // amp mute when no signal detected
//    digitalWrite (SQLMUTE, LOW);          // UNMute the amp

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

  // Start up message for 1602A
  lcd.setCursor( 0, 0);
  lcd.print("R909-SDR-1602   ");
  lcd.setCursor( 4, 1);
  lcd.print("Version 2.00");
  
  delay(2000);
  lcd.clear();
  Serial.begin(9600);
  Serial.println("\nR909-SDR-1602 Radio V2.00");

////////////// 4732 set up section ///////////
  int16_t si4735Addr = rx.getDeviceI2CAddress(RESET_PIN);
  if ( si4735Addr == 0 ) {    // 4732 address check  0x11 expected
    lcd.setCursor( 4, 1);
    lcd.print("Not find Si4732 ");    
    Serial.println("\nCan't find 4732");   
    while (1);
  }


  rx.setup(RESET_PIN, AM_FUNCTION);   //  Starts default radio function 
  delay(500);

  rx.setVolume(10);           // once set Range 0-127
  delay(500);
  set21400kHz();              // Set Si4732 as 21.4MHz mother radio
 
  /////// 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 == 10000000) {
  }
  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();
  /*
      Serial.print("j: ");
      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);
  */
  // 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 scan chan
          ascandisp[2] = 0x30 | (scan_ad % 10) ;   //  display scan chan
          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  ; //  IF10.7MH
          send_frequency(freq_0, 0);        //send it to si5351
          delay(300);
          
          s_meter_disp();                      // Get AGC 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  )  { // Left 0x20 ? Right 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
    if ((mode == FREQ) && (re_result == 0x10 ) ) {  // clockwise FREQ
      freq1 = freq1 + fstep;
      
      // 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);     
      }
    }
    else if ((mode == FREQ) && (re_result == 0x20) ) { //counter clockwise FREQ
      freq1 = freq1 - fstep;
      
      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 = 100;   // 25000-->100
      fstep = fstep * 10;
      if (fstep > 10000000)  fstep = 100; // 100-->1000
      if (fstep == 100)  fstep = 25000;   // 100-->25000
      Step_Disp();
    }
    else if ((mode == STEP) && (re_result == 0x20 )) { // counter clockwise STEP
      if (fstep == 25000)  fstep = 100;   // 25000-->100
      fstep = fstep / 10;
      if (fstep < 100) fstep = 10000000;  //  100-->1000
      if (fstep == 100)  fstep = 25000;   // 100-->25000
      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) ;
    }
       
  //volume 0 is minimum 63 is max  VolumeLevel
    else if ((mode == VOLUME) && (re_result == 0x10 )) { // counter clockwise VOLUME
      rx.volumeUp();      // Range 0-63
      VolumeLevel = rx.getVolume();
      Vol_Disp();         // show volume level on display        
    }
    else if ((mode == VOLUME) && (re_result == 0x20 )) { //  clockwise VOLUME
      rx.volumeDown();
      VolumeLevel =  rx.getVolume();
      Vol_Disp();           // show volume level on display
    }
    
  //squelch 0 is minimum 63 is max
    else if ((mode == SQUELCH) && (re_result == 0x20 )) { // counter clockwise VOLUME
      //  LCD_Disp ( 2, 3, "SQU:") ;
      SquelchLevel =  SquelchLevel - 1;
      checkSquLimits();
      Squ_Disp();  // show squelch level on display

    }
    else if ((mode == SQUELCH) && (re_result == 0x10 )) { //  clockwise VOLUME
      // LCD_Disp ( 2, 3, "SQU:") ;
      SquelchLevel =  SquelchLevel + 1;
      checkSquLimits();                  // #1380
      Squ_Disp();  // show squelch level on display
    }
    else if ((mode == BAND) && (re_result )) { 
 
      // counter clockwise or clockwise band
      // changed the BandSelect 
      BandSelect = !BandSelect ;  // AM->FM or FM->AM
      
 // AM mode selected   
      if( BandSelect == true ){   // Change from FM to AM
        previous_freqFM = freq1;
        
        if ( previous_freqAM != freq1){
          freq1 = 118000000;

        }
        else {
          freq1 = previous_freqAM; // store the current AM freq
        }
      }
  // FM mode selected
      else {                      // Change from AM to FM
        previous_freqAM = freq1;  // store the current AM freq
        
        if ( previous_freqFM != freq1){
          freq1 = (long)76000000;
       
        }
        else {
          freq1 = previous_freqFM;
        }
      }
      Dsp_Disp();             // Update the display
      
      freq_0 = freq1  + rxclk  ;  //  on IF mode 10.7MH upper
      //SI_setfreq(freq_0);
      send_frequency(freq_0, 0);  //send it to si5351
      Band_Disp();                // show BAND on display
      Dsp_Disp();                 //update the frequency according to the band selected
    }
       
    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); 

    /*
      Serial.print("F-SW ADC:");
      Serial.print(sw_value);  
      Serial.print(" F-SW:");
      Serial.println(sw_stat); 
    */
     
    switch ( sw_stat){
      case 1:
        mode = FREQ;           // freq mode
        break; 
      case 2:   
        mode = STEP;           // STEP mode
        break;      
      case 3: 
        mode = VOLUME;         // VOLUME mode
        break;
      case 4:   
        mode = SQUELCH;        // SQUELCH mode
        break;   
    }

    digitalWrite(led_pin, 1);
    delay(150);
  }

}
//end of loop

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



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

// Band.ino  2022/08/18
void Band_Disp() {
  if( last_BandSelect != BandSelect){
   
// clearLCDLine(10,0,5);
  
    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();
  
}


// display.ino   2022/08/14  ****************************************
//#define lcdTypeOled
//#define lcdTypeLCD
//#define lcdTypeLCD4bit

// EEprom.ino   **************************************
// eeprom functions  2022/07/19

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 );    // 
...

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

Credits

nobcha a

nobcha a

4 projects • 2 followers
I'm interested in designing a radio with Si4732 and Si5351a.
Thanks to PU2CLR and Dr.Uebo.

Comments