To round off this session on generating various digital transmissions with the AD9850 synthesiser and the Arduino, here is the RTTY one.
Beacon Tx
SDR RX
Received signals, using MacOS MultiMode Cooca software
And here's the code
// BCN_RTTY Beacon for RTTY // V1.1 9-3-17 // thanks to F0GOJ for some of the code // AD9850 // W_CLK 8 // FQ_UD 9 // DATA 10 // RESET 11 // LCD I2C bus (16x2) // SDA = A4 // SCL = A5 // ADS9850, LCD and Rotary Encoder libraries #include "ADS9850.h" #include "LiquidCrystal_I2C.h" // AD9850 pins #define W_CLK 8 #define FQ_UD 9 #define DATA 10 #define RESET 11 // chose address of 0x27 or 0x3F for LCD //#define LCDADDR 0x27 #define LCDADDR 0x3F #define LCDCOLS 16 #define LCDROWS 2 // baudot varicode in b4-b0 (sent b0->b4) char rttyVaricode[59] = { 4, 22, 17, 5, 18, 0, 11, 26, 30, 9, 0, 0, 6, 24, 7, 23, 13, 29, 25, 16, 10, 1, 21, 28, 12, 3, 14, 15, 0, 0, 0, 19, 0, 24, 19, 14, 18, 16, 22, 11, 5, 12, 26, 30, 9, 7, 6, 3, 13, 29, 10, 20, 1, 28, 15, 25, 23, 21, 17 }; #define FIGS 27 #define LTRS 31 // beacon message to send (u.c.) char msg[] = "RTTY BCN M0IFA"; // freq in Hz and cHz double freqHz = 7080000; // frequency Hz double freqChz = 0; // sub freuency cHz // repeat time (ms) unsigned long repeat = 2000; // ads (analog-output digital synthesiser) object ADS9850 ads; // lcd object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); void setup() { // init LCD lcd.begin(); //init AD9850 ads.begin(W_CLK, FQ_UD, DATA, RESET); // initialise synthesiser, pins dispMsg(0, 0, "RTTY"); dispFreq(5, 0, freqHz, freqChz, 0); // display FREQ xxxxxx.xx kHz col 5 row 0 dispMsg(0, 1, msg); // out msg } void loop() { // send message at frequency sendMsg(freqHz, freqChz, msg); delay(repeat); // repeat } void sendMsg(double fHz, double fChz, char *m) { bool figsLtrs; // FIGS/LTRS toggle char c; figsLtrs = 1; // start in letter mode c = *m++; while ( c != '\0') { // EOM? c = toupper((int)c); // get char, uppercase if (c == 10) { // Line Feed 8 rttyTxByte(fHz, fChz, 8); } else if (c == 13) { // Carriage Return 2 rttyTxByte(fHz, fChz, 2); } else if (c == 32) { rttyTxByte(fHz, fChz, 4); } else if (c > ' ' && c <= 'Z' ) { // non-baudot chars sent as blanks 00000 c = c - ' '; // c index 0-58 if (c < 33) { if (figsLtrs == 1) { // if LTRS figsLtrs = 0; // toggle to FIGS rttyTxByte(fHz, fChz, FIGS); // send 27 } } else if (figsLtrs == 0) { // if FIGS figsLtrs = 1; // toggle to LTRS rttyTxByte(fHz, fChz, LTRS); // send 31 } rttyTxByte(fHz, fChz, rttyVaricode[c]); // Send the 5 bits word } c = *m++; // Next character in string } ads.down(); } // send at fHz, fChz, rttyVaricode s(ymb nnnnn void rttyTxByte(long fHzSymb, long fChzSymb, char symb) { int bits, val; // build the byte to send symb = (symb << 2) + 3; // shift two left, add B00000011, makes B0nnnnn11 for (bits = 7; bits >= 0; bits--) { // MSB first, b7 -> b0 val = bitRead(symb, bits); // Read 1 bit ads.setFreq(fHzSymb + (170 * val), fChzSymb, 0); // Let's transmit (bit 1 is 170Hz shifted up) delay(22); // Gives the baud rate, 22ms per bit } delay(110); // intersumbol pause } // display freq at c)ol, r)ow, f (cHz), d decimal places void dispFreq(uint8_t c, uint8_t r, float f, float cf, uint8_t d) { lcd.setCursor(c, r); lcd.print((f + cf / 100.0), d); lcd.print("Hz "); } // display msg *m at c)ol, r)ow void dispMsg(uint8_t c, uint8_t r, char *m) { lcd.setCursor(c, r); lcd.print(m); }I am not too happy with this code as it seems VERY timing sensitive.
No comments:
Post a Comment