/* MODIFIED FOR USE OF THE AD9851DDS MODULE AND ADDED PULLUP COMMAND FOR A3, A4 FOR STEP ENCODER, 5/7/2020 SOFTWARE VERSION R2 FOR THE WA3TFS SINGLE BAND HF SSB/CW 40 METER RECEIVER WITH 1.8" LCD DISPLAY OCTOBER 24, 2019 DISPLAY DATA FORMATTED FOR 1.8" LCD ST3375 DISPLAY MODULE TUNING RANGE 7.0 MHZ TO 7.30 MHZ BUT LIMITED BY HARDWARE TO AROUND 40 METERS BY HARDWARE COMMENTS OR QUESTIONS SHOULD BE SENT TO WA3TFS@ARRL.NET ADITIONAL INFORMATION ON THIS AND OTHER PROJECTS AVAILABLE ON HTTP://WA3TFS.COM ADDED A7 INPUT TO READ AGC OUTPUT AND ADDED CODE TO DISPLAY RECEIVE SIGNAL STRENGTH JULY 2023 */ #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 = 8; #define TFT_SCLK 13 // 1.4" TFT Display. #define TFT_MOSI 11 // #define TFT_CS 10 #define TFT_RST A1 #define TFT_DC A0 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); //#define AD9850_CLOCK 125000000 // Module crystal frequency. Tweak here for accuracy. #define AD9851_CLOCK 180.0e6 //9851 clock frequency #define W_CLK 8 // AD9850 Module pins. #define FQ_UD 7 #define DATA 6 #define RESET 5 #define BACKCOLOR 0x18E3 #define BARCOLOR 0x0620 #define SCALECOLOR 0xFFFF const int analogIn = A7 ; int RawValue = 0; int LastPercent = 0; int newPercent = 0; //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 long unsigned int freq = 16150000; // Set initial frequency.LO INJECTION WITH 9 MHZ IF FOR 7.150 MHZ long unsigned int freqOld = freq; long unsigned int freqDold; long unsigned int freqD = (freq - 9000000); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% long int timer; String stepText[11] = {" 1 Hz", " 10 Hz", "100 Hz", " 1 kHz", "10 kHz", "100 kHz", "500 kHz" }; int stepPointer = 3; //Start in 1000 Hz steps unsigned long incr = 0; String units = stepText[stepPointer]; #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } // transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line void tfr_byte(byte data) { for (int i = 0; i < 8; i++, data >>= 1) { digitalWrite(DATA, data & 0x01); pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high } } void sendFrequency(double frequency) { int32_t freq1 = frequency * 4294967295 / AD9851_CLOCK; // note 125 MHz clock on 9850 and 180 MHz for 9851 for (int b = 0; b < 4; b++, freq1 >>= 8) { tfr_byte(freq1 & 0xFF); } tfr_byte(0x000); // Final control byte, all 0X000 for 9850 chip //tfr_byte(0x001); // Final control byte, all 0X001 for 9851 chip pulseHigh(FQ_UD); // Done! Should see output updateDisplay(); // Update the TFT display. } 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(A3, INPUT_PULLUP); //PULLUP FOR STEP ENCODER pinMode(A4, INPUT_PULLUP); //PULLUP FOR STEP ENCODER pinMode(forceHzStep, INPUT_PULLUP); pinMode(forcekHz, INPUT_PULLUP); pinMode(FQ_UD, OUTPUT); // Configure pins for output to AD9850 module. pinMode(W_CLK, OUTPUT); pinMode(DATA, OUTPUT); pinMode(RESET, OUTPUT); pinMode(TFT_RST, OUTPUT); // Configure pins for output to TFT display. pinMode(TFT_DC, OUTPUT); pinMode(TFT_LED, OUTPUT); // drawScale(); analogWrite(TFT_LED, 255); // Adjust backlight brightness. // 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 HF 40 MTR"); tft.print(" SSB/CW RECEIVER"); // Initialise the AD9850/AD9851 module. pulseHigh(RESET); pulseHigh(W_CLK); pulseHigh(FQ_UD); // this pulse enables serial mode - Datasheet page 12 figure 10 updateDisplay(); // Update the TFT display. } void drawScale() { tft.setRotation(3); tft.drawFastHLine(30, 58, 100, SCALECOLOR ); // Horizontal Scale Line tft.drawFastVLine(30, 50, 8, SCALECOLOR); // Major Division tft.drawFastVLine(50, 53, 5, SCALECOLOR); // Minor Division tft.drawFastVLine(70, 50, 8, SCALECOLOR); // Major Division tft.drawFastVLine(90, 53, 5, SCALECOLOR); // Minor Division tft.drawFastVLine(110, 50, 8, SCALECOLOR); // Major Division tft.drawFastVLine(130, 50, 8, SCALECOLOR); // Major Division } void drawBar (int nPer) { nPer == 0; tft.setRotation(0); if (nPer < LastPercent) { tft.fillRect(50, 40 + (100 - LastPercent), 8, LastPercent - nPer, BACKCOLOR); //44-58 } else { tft.fillRect(50, 40 + (100 - nPer), 8, nPer - LastPercent, BARCOLOR); //5 SETS WIDTH OF BAR } LastPercent = nPer; tft.setRotation(3); delay(100); tft.setRotation(3); } void getStep() { 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; //case 6: incr = 500000; break; } } void updateDisplay() { tft.setRotation(3); long unsigned int freqD = (freq - 9000000); //MODIFIED FOR 9 MHZ IF getStep(); // units = stepText[stepPointer]; tft.fillRect(0, 15, 160, 20, ST7735_BLACK); //0, 15, 160, 20 tft.setTextColor(ST7735_RED); tft.setCursor(10, 15); tft.setTextSize(1); tft.print(" Step "); tft.setCursor(10, 32); //10-30 tft.setTextSize(2); tft.setCursor(45, 15);//60 tft.print(units); tft.fillRect(0, 40, 160, 60, ST7735_BLACK); tft.setTextColor(ST7735_GREEN); tft.setTextSize(3); if (freq < 500) { tft.setCursor(50, 50);//78, 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(50); } else if (freqD < 30000000) { tft.setCursor(8, 75); //40, 50 SETS LOCATION OF FREQ DISPLAY if (freqD < 1000000)tft.print(" "); tft.print((float)freqD / 1000, 3); tft.setCursor(48, 75);//58, 75 } else { format(freqD); tft.setCursor(58, 75); drawScale(); } } void format(long value) { 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() { drawScale(); //LastPercent == 0; //getStep(); unsigned char result = i.process(); if (result) { delay(100); if (result == DIR_CW) { delay(100); if (stepPointer < 5) stepPointer++; } delay(100); if (result == DIR_CCW) { if (stepPointer > 0) stepPointer--; } updateDisplay(); } if (digitalRead(forceHzStep) == LOW) { stepPointer = 2; delay(50); updateDisplay(); } if (digitalRead(forcekHz) == LOW) { freq = 16150000; //SET TO 7150000 ON BUTTON PRESS sendFrequency(freq); delay(350); updateDisplay(); } if (freqOld != freq) { sendFrequency(freq); updateDisplay(); freqOld = freq; } int newPercent; RawValue = analogRead(analogIn); newPercent = int((RawValue / 1024.0) * 600.0); //Change 600 to calibrate s meter if (newPercent != LastPercent) { drawBar(newPercent); delay(10); drawScale(); } } ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW) { if ((freq + incr) <= 39000000) freq += incr; //SET UPPER LIMIT TO 30 MHZ (TUNE 8 MHZ) } else { if ((freq - incr) >= 10500000) freq -= incr; //SET LOWER LIMIT TO .5 MHZ (TUNE 6.5 MHZ } if (freq <= 500) freq = 500; if (freq >= 39000100) freq = 39000000; updateDisplay(); // Update the TFT display. } }