/* From N6QW using the 240 X 320 TFT Color display with the Si5351 Clock Generator. The sketch includes selectable USB/LSB, a Tune function with 988 Hz tone and the Fout is 4X the LO (operating frequency + offset). The Fout is passed through a 74AC74 Dual D flip flop so that a quadrature output results at 1X -- This helps the phase noise and provides an I Q LO output. The sketch also includes a built in S Meter. Pete N6QW 1/18/2015 You must use the CD4050 Logic Level Convertor to make this display */ #include #include #include #include "Rotary.h" #include //#include #define NOTE_B5 988 #if defined(__SAM3X8E__) #undef __FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif #define __CS 10 #define __DC 9 #define __RST 8 #define ENCODER_B 2 // Encoder pin A #define ENCODER_A 3 // Encoder pin B #define ENCODER_BTN A3 // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF TFT_ILI9340 tft = TFT_ILI9340(__CS, __DC, __RST); #include "si5351.h" #include "Wire.h" Si5351 si5351; long int frq; int_fast32_t rx = 64794000L; // Starting frequency of VFO = 4X times the operating frequency plus offset which is selectable int_fast32_t rx2=1; // variable to hold the updated frequency int_fast32_t increment = 10; // starting VFO update increment in HZ. int_fast32_t bfo = 8998500L; // default offset String hertz = " 10"; byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders int buttonstate = 0; int buttonstate2 = 0; const int tonepin = 6; const int SW = A1; //selects upper or lower sideband const int SW1 = A2; // provides the TUNE fucntion const int LED = 7; int i = 0; const int SENSOR = 0; // Analog Pin A0 for the S Meter function int val = 0; int val1 = 0; int val2 = 0; int val5 = 0; int val6 = 0; int buttonState = 0; int lastButtonState = 0; int x = 0; int y = 0; Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins. void setup() { Serial.begin(9600); PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); tft.begin(); // init display pinMode(SW, INPUT); // Selects either USB or LSB````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````[ digitalWrite(SW,HIGH); pinMode(SW1, INPUT); //Tune digitalWrite(SW1,HIGH); pinMode(A3,INPUT); // Connect to a button that goes to GND on push pinMode(A1,INPUT); // IF sense ********************************************** digitalWrite(A3,HIGH); digitalWrite(A2,HIGH); digitalWrite(A1,HIGH); // init done pinMode(LED, OUTPUT); tft.begin(); #if defined(__MK20DX128__) || defined(__MK20DX256__) tft.setBitrate(24000000); #endif tft.fillScreen(0x07F0); tft.fillScreen(0xF820); // 0x07F0 = lt green, 0xF810 = rose, 0xF840 = rust, 0xF820 = orange tft.setRotation(1); // landsacape versus portrait tft.drawRect(212, 94, 84,32, WHITE); //call sign on the face tft.fillRect(214,96,81,28,BLUE); tft.setCursor(220, 100); tft.setTextColor(YELLOW); tft.setTextSize(3); tft.print("N6QW"); tft.setCursor(30,208); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("Let's Build Something"); tft.drawRect(120, 100, 64,32, BLACK); //Tune Block tft.fillRect(122,102,59,28,0x07F0); // initialize the Si5351 si5351.init(SI5351_CRYSTAL_LOAD_8PF); si5351.set_correction(230); // Set CLK0 to output 4 times 7.2 MHz with a fixed PLL frequency --later a divide by 4 ~ phase noise improvement si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); si5351.set_freq(rx , SI5351_PLL_FIXED, SI5351_CLK0); si5351.set_freq(bfo, 0, SI5351_CLK2); si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_8MA); si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_8MA); } void setincrement(){ if (increment == 10){increment = 100; hertz = "100";} else if (increment == 100){increment = 1000; hertz=" 1K";} else if (increment == 1000){increment = 10000; hertz=" 10K"; } else if (increment == 10000){increment = 100000; hertz="100K";} else if (increment == 100000){increment = 1000000; hertz=" 1M";} else{increment = 10; hertz = " 10";}; delay(50); // Adjust this delay to speed up/slow down the button menu scroll speed. }; void showFreq(){ millions = int(((rx/4)-bfo)/1000000); hundredthousands = ((((rx/4)-bfo )/100000)%10); tenthousands = ((((rx/4)-bfo )/10000)%10); thousands = ((((rx/4)-bfo )/1000)%10); hundreds = ((((rx/4)-bfo )/100)%10); tens = ((((rx/4)-bfo )/10)%10); ones = ((((rx/4)-bfo )/1)%10); tft.drawRect(28, 10, 266,48, BLACK); //tft.fillRect(30, 12, 260,44, WHITE); tft.setTextSize(4); tft.setTextColor(BLACK); if (millions > 9){tft.setCursor(56,20);} else{tft .setCursor(60,20);} tft.print(millions); tft.print("."); tft.print(hundredthousands); tft.print(tenthousands); tft.print(thousands); tft.setTextColor(GREEN); tft.setTextSize(4); tft.print("."); tft.print(hundreds); tft.print(tens); tft.print(ones); }; ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW){rx=rx+(4*increment);} // account that rx = 4 times the frequency so the increment must be 4* or /.25 else {rx = rx-(4*increment);}; if (rx >=65994000){rx=rx2;}; // UPPER VFO LIMIT = 4 X the opearting frequency + offset if (rx <=63994000){rx=rx2;}; // LOWER VFO LIMIT = 4 X the opearting frequency + Offset } } void loop() { checkMode(); //********Moved void checkBand out of the loop lastButtonState = buttonState; tft.setCursor(270,70); tft.setTextColor(YELLOW); tft.setTextSize(2); tft.print("Hz"); ; if(digitalRead(SW)){ //********If SW is true do the following. bfo = 8998500L; si5351.set_freq( bfo, 0, SI5351_CLK2); tft.drawRect(16, 94, 64,32, BLACK); //call sign on the face tft.fillRect(18,96,60,28,WHITE); /* tft.setTextSize(2); // lets you toggle bewteen USB and LSB without having a screen overwrite tft.setTextColor(BLACK); tft.setCursor(10,100); tft.println("USB");*/ tft.setTextSize(3); tft.setTextColor(RED); tft.setCursor(20,100); tft.println("LSB"); } else{ //**********if not, do this. bfo = 9001500L; si5351.set_freq( bfo, 0, SI5351_CLK2); tft.drawRect(16, 94, 64,32, BLACK); //call sign on the face tft.fillRect(18,96,60,28,WHITE); /* tft.setTextSize(2); // lets you toggle bewteen USB and LSB without having a screen overwrite tft.setTextColor(BLACK); tft.setCursor(10,100); tft.println("LSB"); */ tft.setTextSize(3); tft.setTextColor(RED); tft.setCursor(20, 100); tft.println("USB"); } if (rx != rx2){ tft.setTextSize(4); tft.setTextColor(0xF820); if (millions > 9){tft.setCursor(56,20);} else{tft .setCursor(60,20);} tft.print(millions); tft.print("."); tft.print(hundredthousands); tft.print(tenthousands); tft.print(thousands); tft.setTextColor(0xF820); tft.setTextSize(4); tft.print("."); tft.print(hundreds); tft.print(tens); tft.print(ones); /* tft.setTextSize(3); // When you change frequency you don't have to screen clear! It paints it black tft.setTextColor(WHITE); if (millions > 9){tft.setCursor(80,20);} else{tft .setCursor(84,20);} tft.print(millions); tft.print("."); tft.print(hundredthousands); tft.print(tenthousands); tft.print(thousands); //tft.setCursor(170,20); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("."); tft.print(hundreds); tft.print(tens); tft.print(ones);*/ showFreq(); si5351.set_freq(rx , SI5351_PLL_FIXED, SI5351_CLK0); si5351.set_freq(bfo , SI5351_PLL_FIXED, SI5351_CLK2); rx2 = rx; tft.drawRect(180, 66, 80,23,WHITE); tft.fillRect(182, 68, 77, 20, BLACK); tft.setCursor(200,70); tft.setTextColor(YELLOW); tft.setTextSize(2); tft.print(hertz); } buttonstate = digitalRead(A3); if(buttonstate == LOW) { setincrement(); tft.drawRect(180, 66, 80,23,WHITE); tft.fillRect(182, 68, 77, 20, BLACK); tft.setCursor(200,70); tft.setTextColor(BLACK); // blanks out the old setting tft.setTextSize(2); tft.print(hertz); delay(10); tft.setCursor(200,70); tft.setTextColor(YELLOW); tft.setTextSize(2); tft.print(hertz); showFreq(); }; delay(25); tft.drawRect(20, 150, 280,40, WHITE); tft.fillRect(30, 160, 260, 20, YELLOW); tft.setTextSize(2); tft.setTextColor(BLACK); tft.setCursor(32,164); tft.println("S="); long randnum = random (0, 116); val2 = random(0,80);{ if(val2 <(0, 48)); val5 = val2; tft.drawRect(60, 166, 48, 8,YELLOW); tft.fillRect(60, 166, 1.5*val5, 8, CYAN);} if(val2>(50, 80));{ val6 = val2; tft.drawRect(160,166,(val6-49),8,YELLOW); tft.fillRect(160,166, (val6-49), 8, RED); delay(200); } } void checkMode(){ buttonState = digitalRead(SW1); // creates a 10 second tuning pulse trani 50% duty cycle and makes TUNE appear on the screen if(buttonState != lastButtonState){ if(buttonState == LOW){ digitalWrite(7, HIGH); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor(126, 110); tft.print("TUNE"); //display.display(); delay(12); for(int i = 0; i < 60; i++) { tone(6, NOTE_B5); delay(50); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor(126, 110); tft.print("TUNE"); delay(100); tft.drawRect(120, 100, 64,32, BLACK); //Tune Block Prints over tune when the cycle is over tft.fillRect(122,102,59,28,CYAN); } } else{ digitalWrite(7,LOW); /* tft.setTextSize(2); // This prints a white TUNE over the black TUNE and makes it disappear from the scereen tft.setTextColor(BLACK); tft.setCursor(40, 44); tft.print("TUNE"); noTone(6);*/ } delay(50); } }