* HelloWorld.ino A very simple example for Ucglib Universal uC Color Graphics Library Copyright (c) 2014, olikraus@gmail.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 Feb 2014: ROM Size Font Mode 9928 NONE 10942 TRANSPARENT (1014 Bytes) 11650 SOLID (1712 Bytes) 12214 TRANSPARENT+SOLID */ #include #include #include #include "si5351.h" #include "Rotary.h" #define OLED_RESET 8 #include "Tone.h" #define TONE_PIN 6 #define NOTE_B5 988 #define ENCODER_B 2 // Encoder pin A #define ENCODER_A 3 // Encoder pin B #define ENCODER_BTN A3 Si5351 si5351; long int frq; int_fast32_t rx =0L; // Starting frequency of VFO operating frequency plus offset which is selectable IF = 9.0 MHz int_fast32_t rx2= 0L; // variable to hold the updated frequency int_fast32_t increment = 100; // starting VFO update increment in HZ. int_fast32_t bfo = 9001500L; // default offset sideband inversion thus USB int_fast32_t rx1 = 23201500L; //20 meters int_fast32_t rx3 = 23075500L; // 20M FT8 int_fast32_t vfoA = 1; int_fast32_t vfoB = 1; int_fast32_t old_vfoA = 1; int_fast32_t old_vfoB = 1; int RunOnce = 1; String hertz = "100"; //initial tune step rate. byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders Rotary r = Rotary(3,2); // sets the pins the rotary encoder uses. Must be interrupt pins. int i = 0; int z = 0; const int TX = 4; //USE VFO A only on transmit const int VS = 5; const int SW = A1; // Toggle Switch USB/LSB const int SW1 = A2; // provides the TUNE fucntion const int VFO = A0; const int tonepin = 6; int buttonstate = 0; int buttonState = 0; int lastButtonState = 0; int lastbuttonstate = 0; /* Hardware SPI Pins: Arduino Uno sclk=13, data=11 Arduino Due sclk=76, data=75 Arduino Mega sclk=52, data=51 >>> Please uncomment (and update) one of the following constructors. <<< */ //Ucglib8BitPortD ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /* wr= */ 18 , /* cd= */ 19 , /* cs= */ 17, /* reset= */ 16 ); //Ucglib8Bit ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, 0, 1, 2, 3, 4, 5, 6, 7, /* wr= */ 18 , /* cd= */ 19 , /* cs= */ 17, /* reset= */ 16 ); //Ucglib4WireSWSPI ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9 , /*cs=*/ 10, /*reset=*/ 8); // not working //Ucglib4WireSWSPI ucg(ucg_dev_ili9325_spi_18x240x320, ucg_ext_ili9325_spi_18, /*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9 , /*cs=*/ 10, /*reset=*/ 8); // not working //Ucglib3WireILI9325SWSPI ucg(ucg_dev_ili9325_spi_18x240x320, ucg_ext_ili9325_spi_18, /*sclk=*/ 13, /*data=*/ 11, /*cs=*/ 10, /*reset=*/ 8); // not working //Ucglib3WireILI9325SWSPI ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /*sclk=*/ 13, /*data=*/ 11, /*cs=*/ 10, /*reset=*/ 8); // not working Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_ST7735_18x128x160_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_ILI9163_18x128x128_SWSPI ucg(/*sclk=*/ 7, /*data=*/ 6, /*cd=*/ 5, /*cs=*/ 3, /*reset=*/ 4); //Ucglib_ILI9163_18x128x128_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); /* HW SPI Adapter */ //Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 7, /*data=*/ 6, /*cd=*/ 5, /*cs=*/ 3, /*reset=*/ 4); //Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_ILI9341_18x240x320_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 4, /*data=*/ 3, /*cd=*/ 6, /*cs=*/ 7, /*reset=*/ 5); /* Elec Freaks Shield */ //Ucglib_HX8352C_18x240x400_SWSPI ucg(/*sclk=*/ 7, /*data=*/ 6, /*cd=*/ 5, /*cs=*/ 3, /*reset=*/ 4); //Ucglib_HX8352C_18x240x400_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_ILI9486_18x320x480_SWSPI ucg(/*sclk=*/ 7, /*data=*/ 6, /*cd=*/ 5, /*cs=*/ 3, /*reset=*/ 4); //Ucglib_ILI9486_18x320x480_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1351_18x128x128_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1351_18x128x128_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1351_18x128x128_FT_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1351_18x128x128_FT_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1351_18x128x128_FT_SWSPI ucg(/*sclk=*/ 4, /*data=*/ 17, /*cd=*/ 16, /*cs=*/ 0, /*reset=*/ 2); /* FT SSD1351 direct connect to ESP32 */ //Ucglib_PCF8833_16x132x132_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cs=*/ 9, /*reset=*/ 8); /* linksprite board */ //Ucglib_PCF8833_16x132x132_HWSPI ucg(/*cs=*/ 9, /*reset=*/ 8); /* linksprite board */ //Ucglib_LD50T6160_18x160x128_6Bit ucg( /*d0 =*/ d0, /*d1 =*/ d1, /*d2 =*/ d2, /*d3 =*/ d3, /*d4 =*/ d4, /*d5 =*/ d5, /*wr=*/ wr, /*cd=*/ cd, /*cs=*/ cs, /*reset=*/ reset); //Ucglib_LD50T6160_18x160x128_6Bit ucg( /*d0 =*/ 16, /*d1 =*/ 17, /*d2 =*/ 18, /*d3 =*/ 19, /*d4 =*/ 20, /*d5 =*/ 21, /*wr=*/ 14, /*cd=*/ 15); /* Samsung 160x128 OLED with 6Bit minimal interface with Due */ //Ucglib_LD50T6160_18x160x128_6Bit ucg( /*d0 =*/ 5, /*d1 =*/ 4, /*d2 =*/ 3, /*d3 =*/ 2, /*d4 =*/ 1, /*d5 =*/ 0, /*wr=*/ 7, /*cd=*/ 6); /* Samsung 160x128 OLED with 6Bit minimal interface with Uno */ //Ucglib_SSD1331_18x96x64_UNIVISION_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SSD1331_18x96x64_UNIVISION_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SEPS225_16x128x128_UNIVISION_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); //Ucglib_SEPS225_16x128x128_UNIVISION_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8); void setup(void) { delay(1000); //ucg.begin(UCG_FONT_MODE_TRANSPARENT); ucg.begin(UCG_FONT_MODE_SOLID); ucg.clearScreen(); ucg.setPrintDir(0); PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); // Connect to a button that goes to GND on push to set the 4 step rates pinMode(SW1, INPUT); // USB/LSB Select digitalWrite(SW1, HIGH); pinMode(SW,INPUT); digitalWrite(SW,HIGH); pinMode(4, INPUT); digitalWrite(4, HIGH); pinMode(5, INPUT); digitalWrite(5, HIGH); pinMode(7, OUTPUT); digitalWrite(7, LOW); pinMode(A0, INPUT); pinMode(A3,INPUT); digitalWrite(A3,HIGH); #if defined(__MK20DX128__) || defined(__MK20DX256__) tft.setBitrate(24000000); #endif si5351.init(SI5351_CRYSTAL_LOAD_8PF); si5351.set_correction(100); 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); // Higher Drive since it is a TUF-1 DBM 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(150); // Adjust this delay to speed up/slow down the button menu scroll speed. } void showFreq(){ millions = int(((rx)-bfo)/1000000); hundredthousands = ((((rx)-bfo )/100000)%10); tenthousands = ((((rx)-bfo )/10000)%10); thousands = ((((rx)-bfo )/1000)%10); hundreds = ((((rx)-bfo )/100)%10); tens = ((((rx)-bfo )/10)%10); ones = ((((rx)-bfo )/1)%10); delay(25); } ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW){rx=rx-(1*increment);} else {rx = rx+(1*increment);}; if (rx >=50000000L){rx=rx2;}; //This sets the upper LO range if (rx <=500000L){rx=rx2;}; // This sets the lower LO range } } void loop(void) { ucg.setRotate90(); SplashScreen(); RunOnce = 0; CheckDisplay(); CheckMode(); CheckSB(); CheckVS(); // CheckTX(); CheckGoober(); } /* ucg.setPrintPos(5,55); ucg.print("14.074000 MHz"); ucg.setPrintPos(5,75); ucg.print("14.200000 MHz"); ucg.setColor(255, 255, 0); ucg.setPrintPos(130,95); ucg.print("Hz"); ucg.setColor(255, 255, 255); ucg.setPrintPos(90,95); ucg.print("100"); ucg.setColor(255, 0, 255); ucg.setPrintPos(8,95); ucg.print("USB"); ucg.setColor(255, 255, 0); ucg.setPrintPos(130,55); ucg.print("ON"); ucg.setColor(255, 255, 0); ucg.setPrintPos(5,37); ucg.print("Paesano SSB XCVR"); delay(500); */ //*************************************************************** void SplashScreen(){ if (RunOnce == 1){ //ucg.setRotate90(); ucg.setFont(ucg_font_ncenR10_tr); ucg.setColor( 0, 255,255); ucg.setPrintPos(22,39); ucg.print("N6QW"); delay(500); ucg.setColor(0, 255, 255); ucg.setPrintPos(22,54); ucg.print("Amazing - -"); ucg.setColor(0, 255,255); ucg.setPrintPos(22,69); ucg.print("Pete is the "); ucg.setColor(0, 255, 255); ucg.setPrintPos(22,84); ucg.print("Ham"); ucg.setColor(0, 255,255); ucg.setPrintPos(60,84); ucg.print("Genius"); delay(1000); ucg.clearScreen(); // ucg.setColor(255,255,255); // ucg.drawBox(0,0,180,127); RunOnce = 0; } } //******************************************************************** void CheckDisplay(void){ ucg.setFont(ucg_font_ncenR08_tr); ucg.setColor(255, 255, 255); // ucg.setPrintPos(3,37); // ucg.print("Paesano, A Left Coast SSB Xcvr"); ucg.setColor(255, 255, 255); ucg.setPrintPos(138,98); ucg.print("Hz"); } //*********************Check Sideband ************************************ void CheckSB(){ // *** S Meter code smaple the audio output and uses a log function if(digitalRead(SW)){ //********If SW is true do the following. bfo = 9001500L; //Sideband inversion with the LO above the operating frequency si5351.set_freq( bfo, 0, SI5351_CLK2);{ ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(0, 0, 0); ucg.setPrintPos(38,98); ucg.println("LSB"); ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(255,10, 200); ucg.setPrintPos(3,98); ucg.println("USB");} } else{ //**********if not, do this. bfo = 8998500L; // Keep in mind the LO is above the operating frequency so sideband inversion si5351.set_freq( bfo, 0, SI5351_CLK2); ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(0, 0, 0); ucg.setPrintPos(3,98); ucg.println("USB"); ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(255, 10, 200); ucg.setPrintPos(38,98); ucg.println("LSB"); } } //******************************************************************************** // THIS IS THE MAIN Frequency Determining Code //*************************************** VFO A or B **************** void CheckVS(){ //thus a toggle switch controls writing which VFO indirectly digitalRead(5); if(digitalRead(5) == HIGH){ digitalWrite(A0, HIGH); useVFOA(); z = 1; } else { digitalWrite(A0, LOW); useVFOB(); z = 2; } } // *************************************VFO A******************* void useVFOA(){ // Has logic so you can have the correct display in concert with USB/LSB CheckFreq1(); digitalRead(A0) == HIGH; rx = rx1; ucg.setFont(ucg_font_ncenR14_tr); ucg.setColor( 255, 255, 0); ucg.setPrintPos(5,60); ucg.print(rx1-bfo); ucg.setColor(255,255,255); ucg.drawBox(135,48,10,10); ucg.setColor(0,0,0); ucg.drawBox(135,66,10,10); rx1 == vfoA; vfoA = rx1; old_vfoA = vfoA; showFreq(); si5351.set_freq(vfoA , SI5351_PLL_FIXED, SI5351_CLK0); } // ******************************** VFO B ***************************** void useVFOB(){ CheckFreq2(); digitalRead(A0) == LOW; rx = rx3; ucg.setFont(ucg_font_ncenR14_tr); ucg.setColor(255, 255, 0); ucg.setPrintPos(5,78); ucg.print(rx3-bfo); ucg.setColor(255,255,255); ucg.drawBox(135,66,10,10); ucg.setColor(0,0,0); ucg.drawBox(135,48,10,10); rx3 == vfoB; vfoB = rx3; old_vfoB = vfoB; si5351.set_freq(vfoB , SI5351_PLL_FIXED, SI5351_CLK0); } //************* /* //Not Needed void CheckFreq(){ if (rx != rx2){ showFreq(); si5351.set_freq(rx , SI5351_PLL_FIXED, SI5351_CLK0); Serial.println(rx); //si5351.set_freq(bfo , SI5351_PLL_FIXED, SI5351_CLK2); rx2 = rx; } } */ //************************* Frequency Change 1 ************************* void CheckFreq1(){ if( rx != rx2){ // This is the key to memory si5351.set_freq(rx1 , SI5351_PLL_FIXED, SI5351_CLK0); si5351.set_freq(bfo , SI5351_PLL_FIXED, SI5351_CLK2); rx1 = rx; showFreq(); } } //************************* Check Frequency 2 ******************************* void CheckFreq2(){ if( rx != rx2){ si5351.set_freq(rx3 , SI5351_PLL_FIXED, SI5351_CLK0); si5351.set_freq(bfo , SI5351_PLL_FIXED, SI5351_CLK2); rx3 = rx; showFreq(); } } // *************************** Check for Transmit ************************* // ***************************************Check for TRansmit ****************************************** /* This has proven to be a nasty problem for me as I have not been able to implement this in software. Try as I might * the software does not follow what I want to do. I have total functionality with two separate VFO's --my failure is how * to transmit on one while receiving on the other. Finally I hit on a simple hardware solution. Pin A0 is either set high or * low depedning on whether Pin 5 is grounded via a switch. So lets add some hardware in that loop like a NC relay. So here is * how it would work. * 1) In the receiove mode by engaging Pin 5 high or low with an external switch we have a choice of VFO A or VFO B * 2) Let us say we want to make VFO A the Receive and Transmit VFO and VFO B Receive only * 3) When the PTT Switch ground Pin 4 it also causes a NC relay to open. So if you were receiving on VFO B the break in the circuit * would cause the controlling VFO to be VFO A whihc means you would be transmitting on VFO A. * 4) If you purposefully open the VFO A/B sweitch then you would receive and transmit entirely on VFO A. * 5) Adding yet another switch in the loop in the line feeding the juice (or ground) to the NC relay Then you would receive and transmit only on VFO B * 6) Normal Opeartion would entail opening the A/B select swithc so that you would pick the transmit frequency on VFO A. Then closing the switch you would * have VFO A fixed for transmit and tune around on VFO B. Opening the switch then tuning and transmitting is on VFO A */ void CheckTX() { //Green Dot comes on to PTT Also selects which VFO A is used for tranmit digitalRead(4); if(digitalRead(4) == LOW){ ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(255, 255, 0); ucg.setPrintPos(5,85); ucg.println(rx1 - bfo); /* display.setCursor(52,50); //We are dsiplayin the received Freq display.setTextSize(2); display.setTextColor(WHITE); display.println("T=A"); */ // display.fillCircle(108, 40, 4, WHITE); useVFOA(); digitalWrite(7, HIGH); } } //************************************TUNE MODE************************** 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){ ucg.setFont(ucg_font_ncenR08_tr); ucg.setColor(0,0,0); ucg.setPrintPos(3,37); ucg.print("Paesano,HB SSB Xcvr"); ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(0, 255,0); ucg.setPrintPos(50,37); ucg.print("TUNE "); digitalWrite(A0, HIGH); delay(12); for(int i = 0; i < 100; i++) { tone(6, NOTE_B5); delay(75); noTone(6); delay(25); } } else{ ucg.setFont(ucg_font_ncenR12_tr); ucg.setColor(0, 0,0); ucg.setPrintPos(50,37); ucg.print("TUNE "); ucg.setFont(ucg_font_ncenR08_tr); ucg.setColor(0,255,255); ucg.setPrintPos(3,37); ucg.print("Paesano, A Left Coast SSB Xcvr"); noTone(6); } delay(50); } } //**************************************CheckGoober************************************************************************* void CheckGoober(){ lastButtonState = buttonState; lastbuttonstate = buttonstate; ucg.setFont(ucg_font_ncenR10_tr); ucg.setColor(0,255,255); ucg.setPrintPos(98,98); ucg.print(hertz); showFreq(); if (rx != rx2){ showFreq(); si5351.set_freq(rx , SI5351_PLL_FIXED, SI5351_CLK0); rx2=rx ; } buttonstate = digitalRead(A3); if(buttonstate != lastbuttonstate){ if(buttonstate == LOW) { ucg.setFont(ucg_font_ncenR10_tr); ucg.setColor(0,0,0); //blanks out old number ucg.setPrintPos(98,98); ucg.print(hertz); delay(10); setincrement(); } } }