/* * This project is a tri digital oscillator using a si5351a break out board. * The arduino Uno is used with the LCD Keypad shield unit. * * Ideas for this project is for a single or twin or a tri vfo single source for RF measurements. * Such measurements are perhaps intermodulation calculations for both RX and TX tests. * * May perhaps also RX signal I.F. bandwidth measurements and also perhaps AF filtering tests using * an RF signal source at the antenna input of the radio. * * Code written by Alastair GW0AJU * * date :- 8th May 2018 * updated : 21st May 2019 * * Note: I have left the "Serial.print" commands within the coding for code fault * finding should users experience code faults with the program. */ // include the library code: #include #include #include #include "si5351.h" Si5351 si5351; long sig_gen_freq; //************ vfo A ************ long start_freq_one; long carrier_centre_one; long frequency_one; int address_vfo_one = 0; int address_step_one = 6; long ch_step_one; long freq_one; long VFO_freq_set_one; float freq_math_one; //************* vfo B *********** long start_freq_two; long carrier_centre_two; long frequency_two; int address_vfo_two = 10; int address_step_two = 16; long ch_step_two; long freq_two; long VFO_freq_set_two; float freq_math_two; // ******* vfo C ************* long start_freq_three; long carrier_centre_three; long frequency_three; int address_vfo_three = 20; int address_step_three = 26; long ch_step_three; long freq_three; long VFO_freq_set_three; float freq_math_three; // ***** analog port zero sample values for button selection ******* int right_button_low = 0; int right_button_high = 50; int up_button_low = 70; int up_button_high = 170; int down_button_low = 200; int down_button_high = 300; int left_button_low = 350; int left_button_high = 450; int select_button_low = 600; int select_button_high = 700; //******************************************************************* int address_step = 30; int bc_one; int bc_two; int bc_three; int bc_vfo; int key_delay = 250; // max limits of the si5351a digitql oscillator long f_max = 160e6; long f_min = 8e3; // initialize the library with the numbers of the interface pins LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //This function will write a 4 byte (32bit) long to the eeprom at //the specified address to address + 3. void EEPROMWritelong(int address, long value) { //Decomposition from a long to 4 bytes by using bitshift. //One = Most significant -> Four = Least significant byte byte four = (value & 0xFF); byte three = ((value >> 8) & 0xFF); byte two = ((value >> 16) & 0xFF); byte one = ((value >> 24) & 0xFF); //Write the 4 bytes into the eeprom memory. EEPROM.write(address, four); EEPROM.write(address + 1, three); EEPROM.write(address + 2, two); EEPROM.write(address + 3, one); } //This function will return a 4 byte (32bit) long from the eeprom //at the specified address to address + 3. long EEPROMReadlong(long address) { //Read the 4 bytes from the eeprom memory. long four = EEPROM.read(address); long three = EEPROM.read(address + 1); long two = EEPROM.read(address + 2); long one = EEPROM.read(address + 3); //Return the recomposed long by using bitshift. return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF); } void setup() { si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB); si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA); si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_2MA); si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_2MA); si5351.output_enable(SI5351_CLK0, 1); si5351.output_enable(SI5351_CLK1, 1); si5351.output_enable(SI5351_CLK2, 1); // calibration of vfo with digital frequency counter to test 25MHz crystal //si5351.set_freq(50000000, SI5351_CLK2); si5351.update_status(); Serial.begin(9600); // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.setCursor(0,0); lcd.print("Sig Gen Shield"); lcd.setCursor(0,1); lcd.print("Alastair GW0AJU"); delay(2000); Serial.println("reset start"); //Starting at the first byte on the eeprom. start_freq_one = EEPROMReadlong(address_vfo_one); if (start_freq_one > f_min && start_freq_one < f_max) { carrier_centre_one = start_freq_one; bc_one = EEPROM.read(address_step_one); } else { start_freq_one = 3.710e6; EEPROMWritelong(address_vfo_one, start_freq_one); carrier_centre_one = EEPROMReadlong(address_vfo_one); bc_one = 5; EEPROM.write(address_step_one, bc_one); bc_one = EEPROM.read(address_step_one); bc_vfo = 1; EEPROM.write(address_step, bc_vfo); bc_vfo = 1; bc_one = 4; } //Starting at the first byte on the eeprom. start_freq_two = EEPROMReadlong(address_vfo_two); if (start_freq_two > f_min && start_freq_two < f_max) { carrier_centre_two = start_freq_two; bc_two = EEPROM.read(address_step_two); } else { start_freq_two = 7.120e6; EEPROMWritelong(address_vfo_two, start_freq_two); carrier_centre_two = EEPROMReadlong(address_vfo_two); bc_two = 4; EEPROM.write(address_step_two, bc_two); bc_two = EEPROM.read(address_step_two); bc_vfo = 1; bc_one = 4; } //Starting at the first byte on the eeprom. start_freq_three = EEPROMReadlong(address_vfo_three); if (start_freq_three > f_min && start_freq_three < f_max) { carrier_centre_three = start_freq_three; bc_three = EEPROM.read(address_step_three); } else { start_freq_three = 14.25e6; EEPROMWritelong(address_vfo_three, start_freq_three); carrier_centre_three = EEPROMReadlong(address_vfo_three); bc_three = 3; EEPROM.write(address_step_three, bc_three); bc_three = EEPROM.read(address_step_three); bc_vfo = 1; bc_one = 4; } bc_vfo = EEPROM.read(address_step); selected_vfo(); // selection of vfo step Serial.println("reset start end"); } void loop() { vfo_selection(); delay(300); } void vfo_selection() { Serial.println("vfo_selection"); int xy; xy = analogRead (0); if (xy > 600 && xy < 660) { //lcd.print ("Select"); bc_vfo = bc_vfo + 1; if (bc_vfo == 5) // to detect if the bottom of band, them set to top range for down count { bc_vfo = 1; // reach bottom now starting from the top downwards } Serial.println(""); Serial.print("bc_vfo = "); Serial.print(bc_vfo); Serial.println(""); Serial.println(""); EEPROM.write(address_step, bc_vfo); selected_vfo(); // selection of vfo step } } void selected_vfo() { Serial.println("selected_vfo"); if (bc_vfo == 1 ) { lcd.home(); lcd.clear(); lcd.setCursor(0,0); lcd.print("Oscillator o/p's"); lcd.setCursor(0,1); lcd.print("disabled"); si5351.output_enable(SI5351_CLK0, 0); si5351.output_enable(SI5351_CLK1, 0); si5351.output_enable(SI5351_CLK2, 0); } else if (bc_vfo == 2 ) { lcd.home(); lcd.clear(); lcd.setCursor(0,0); lcd.print("A"); lcd.setCursor(13,0); lcd.print("KHz"); lcd.setCursor(0,1); lcd.print("inc/dec = "); si5351.output_enable(SI5351_CLK0, 1); si5351.output_enable(SI5351_CLK1, 1); si5351.output_enable(SI5351_CLK2, 1); carrier_centre_one = EEPROMReadlong(address_vfo_one); vfo_tune_one(); bc_one = EEPROM.read(address_step_one); selection_step_one(); keyboard_access_vfo_one(); } else if (bc_vfo == 3 ) { lcd.home(); lcd.clear(); lcd.setCursor(0,0); lcd.print("B"); lcd.setCursor(13,0); lcd.print("KHz"); lcd.setCursor(0,1); lcd.print("inc/dec = "); si5351.output_enable(SI5351_CLK0, 1); si5351.output_enable(SI5351_CLK1, 1); si5351.output_enable(SI5351_CLK2, 1); carrier_centre_two = EEPROMReadlong(address_vfo_two); vfo_tune_two(); bc_two = EEPROM.read(address_step_two); selection_step_two(); keyboard_access_vfo_two(); } else if (bc_vfo == 4 ) { lcd.home(); lcd.clear(); lcd.setCursor(0,0); lcd.print("C"); lcd.setCursor(13,0); lcd.print("KHz"); lcd.setCursor(0,1); lcd.print("inc/dec = "); si5351.output_enable(SI5351_CLK0, 1); si5351.output_enable(SI5351_CLK1, 1); si5351.output_enable(SI5351_CLK2, 1); carrier_centre_three = EEPROMReadlong(address_vfo_three); vfo_tune_three(); bc_three = EEPROM.read(address_step_three); selection_step_three(); keyboard_access_vfo_three(); } } void keyboard_access_vfo_one() { top_one: delay(key_delay); Serial.println("keyboard_access_vfo_one"); int x_one; x_one = analogRead (0); lcd.setCursor(10,1); if (x_one < right_button_high) { Serial.print ("Right "); bc_one = bc_one + 1; if (bc_one == 10) // to detect if the bottom of band, them set to top range for down count { bc_one = 1; // reach bottom now starting from the top downwards } EEPROM.write(address_step_one, bc_one); selection_step_one(); // selection of vfo step } else if (x_one > up_button_low && x_one < up_button_high ) { Serial.print ("Up "); // up band movement carrier_centre_one = carrier_centre_one + (1 * ch_step_one); // ch_step increments if ( carrier_centre_one >= f_max ) { carrier_centre_one = f_max; } EEPROMWritelong(address_vfo_one, carrier_centre_one); vfo_tune_one(); } else if (x_one > down_button_low && x_one < down_button_high ) { Serial.print ("Down "); // down band movement carrier_centre_one = carrier_centre_one - (1 * ch_step_one); // ch_step increments if ( carrier_centre_one <= f_min ) { carrier_centre_one = f_min; } EEPROMWritelong(address_vfo_one, carrier_centre_one); vfo_tune_one(); } else if (x_one > left_button_low && x_one < left_button_high ) { Serial.print ("Left "); bc_one = bc_one - 1; if (bc_one == 0) // to detect if the bottom of band, them set to top range for down count { bc_one = 9; // reach bottom now starting from the top downwards } EEPROM.write(address_step_one, bc_one); selection_step_one(); // selection of vfo step } else if (x_one > select_button_low && x_one up_button_low && x_two < up_button_high) { // lcd.print ("Up "); // up band movement carrier_centre_two = carrier_centre_two + (1 * ch_step_two); // ch_step increments if ( carrier_centre_two >= f_max ) { carrier_centre_two = f_max; } EEPROMWritelong(address_vfo_two, carrier_centre_two); vfo_tune_two(); } else if (x_two > down_button_low && x_two < down_button_high) { //lcd.print ("Down "); // down band movement carrier_centre_two = carrier_centre_two - (1 * ch_step_two); // ch_step increments if ( carrier_centre_two <= f_min ) { carrier_centre_two = f_min; } EEPROMWritelong(address_vfo_two, carrier_centre_two); vfo_tune_two(); } else if (x_two > left_button_low && x_two < left_button_high) { // lcd.print ("Left "); bc_two = bc_two - 1; if (bc_two == 0) // to detect if the bottom of band, them set to top range for down count { bc_two = 9; // reach bottom now starting from the top downwards } EEPROM.write(address_step_two, bc_two); selection_step_two(); // selection of vfo step } else if (x_two > select_button_low && x_two < select_button_high) { vfo_selection(); } goto top_two; } void vfo_tune_two() { Serial.println(" vfo_tune_two"); frequency_two = carrier_centre_two; VFO_freq_set_two = frequency_two * 100ULL; si5351.set_freq(VFO_freq_set_two, SI5351_CLK1); si5351.update_status(); lcd.setCursor(2,0); lcd.print(" "); lcd.setCursor(2,0); freq_math_two = frequency_two/1e3; lcd.print(freq_math_two,3); } void selection_step_two() // to change the hf band of operation { Serial.println("selection_step_two"); if (bc_two == 1 ) { ch_step_two = 5e6; // 5KHz vfo increment lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("5MHz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 2 ) { ch_step_two = 1e6; // 5KHz vfo increment lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1MHz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 3 ) { ch_step_two = 100e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("100KHz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 4 ) { ch_step_two = 10e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("10KHz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 5 ) { ch_step_two = 1e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1KHz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 6 ) { ch_step_two = 500; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("500Hz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 7 ) { ch_step_two = 100; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("100Hz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 8 ) { ch_step_two = 10; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("10Hz"); EEPROM.write(address_step_two, bc_two); } if (bc_two == 9 ) { ch_step_two = 1; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1Hz"); EEPROM.write(address_step_two, bc_two); } } void keyboard_access_vfo_three() { top_three: delay(key_delay); Serial.println("keyboard_access_vfo_three"); int x_three; x_three = analogRead (0); lcd.setCursor(10,1); if (x_three < right_button_high ) { //lcd.print ("Right "); bc_three = bc_three + 1; if (bc_three == 10) // to detect if the bottom of band, them set to top range for down count { bc_three = 1; // reach bottom now starting from the top downwards } EEPROM.write(address_step_three, bc_three); selection_step_three(); // selection of vfo step } else if (x_three > up_button_low && x_three < up_button_high) { // lcd.print ("Up "); // up band movement carrier_centre_three = carrier_centre_three + (1 * ch_step_three); // ch_step increments if ( carrier_centre_three >= f_max ) { carrier_centre_three = f_max; } EEPROMWritelong(address_vfo_three, carrier_centre_three); vfo_tune_three(); } else if (x_three > down_button_low && x_three < down_button_high) { //lcd.print ("Down "); // down band movement carrier_centre_three = carrier_centre_three - (1 * ch_step_three); // ch_step increments if ( carrier_centre_three <= f_min ) { carrier_centre_three = f_min; } EEPROMWritelong(address_vfo_three, carrier_centre_three); vfo_tune_three(); } else if (x_three > left_button_low && x_three < left_button_high) { // lcd.print ("Left "); bc_three = bc_three - 1; if (bc_three == 0) // to detect if the bottom of band, them set to top range for down count { bc_three = 9; // reach bottom now starting from the top downwards } EEPROM.write(address_step_three, bc_three); selection_step_three(); // selection of vfo step } else if (x_three > select_button_low && x_three < select_button_high) { vfo_selection(); } goto top_three; } void vfo_tune_three() { Serial.println("vfo_tune_three"); frequency_three = carrier_centre_three; VFO_freq_set_three = frequency_three * 100ULL; si5351.set_freq(VFO_freq_set_three, SI5351_CLK2); si5351.update_status(); lcd.setCursor(2,0); lcd.print(" "); lcd.setCursor(2,0); freq_math_three = frequency_three/1e3; lcd.print(freq_math_three,3); } void selection_step_three() // to change the hf band of operation { Serial.println("selection_step_three"); if (bc_three == 1 ) { ch_step_three = 5e6; // 5KHz vfo increment lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("5MHz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 2 ) { ch_step_three = 1e6; // 5KHz vfo increment lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1MHz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 3 ) { ch_step_three = 100e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("100KHz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 4 ) { ch_step_three = 10e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("10KHz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 5 ) { ch_step_three = 1e3; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1KHz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 6 ) { ch_step_three = 500; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("500Hz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 7 ) { ch_step_three = 100; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("100Hz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 8 ) { ch_step_three = 10; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("10Hz"); EEPROM.write(address_step_three, bc_three); } if (bc_three == 9 ) { ch_step_three = 1; lcd.setCursor(10,1); lcd.print(" "); lcd.setCursor(10,1); lcd.print("1Hz"); EEPROM.write(address_step_three, bc_three); } }