Arduino RTTY decoder

I guess this is the correct place to put this...
FFT code from: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286718155
This program decoders 45.4 RTTY on analog 0 and outputs it to the serial console.
It has quite a bit of limitations.
RTTY shift has to be between 160-182hz.
It has to be ~45.4 baud.
The decode output has errors in it and its just a proof of concept but still cool.
--edit--
Also the RTTY center frequency has to be 300hz +/- 10

#include <avr/pgmspace.h>
#include "fixfft.h"
#include "fix_fft.cpp"
#define THRESH 27 //Bit threshold adjust for best decode
#define CHK(x) (sqrt(real[x] * real[x] + imag[x] * imag[x])) Convert FFT output to more usable form
#define PCK(ar) (ar[0] | ar[1]<<1 | ar[2] << 2 | ar[3] << 3 | ar[4] << 4) //Pack bits into byte
unsigned char lookup[] = { //Baudot lookup table
  ' ', 'E' , ' ', 'A', ' ', 'S', 'I', 'U',
  '\n', 'D', 'R', 'J', 'N', 'F', 'C', 'K',
  'T', 'Z', 'L', 'W', 'H', 'Y', 'P', 'Q',
  'O', 'B', 'G', 0, 'M', 'X', 'V', 0, ' ', 
  '3', '\n', '-', ' ', '`', '8', '7',
  '\r', ' ', '4', ' ', ',', '!', ':', '(',
  '5', '+', ')', '2', '

, '6', '0', '1',
 '9', '?', '&', 0, '.', '/', ';', 0};
 int toffset=0; //Symbols and numbers shift

void setup(){
 Serial.begin(115200); //115200 baud output
 digitalWrite(A0, 1); //Turn this off depending on input source

}
void loop(){
 char bits[6]={0,0,0,0,0};
 char real[32],imag[32];
 int ticker = 0;
 unsigned char pbyte;
 for(int a = 0;a < 16;a++){
   real[a] = (analogRead(A0)-512) / 4; //Get samples
   imag[a] = 0;
   delayMicroseconds(780);
 }
 fix_fft(real, imag, 4, 0); //Preform FFT
   if(CHK(6) > THRESH){ //Got a start bit?
    for(int b = 0;b < 5;b++){  //Yes - start collecting bits
    delay(7); //For timing
    for(int a = 0;a < 16;a++){
   real[a] = (analogRead(A0)-512) / 4; //Get more samples
   imag[a] = 0;
   delayMicroseconds(780);
 }
   fix_fft(real, imag, 4, 0); //Preform FFT
   bits[b] = (CHK(6) > THRESH)? 0:1; //Check if we got a 1 or a 0
//    bits[b] = (CHK(7) > THRESH)? 1:0;
   }
   pbyte = PCK(bits); //Pack the byte
   if(pbyte == 0x1B){toffset=0x20; pbyte=0;} //Handle character set shift
   if(pbyte == 0x1F){toffset=0x00; pbyte=0;}
   Serial.print(lookup[pbyte+toffset]); //Print output
   ticker++;
   //if(ticker>60){ticker=0; Serial.println();}
/* for(int b = 0;b< 5;b++){
   
 }*/
//  Serial.println();
 delay(12); //For timing
 }

}

Well done.

I have a soft spot for RTTY as it was my first project that I ever sold. It was back in 1975 and before the days of micro processors gave you cheap peripherals. It was all done with TTL and produced a video output onto a TV screen. It contained about 40 chips. It was the first time most people had seen writing on a TV and they complained about the vertical scrolling it did.

Anyway this is certainly a lot simpler than my effort,
well done again.

Grumpy_Mike:
Well done.

I have a soft spot for RTTY as it was my first project that I ever sold. It was back in 1975 and before the days of micro processors gave you cheap peripherals. It was all done with TTL and produced a video output onto a TV screen. It contained about 40 chips. It was the first time most people had seen writing on a TV and they complained about the vertical scrolling it did.

Anyway this is certainly a lot simpler than my effort,
well done again.

Thank you.
BTW Another limitation is the center frequency needs to be around 300hz +/- 10

smeezekitty:
BTW Another limitation is the center frequency needs to be around 300hz +/- 10

No way to change this value?

It should be possible to change the center freq by increasing the sampling frequency reducing

delayMicroseconds(780);

on both lines but increasing the number of total samples is required to maintain timings. Also, if you increase the number of samples, the number of FFT bits will have to be proportionally increased.

fix_fft(real, imag, /*-->*/4/*<--*/, 0);

then

CHK(6)

would have to be increased to the correct FFT bin number.

I've calculate the values in an empiric way.
Later I'll do some tests.. but I don't understand how to find the FFT bit number for the CHK() function

Istevene:
I've calculate the values in an empiric way.
Later I'll do some tests.. but I don't understand how to find the FFT bit number for the CHK() function

This calculation could be wrong.
FFT bin width = ((Samplerate / 2) / (NumberOfSamples / 2)) * 2
CHK value = (SpaceFrequency / FFT bin width)
Then round CHK to the nearest integer.

Thanks for your help :slight_smile:
by the way is not working, I'll try something else.

Istevene:
Thanks for your help :slight_smile:
by the way is not working, I'll try something else.

Its quite particular and alittle difficult to get it to work.
But it is proof of concept only.

Hi, Since you are only looking at two frequencies, aren't there digital filtering algorithms that are less compute-intensive than FFT?? (Not that I know how to do this!)

I cheated and started with a simple PLL and then coded stuff. In 1975. In 6502 assembler . :slight_smile: History...

Signals are still fun!

terryking228:
Hi, Since you are only looking at two frequencies, aren't there digital filtering algorithms that are less compute-intensive than FFT?? (Not that I know how to do this!)

I cheated and started with a simple PLL and then coded stuff. In 1975. In 6502 assembler . :slight_smile: History...

Signals are still fun!

Probably. I know very little about DSP though.