/**********************************************************
JI3BNB RTTY ENCODER for ARDUINO UNO <Simple Version>
2016.06.25 v3.1
5BIT-BAUDOT-CODE, 45.45baud
LCD 16x2 (SC1602BBWB-XA-GB-G) or 20x4 (UC-204)
/**********************************************************/
#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <FlexiTimer2.h>
#include <PS2Keyboard.h>
LiquidCrystal lcd(4,5,6,7,8,9,10);
const boolean lcdType = 0; // ***** 16x2: 0 / 20x4: 1 *****
#define MARK 346 // 346 = (500000 / 1445 Hz)
#define SPACE 392 // 392 = (500000 / 1275 Hz)
/*
#define MARK 218 // 218 = (500000 / 2295 Hz)
#define SPACE 235 // 235 = (500000 / 2125 Hz)
*/
PS2Keyboard keyboard;
const int DataPin = 2; //PS/2 DATA
const int IRQpin = 3; //PS/2 CLOCK
boolean ddl = 1; //DIDDLE ENABLE
boolean space;
boolean crLf;
boolean snd;
int fig_2;
int ti;
byte x;
char ch;
uint8_t baudot;
void setup()
{
if(lcdType == 0)
{
lcd.begin(16, 2);
}
else
{
lcd.begin(20, 4);
}
lcd.cursor();
lcd.setCursor(0, 0);
keyboard.begin(DataPin, IRQpin);
pinMode(12, OUTPUT); //--AFSK AUDIO OUTPUT
pinMode(13, OUTPUT); //--TTL LEVEL OUTPUT
digitalWrite(13, 1);
Timer1.initialize();
Timer1.attachInterrupt(timer1_interrupt, MARK);
FlexiTimer2::set(1, timer2_interrupt);
FlexiTimer2::start();
}
//AFSK TONE GENERATOR
void timer1_interrupt(void)
{
static boolean toggle;
toggle = toggle ^ 1;
digitalWrite(12, toggle);
}
//5BIT BAUDOT GENERATOR
void timer2_interrupt(void)
{
static boolean bit1;
static boolean bit2;
static boolean bit3;
static boolean bit4;
static boolean bit5;
if(snd == 1)
{
switch(ti)
{
case 0:
digitalWrite(13, 0);
Timer1.setPeriod(SPACE);
bit1 = baudot & B00001;
bit2 = baudot & B00010;
bit3 = baudot & B00100;
bit4 = baudot & B01000;
bit5 = baudot & B10000;
break;
case 22:
digitalWrite(13, bit1);
if(bit1){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 44:
digitalWrite(13, bit2);
if(bit2){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 66:
digitalWrite(13, bit3);
if(bit3){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 88:
digitalWrite(13, bit4);
if(bit4){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 110:
digitalWrite(13, bit5);
if(bit5){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 132:
digitalWrite(13, 1);
Timer1.setPeriod(MARK);
break;
case 165:
snd = 0;
break;
}
ti++;
}
}
//CONTROLS 16x2 or 20x4 LCD DISPLAY
void lcdOut()
{
static byte y;
int i;
if(lcdType == 0) //16x2
{
static char c[17];
lcd.print(ch);
c[x] = ch;
x++;
if(x == 16 && y == 0)
{
x = 0; y = 1;
}
else if(x == 16 && y == 1)
{
lcd.clear();
lcd.noCursor();
for(i = 0; i < 16; i++)
{
lcd.print(c[i]);
}
lcd.cursor();
x = 0; y = 1;
}
lcd.setCursor(x, y);
}
else //20x4
{
static char c[61];
lcd.print(ch);
if(y == 1){c[ x] = ch;}
else if(y == 2){c[20 + x] = ch;}
else if(y == 3){c[40 + x] = ch;}
x++;
if(x == 20 && y == 0){x = 0, y = 1;}
else if(x == 20 && y == 1){x = 0, y = 2;}
else if(x == 20 && y == 2){x = 0, y = 3;}
else if(x == 20 && y == 3)
{
lcd.clear();
lcd.setCursor(0, 0); for(i = 0; i < 20; i++){lcd.print(c[ i]);}
lcd.setCursor(0, 1); for(i = 0; i < 20; i++){lcd.print(c[20 + i]);}
lcd.setCursor(0, 2); for(i = 0; i < 20; i++){lcd.print(c[40 + i]);}
x = 0, y = 3;
for(i = 0; i < 20; i++){c[ i] = c[20 + i];}
for(i = 0; i < 20; i++){c[20 + i] = c[40 + i];}
}
lcd.setCursor(x, y);
}
}
void lcdCrLf()
{
byte rest;
if(lcdType == 0)
{
rest = (16 - x);
}
else
{
rest = (20 - x);
}
ch = ' ';
for(int i = 0; i < rest; i++) //FILL THE LINE WITH SPACES, INSTEAD OF CR&LF
{
lcdOut();
}
}
//LOOK UP TABLE
void chTable()
{
fig_2 = -1;
switch(ch)
{
case 'A': baudot = B00011; fig_2 = 0; break;
case 'B': baudot = B11001; fig_2 = 0; break;
case 'C': baudot = B01110; fig_2 = 0; break;
case 'D': baudot = B01001; fig_2 = 0; break;
case 'E': baudot = B00001; fig_2 = 0; break;
case 'F': baudot = B01101; fig_2 = 0; break;
case 'G': baudot = B11010; fig_2 = 0; break;
case 'H': baudot = B10100; fig_2 = 0; break;
case 'I': baudot = B00110; fig_2 = 0; break;
case 'J': baudot = B01011; fig_2 = 0; break;
case 'K': baudot = B01111; fig_2 = 0; break;
case 'L': baudot = B10010; fig_2 = 0; break;
case 'M': baudot = B11100; fig_2 = 0; break;
case 'N': baudot = B01100; fig_2 = 0; break;
case 'O': baudot = B11000; fig_2 = 0; break;
case 'P': baudot = B10110; fig_2 = 0; break;
case 'Q': baudot = B10111; fig_2 = 0; break;
case 'R': baudot = B01010; fig_2 = 0; break;
case 'S': baudot = B00101; fig_2 = 0; break;
case 'T': baudot = B10000; fig_2 = 0; break;
case 'U': baudot = B00111; fig_2 = 0; break;
case 'V': baudot = B11110; fig_2 = 0; break;
case 'W': baudot = B10011; fig_2 = 0; break;
case 'X': baudot = B11101; fig_2 = 0; break;
case 'Y': baudot = B10101; fig_2 = 0; break;
case 'Z': baudot = B10001; fig_2 = 0; break;
case '0': baudot = B10110; fig_2 = 1; break;
case '1': baudot = B10111; fig_2 = 1; break;
case '2': baudot = B10011; fig_2 = 1; break;
case '3': baudot = B00001; fig_2 = 1; break;
case '4': baudot = B01010; fig_2 = 1; break;
case '5': baudot = B10000; fig_2 = 1; break;
case '6': baudot = B10101; fig_2 = 1; break;
case '7': baudot = B00111; fig_2 = 1; break;
case '8': baudot = B00110; fig_2 = 1; break;
case '9': baudot = B11000; fig_2 = 1; break;
case '-': baudot = B00011; fig_2 = 1; break;
case '?': baudot = B11001; fig_2 = 1; break;
case ':': baudot = B01110; fig_2 = 1; break;
case '(': baudot = B01111; fig_2 = 1; break;
case ')': baudot = B10010; fig_2 = 1; break;
case '.': baudot = B11100; fig_2 = 1; break;
case ',': baudot = B01100; fig_2 = 1; break;
case '/': baudot = B11101; fig_2 = 1; break;
case '\r':
baudot = B01000; //CR
crLf = 1;
break;
case ' ':
baudot = B00100; //SPACE
space = 1;
break;
default:
ch = ' ';
baudot = B00100; //SPACE
space = 1;
break;
}
}
void chConvt()
{
if(ch >= 97 && ch <= 122) //CONVERT LOWER CASE TO UPPER CASE
{
ch = ch - 32;
}
else if(ch == PS2_TAB ){ch = '\0';} //IGNORE THESE KEYS
else if(ch == PS2_BACKSPACE ){ch = '\0';}
else if(ch == PS2_ESC ){ch = '\0';}
else if(ch == PS2_DELETE ){ch = '\0';}
else if(ch == PS2_PAGEUP ){ch = '\0';}
else if(ch == PS2_PAGEDOWN ){ch = '\0';}
else if(ch == PS2_UPARROW ){ch = '\0';}
else if(ch == PS2_LEFTARROW ){ch = '\0';}
else if(ch == PS2_DOWNARROW ){ch = '\0';}
else if(ch == PS2_RIGHTARROW){ch = '\0';}
else if(ch == '!' ){ch = '\0';}
else if(ch == '"' ){ch = '\0';}
else if(ch == '#' ){ch = '\0';}
else if(ch == '$' ){ch = '\0';}
else if(ch == '%' ){ch = '\0';}
else if(ch == '&' ){ch = '\0';}
else if(ch == '\'' ){ch = '\0';}
else if(ch == '=' ){ch = '\0';}
else if(ch == '^' ){ch = '\0';}
else if(ch == '~' ){ch = '\0';}
else if(ch == '|' ){ch = '\0';}
else if(ch == '@' ){ch = '\0';}
else if(ch == '`' ){ch = '\0';}
else if(ch == '[' ){ch = '\0';}
else if(ch == '{' ){ch = '\0';}
else if(ch == ';' ){ch = '\0';}
else if(ch == '+' ){ch = '\0';}
else if(ch == '*' ){ch = '\0';}
else if(ch == ']' ){ch = '\0';}
else if(ch == '}' ){ch = '\0';}
else if(ch == '<' ){ch = '\0';}
else if(ch == '>' ){ch = '\0';}
else if(ch == '\\' ){ch = '\0';}
else if(ch == '_' ){ch = '\0';}
}
void loop()
{
static boolean shift;
static boolean fig_1;
static uint8_t baudot_;
if(snd == 0)
{
if(shift == 1) //2ND BYTE AFTER SENDING SHIFT CODE
{
baudot = baudot_; //RESTORE
lcdOut();
shift = 0;
ti = 0; snd = 1; //SEND(2)
}
else if(crLf == 1) //2ND BYTE AFTER SENDING "CR"
{
baudot = B00010; //LF
lcdCrLf();
crLf = 0;
ti = 0; snd = 1; //SEND(2)
}
else //SENDING 2ND BYTE DONE
{
if (keyboard.available()) //KEYBOARD IS TYPED
{
ch = keyboard.read();
chConvt();
if(ch != '\0')
{
chTable();
if(fig_1 == 0 && fig_2 == 1) //SHIFT "UP"
{
baudot_ = baudot; //EVACUATE
baudot = B11011; //SEND FIGURE CODE FIRST
shift = 1;
}
else if(fig_1 == 1 && fig_2 == 0) //SHIFT "DOWN"
{
baudot_ = baudot; //EVACUATE
baudot = B11111; //SEND LETTER CODE FIRST
shift = 1;
}
else if(space == 1 && fig_2 == 1) //FIGURE AFTER SPACE (TX_UOS)
{
baudot_ = baudot; //EVACUATE
baudot = B11011; //SEND FIGURE CODE FIRST
shift = 1;
}
if(shift != 1 && crLf != 1)
{
lcdOut();
}
if(fig_2 == 0 || fig_2 == 1)
{
space = 0;
fig_1 = fig_2; //REGISTER LAST STATE (EXCEPT SPACE, CR&LF)
}
ti = 0; snd = 1; //SEND(1)
}
}
else //NOTHING TO PROCESS, DIDDLE
{
if(ddl == 1)
{
baudot = B11111; //LTR(DIDDLE)
fig_1 = 0;
ti = 0; snd = 1;
}
}
}
}
delay(5);
}