The LCD displays RX & TX and the message letter-by-letter as it is sent, with the output frequency.
The transmit frequency is preset at 101401000Hz (10140.100kHz), but can be tuned with the rotary encoder in 10Hz steps.
Code
// Universal_QRSS_KB sends a QRSS3 message from the KB // uses Universal VFO shield // 30m only (at the moment), at 1014000000Hz // IQ output for SDR GRG is at 10140kHz // tunable in 10Hz steps, button does nothing // ----- SHIELD CONNECTIONS // DDS I2C SI5351 // SCL = A5 // SDA = A4 // I2C address 0x60 // ------ // display I2C LCD 16 * 2 // o A5 SCL (y) // o A4 SDA (or) // o +5 (r) // o GND (bwn) // I2C address 0x27 // ----- // encoder KY-040 // o D2 DT (y) // o D3 CLK (g) // o +5 (r) // o GND (bwn) // I2C, Si5351 libraries #include "Wire.h" #include "si5351.h" #include "LiquidCrystal_I2C.h" #include "Rotary.h" // rotary Encoder pins 2 & 3 (DT & CLK), TX & RX enable (LOW) #define DT 2 #define CLK 3 #define TX 12 #define RX 13 // tuning freq STEPS, 1000cHz (10Hz) #define STEPS 1000 // 3sec dot time #define DOT 3000 // ASCII input char msg[30]; bool newMsg = false; // start freq uint32_t qrg = 1014000000; // SDR 10140kHz uint32_t freq = 1014000000; // cHz // dds object Si5351 dds; // lcd object LiquidCrystal_I2C lcd(0x27, 16, 2); // rotary Encoder object Rotary rot = Rotary(DT, CLK); // morse code strings, _ = dot space, 0-9 numbers, 10-36 A..Z // table from 0 - 36 char morse[][8] = { "-----_", // 0 ".----_", // 1-9 "..---_", "...--_", "....-_", "....._", "-...._", "--..._", "---.._", "----._", ".-_", // A "-..._", // B "-.-._", // C "-.._", // D "._", // E "..-._", // F "--._", // G "...._", // H ".._", // I ".---_", // J "-.-_", // K ".-.._", // L "--_", // M "-._", // N "---_", // O ".--._", // P "--.-_", // Q ".-._", // R "..._", // S "-_", // T "..-_", // U "...-_", // V ".--_", // W "-..-_", // X "-.--_", // Y "--.._", // Z "__", // word space }; void setup() { Serial.begin(9600); // init dds si5351 module, "0" = default 25MHz XTAL dds.init(SI5351_CRYSTAL_LOAD_8PF, 0); // CLK2 output qrg x 4, for IQ dds.set_freq(qrg * 4, 0ULL, SI5351_CLK2); // CLK2/IQ SDR tuned to 10104.00kHz // CLK 0, 1 off, CLK2 on dds.output_enable(SI5351_CLK0, 0); dds.output_enable(SI5351_CLK1, 0); dds.output_enable(SI5351_CLK2, 1); // SDR on // init LCD & backlight on lcd.init(); lcd.backlight(); // encoder, button, RX, TX, band and XMIT pins pinMode(DT, INPUT_PULLUP); pinMode(CLK, INPUT_PULLUP); pinMode(RX, OUTPUT); // SDR RX enable pinMode(TX, OUTPUT); // QRSS TX enable rx(); // receive freqOut(freq); // output freq dispMsg(0, 0, "QRSS "); // display title dispFreq(5, 0, freq, 2); // display freq } void loop() { tune(); getMsg(); qrssOut(); } void tune() { unsigned char dir; dir = rot.process(); // read encoder if (dir != DIR_NONE) // turned? { if (dir == DIR_CW) freq += STEPS; // increment freq +/- STEPS if (dir == DIR_CCW) freq -= STEPS; freqOut(freq); // output freq dispFreq(5, 0, freq, 2); // display freq } } // get input msg[] uc void getMsg() { static byte ndx = 0; // ndx into msg[] char in; while (Serial.available() > 0 && newMsg == false) { in = Serial.read(); if (in != '\n') { if (in >= 97 & in <= 122) in = in - 32; // to uc msg[ndx] = in; ndx++; } else { msg[ndx] = '\0'; // terminate msg Serial.write(msg); // echo msg ndx = 0; newMsg = true; } } } // look up morse string, send char by char void qrssOut() { static byte ndx; byte n; char c; // step along msg chraracters ndx = 0; while (msg[ndx] != '\0' && newMsg == true) { tx(); // transmit dispChar(ndx, 1, msg[ndx]); // display char at col ndx // convert to position in morse table // convert SPACE if (msg[ndx] == 32) c = msg[ndx] + 4; // convert ASCII else if (msg[ndx] >= 48 && msg[ndx] <= 57) // table 0-9 c = msg[ndx] - 48; else if (msg[ndx] >= 65 && msg[ndx] <= 90) // table A-Z (uc) c = msg[ndx] - 55; else if (msg[ndx] >= 97 && msg[ndx] <= 122) // table a-z (lc) c = msg[ndx] - 87; // output morse, up to SPACE n = 0; while (morse[c][n] != '_') { if (morse[c][n] == '.') dotOut(); // dot out else if (morse[c][n] == '-') dashOut(); // dash out n++; } spaceOut(); // end of char ndx++; } // end of msg if(newMsg == true) { dispMsg(0, 1, " "); // clear msg c, r Serial.println(); rx(); // receive } newMsg = false; } // QRSS frequency (in cHz) on CLK0 void freqOut(uint32_t f) { dds.set_freq(f, 0ULL, SI5351_CLK0); } // send a dot for DOT time void dotOut() { unsigned long t; dds.output_enable(SI5351_CLK0, 1); t = millis(); while (millis() < t + DOT); dds.output_enable(SI5351_CLK0, 0); t = millis(); while (millis() < t + DOT); } // send a dash for 3* DOT time void dashOut() { unsigned long t; dds.output_enable(SI5351_CLK0, 1); t = millis(); while (millis() < t + DOT * 3); dds.output_enable(SI5351_CLK0, 0); t = millis(); while (millis() < t + DOT); } // word space for 2 * DOT time (each character has its own one DOT space void spaceOut() { unsigned long t; t = millis(); while (millis() < t + DOT * 2); } //switch to transmit void tx() { digitalWrite(RX, HIGH); digitalWrite(TX, LOW); dispMsg(14, 1, "TX"); } // switch to receive void rx() { digitalWrite(TX, HIGH); digitalWrite(RX, LOW); dispMsg(14, 1, "RX"); } // display character m at col c void dispChar(uint8_t c, uint8_t r, char m) { lcd.setCursor(c, r); lcd.print(m); } // display msg on row l void dispMsg(uint8_t c, uint8_t r, char *m) { lcd.setCursor(c, r); lcd.print(m); } // display freq in kHz,col c, row r, d decimal places void dispFreq(uint8_t c, uint8_t r, uint32_t f, uint8_t d) { lcd.setCursor(c, r); // clear last freq display lcd.print(" "); lcd.setCursor(c, r); // clear last freq display lcd.print((float)f / 100000, d); // convert to float for print function lcd.print("kHz"); }
No comments:
Post a Comment