Thursday 30 March 2017

BASIC Tech Group - MyNews 34 - More on RTTY, Text input

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)).

Screen Shot 2017 03 30 at 11 30 43 Input text on iSerialTerm, on iMac, connected by USB to Arduino UNO/AD9850

Screen Shot 2017 03 30 at 11 32 20 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);
}

No comments: