/* SOFTWARE VERSION FINAL_40mtr_xcvrCW_2/19/2022 FOR THE WA3TFS 40 meter CW XCEIVER WITH 1.8" LCD DISPLAY DISPLAY DATA FORMATTED FOR 1.8" LCD DISPLAY with ST7735 driver TUNING RANGE 7 MHZ TO 7.3 MHZ WITH -9 MHZ OFFSET ON OUTPUT. DISPLAY SHOWS TUNED FREQ COMMENTS OR QUESTIONS SHOULD BE SENT TO WA3TFS@ARRL.NET ADITIONAL INFORMATION ON THIS AND OTHER PROJECTS AVAILABLE ON HTTP://www.WA3TFS.COM */ #include #include // Core graphics library https://github.com/adafruit/Adafruit-GFX-Library #include // Hardware-specific library https://github.com/adafruit/Adafruit-ST7735-Library #include #include // Rotary encoder: https://github.com/brianlow/Rotary int TFT_LED = 9; #define TFT_SCLK 13 // 1.8" TFT Display setup. #define TFT_MOSI 11 // #define TFT_CS 10 #define TFT_RST A1 #define TFT_DC A0 #define xmitctrl D12 //used to detect CW transmit selected #define LSBctrl D8 //used to detect LSB display correction selected Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); #define stepPin1 A3 // Set 'Step' rotary encoder pins #define stepPin2 A4 int forceHzStep = A2; // 'Step' rotary encoder's push button - Set 100 Hz steps. int forcekHz = 4; // Interrupt-driven encoder's push button - force 1kHz freq. Rotary i = Rotary(stepPin1, stepPin2); // Rotary encoder for setting increment. Rotary r = Rotary(2, 3); // Rotary encoder for frequency connects to interrupt pins volatile uint32_t BFO_freq = 8998739; //(9001500 usb (9001000, lsb) 9000400 cw adjust as needed 8998739 Si5351 si5351; //%%%%%%%%%%%%%%%%%%%%%%%%% long int freq = 16149739; // Set initial frequency.LO INJECTION WITH 9 MHZ IF FOR 7150.000 kHz long int freqOld = freq; long int freqDold; //long int freqD = (freq + (BFO_freq + 1500)); //%%set display to show proper tuned frequency/////////// long int freqD = (freq -(BFO_freq + 1099)); //%%set display to show proper tuned frequency 1099 long int timer; long int xmitctrl; long int cwfreq = (BFO_freq - 300);//1400 String stepText[11] = {" 1 Hz", " 10 Hz", "100 Hz", " 1 kHz", "10 kHz", "100 kHz", "500 kHz" //changed char* to String to fix compile warning }; //int val = 0; int steptemp; int stepPointer = 3; //Start in 1 kHz steps unsigned long incr = 0; String units = stepText[stepPointer]; void sendFrequency() { si5351.set_freq((freq * 100ULL), SI5351_CLK0); si5351.set_freq((BFO_freq * 100ULL), SI5351_CLK2); //si5351.output_enable(SI5351_CLK1,1); //keep cw out on } void setup() { pinMode(2, INPUT_PULLUP); //_PULLUP); // Pins for interrupt-driven rotary encoder pinMode(3, INPUT_PULLUP); //_PULLUP); // Pins for interrupt-driven rotary encoder pinMode(4, INPUT_PULLUP); //_PULLUP); // Pins for interrupt-driven rotary encoder push button pinMode(forceHzStep, INPUT_PULLUP); pinMode(forcekHz, INPUT_PULLUP); pinMode(xmitctrl, INPUT_PULLUP); pinMode(8, INPUT_PULLUP); //internal pullup set for digital pin D8 analogWrite(TFT_LED, 255); // Adjust backlight brightness.255 // Configure interrupt and enable for rotary encoder. PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab tft.setRotation(3); tft.setTextWrap(false); // Allow text to run off right edge (false) tft.fillScreen(ST7735_BLACK); tft.setCursor(15, tft.height() - 20); //18 tft.setTextSize(1); tft.drawFastHLine(0, tft.height() - 25, tft.width() - 10, ST7735_RED);//23 tft.setTextColor(ST7735_YELLOW); tft.println(" WA3TFS 40 METER "); tft.print(" CW TRANSCEIVER"); updateDisplay(); // Update the TFT display. // Initialize the DDS si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); si5351.set_correction(88278, SI5351_PLL_INPUT_XO); // Set to specific Si5351 calibration number(88278) si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); //si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLB); //active pllb not used si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); //SET FOR 15 dBm LO OUTPUT 8MA si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_8MA); //SET BFO OUTPUT LEVEL 8MA si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA); //SET BFO OUTPUT LEVEL 8MA si5351.set_freq((freq * 100ULL), SI5351_CLK0); si5351.set_freq((BFO_freq * 100ULL), SI5351_CLK2); si5351.set_freq((cwfreq * 100ULL), SI5351_CLK1); si5351.output_enable(SI5351_CLK2,0); //turn off BFO si5351.output_enable(SI5351_CLK1,1); //turn on CW output si5351.output_enable(SI5351_CLK0,1); //turn on LO output } void getStep() { //set up tuning steps switch (stepPointer) { case 0: incr = 1; break; case 1: incr = 10; break; case 2: incr = 100; break; case 3: incr = 1000; break; case 4: incr = 10000; break; case 5: incr = 100000; break; } } void updateDisplay() { long unsigned int freqD = ((freq - 1000) - (BFO_freq)); //proper display for CW if(digitalRead(8)==LOW) //check if pin D8 is switched low freqD = ((freq) - (BFO_freq)) ;//offsets display to display proper freq when receiving LSB getStep(); //see what step size is set to units = stepText[stepPointer]; tft.fillRect(0, 15, 160, 20, ST7735_BLACK); //0, 15, 160, 20 tft.setTextColor(ST7735_RED); tft.setCursor(10, 20); tft.setTextSize(1); tft.print("Step"); tft.setTextSize(2); tft.setCursor(35, 15);//60 tft.print(units); tft.fillRect(0, 40, 160, 60, ST7735_BLACK); tft.setTextColor(ST7735_GREEN); tft.setTextSize(3);//format the screen display, some not used in this device if (freq < 500) { tft.setCursor(50, 50);//50, 50 if (freq < 1000) tft.print(" "); if (freq < 100) tft.print (" "); tft.print(freqD); tft.setCursor(58, 75); if (freq < 500) tft.print(" "); if (freq < 100) tft.print(" "); tft.print(freqD); tft.setCursor(58, 75);//58, 75 delay (100); } else if (freqD < 15000000) { tft.setCursor(10 , 50);//20, 50 if (freqD < 1000000)tft.print(" "); tft.print((float)freqD / 1000, 3); tft.setCursor(40, 75);//58, 75 delay (100); } else { tft.setCursor(58, 75); delay (100); } } void format(long value) { //calculations to set display properly int M = (value / 1000000); int T100 = ((value / 100000) % 10); int T10 = ((value / 10000) % 10); int T1 = ((value / 1000) % 10); int U100 = ((value / 100) % 10); int U10 = ((value / 10) % 10); int U1 = ((value / 1) % 10); tft.setCursor(25, 50);//25, 50 tft.print(M); tft.print("."); tft.print(T100); tft.print(T10); tft.print(T1); tft.print(","); tft.print(U100); tft.print(U10); tft.print(U1); freqDold = freqD; } void loop() { steptemp = stepPointer; if (stepPointer <1) stepPointer = 5; if (digitalRead (forcekHz) == LOW) //check for button press { delay (75); stepPointer = (stepPointer - 1); //if pressed, deccrement case by one si5351.output_enable(SI5351_CLK0,1); //turn on LO output } else { stepPointer = stepPointer; //if not, case stays the same } if (stepPointer != steptemp) //if it has changed, update the display, otherwise no { updateDisplay(); } if( digitalRead(12)==LOW) { tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(124, 10); tft.print ("R"); delay (100); si5351.output_enable(SI5351_CLK2,0); //keep BFO off freqD = (freq - (BFO_freq + 699)); //ADJUST cwfreq BELOW TO FINE TUNE OUTPT FREQUENCY////// cwfreq = (freq - (BFO_freq + 950)); si5351.set_freq((cwfreq * 100ULL), SI5351_CLK1); si5351.output_enable(SI5351_CLK1,1); //keep cw out on si5351.output_enable(SI5351_CLK0,1); //turn on LO output tft.setTextSize(2); tft.setTextColor(ST7735_WHITE); tft.setCursor(136, 10); tft.print ("T"); } else if (digitalRead (12) == HIGH) { tft.setTextSize(2); tft.setTextColor(ST7735_BLACK); tft.setCursor(136, 10); tft.print ("T"); delay (100); si5351.output_enable(SI5351_CLK2,1); //turn BFO oN //si5351.set_freq((cwfreq * 100ULL), SI5351_CLK1); si5351.output_enable(SI5351_CLK1,0); //turn cw out oFF si5351.output_enable(SI5351_CLK0,1); //turn on LO tft.setTextSize(2); tft.setTextColor(ST7735_YELLOW); tft.setCursor(124, 10); tft.print ("R"); // updateDisplay(); } if (freqOld != freq) { sendFrequency(); updateDisplay(); freqOld = freq; delay (100); } } ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW) { if ((freq + incr) <= 16300000) freq += incr; //SET UPPER LIMIT TO 7.3 MHZ (TUNE 7.3 MHZ) } else { if ((freq - incr) >= 15999999) freq -= incr; //SET LOWER LIMIT TO 7.0 MHZ (TUNE 7.0 MHZ } if (freq <= 15999999) freq = 15999999; if (freq >= 16300000) freq = 16300000; updateDisplay(); // Update the TFT display. } }