I have already described a RTTY Beacon that just sends out regular fixed text messages. Here is a modification of that code that allows users to input text messages to be sent out. The Transmit frequency still remains fixed, but that can be updated in the future.
A new Serial Terminal software is used, in place of the one built in to the Arduino IDE (I have so often opened a sketch , opened the Serial Monitor, then accidentally typed text into the sketch not the monitor window! that I decided to use a dedicated Serial Terminal program, its called iSerialTerm (Mac only)).
Input text on iSerialTerm, on iMac, connected by USB to Arduino UNO/AD9850
Received text on SDR Concept radio and using HDSDR and MultiMode Cocoa decoder running on my MacBook
Code
// RTTY_TEXT
// V1.0 29-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
// message to send (u.c.)
char msg[40];
// freq in Hz and cHz
double freqHz = 7080000; // frequency Hz
double freqChz = 0; // sub freuency cHz
// ads (analog-output digital synthesiser) object
ADS9850 ads;
// lcd object
LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS);
void setup() {
// Serial
Serial.begin(9600);
// init LCD
lcd.begin();
//init AD9850, off to start
ads.begin(W_CLK, FQ_UD, DATA, RESET); // initialise synthesiser, pins
ads.down();
dispMsg(3, 0, "RTTY TEXT");
dispFreq(3, 1, freqHz, freqChz, 0);
}
void loop() {
if (getMsg(msg) == true) {
dispMsg(3, 1, "Sending Text... "); // sending
Serial.println(msg);
// send message at frequency
sendMsg(freqHz, freqChz, msg);
dispMsg(0, 1, " "); // clear line
}
clearBuf(msg);
}
void sendMsg(double fHz, double fChz, char *m) {
bool figsLtrs; // FIGS/LTRS toggle
char c;
figsLtrs = 1; // start in letter mode
rttyTxByte(fHz, fChz, 8); // LFCR for new message
rttyTxByte(fHz, fChz, 2);
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 fHzSymb, fChzSymb, rttyVaricode symb 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
}
// get input msg[] U.C.
bool getMsg(char *m)
{
char ch;
int n;
n = 0;
if (Serial.available() > 0) { // if input
while (Serial.available() > 0) { // get input
ch = Serial.read(); // use upper case as input
if (ch == '\n') ch = '\0'; // end of text
m[n++] = ch;
delay(20); // let USB catch up
}
return true; // got input
}
return false; // no input
}
// clear msg and buffer
void clearBuf(char *m) {
m[0] = '\0';
while (Serial.available() > 0) Serial.read();
}
// 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);
}