The lower dash frequency can be tuned in 10Hz steps. TX shows when transmitting.
The Windows program "Argo", which I run on my iMac under "Wine" is suitable for reception. To remind you here's morse code!
And here's the SDR reception display, I am tuned to 10138.5kHz, so QRSS at around 10140kHz show as a 1500Hz signal in Argo.
This is pretty difficult to read, but with a little patience and practice it gets easier.
Code
// Universal_DFCW_KB sends a DFCW3 message from the KB // DFCW spacing is 0/5Hz // uses Universal VFO shield // 30m only (at the moment), start freq 1014000000cHz // 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), freq step 500cHz (5Hz) #define STEPS 1000 #define FREQ 500 // 3sec dot time #define DOT 3000 // ASCII input char msg[30]; bool newMsg = false; // start freqs uint32_t qrg = 1014000000; // SDR 10140kHz uint32_t dashFreq = 1014000000; // cHz; uint32_t dotFreq = dashFreq + FREQ; // +FREQ // 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); // CLK1 output qgr x 4, for IQ dds.set_freq(qrg * 4, 0ULL, SI5351_CLK2); // SDR tuned to QRG // VFO off, CLK2/IQ 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 (LOW) rx(); // receive freqOut(dashFreq); // init at dot freq dispMsg(0, 0, "DFCW "); // display title dispFreq(5, 0, dashFreq, 2); // display freq } void loop() { tune(); getMsg(); dfcwOut(); } void tune() { unsigned char dir; dir = rot.process(); // read encoder if (dir != DIR_NONE) // turned? { if (dir == DIR_CW) dashFreq += STEPS; // increment freq +/- STEPS if (dir == DIR_CCW) dashFreq -= STEPS; dotFreq = dashFreq + FREQ; // +5Hz dispFreq(5, 0, dashFreq, 2); // update freq display } } // 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 dfcwOut() { 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 on lcd // 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(1, 0, " "); // clear msg dispFreq(0, 4, dashFreq, 2); Serial.println(); rx(); // receive } newMsg = false; } // frequency (in cHz) for freq, 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; freqOut(dotFreq); 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; freqOut(dashFreq); 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 simple menu void dispMenu() { lcd.setCursor(0, 0); lcd.print("DFCW"); } // display character row r, col c void dispChar(uint8_t c, uint8_t r, char m) { lcd.setCursor(c, r); lcd.print(m); } // display char msg at col c, row r 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