/**********************************************************
ASCII 8N2 50baud RTTY(T) v1.00 2016.11.30
/**********************************************************/
#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <FlexiTimer2.h>
#include <PS2Keyboard.h>
LiquidCrystal lcd(4,5,6,7,8,9,10);
/*
#define MARK 294 // 294 = (500000 / 1700 Hz)
#define SPACE 392 // 392 = (500000 / 1275 Hz)
*/
#define MARK 346 // 346 = (500000 / 1445 Hz)
#define SPACE 392 // 392 = (500000 / 1275 Hz)
PS2Keyboard keyboard;
const int DataPin = 2; //PS/2 DATA
const int IRQpin = 3; //PS/2 CLOCK
boolean snd;
boolean org;
int ti;
int x;
byte y;
char ch;
char c[33];
void setup()
{
Serial.begin(9600);
lcd.begin(16, 2);
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);
}
//8BIT ASCII GENERATOR
void timer2_interrupt(void)
{
static boolean bit1;
static boolean bit2;
static boolean bit3;
static boolean bit4;
static boolean bit5;
static boolean bit6;
static boolean bit7;
static boolean bit8;
if(snd == 1)
{
switch(ti)
{
case 0:
digitalWrite(13, 0);
Timer1.setPeriod(SPACE);
bit1 = ch & B00000001;
bit2 = ch & B00000010;
bit3 = ch & B00000100;
bit4 = ch & B00001000;
bit5 = ch & B00010000;
bit6 = ch & B00100000;
bit7 = ch & B01000000;
bit8 = ch & B10000000;
break;
case 20:
digitalWrite(13, bit1);
if(bit1){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 40:
digitalWrite(13, bit2);
if(bit2){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 60:
digitalWrite(13, bit3);
if(bit3){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 80:
digitalWrite(13, bit4);
if(bit4){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 100:
digitalWrite(13, bit5);
if(bit5){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 120:
digitalWrite(13, bit6);
if(bit6){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 140:
digitalWrite(13, bit7);
if(bit7){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 160:
digitalWrite(13, bit8);
if(bit8){Timer1.setPeriod(MARK);}
else{Timer1.setPeriod(SPACE);}
break;
case 180:
digitalWrite(13, 1);
Timer1.setPeriod(MARK);
break;
case 220:
snd = 0;
break;
}
ti++;
}
}
//DISPLAYS CHARACTER
void lcdOut()
{
int i;
lcd.print(ch);
c[16 * y + x] = ch;
x++;
if(x == 16 && y == 0)
{
x = 0; y = 1;
}
else if(x == 16 && y == 1)
{
for(i = 0; i < 16; i++)
{
c[i] = c[16 + i];
}
for(i = 0; i < 16; i++)
{
c[16 + i] = '\0';
}
lcd.clear();
lcd.noCursor();
for(i = 0; i < 16; i++)
{
lcd.print(c[i]);
}
lcd.cursor();
x = 0; y = 1;
}
lcd.setCursor(x, y);
}
//HANDLES BACKSPACE
void lcdBs()
{
int i;
if(x == 0 && y == 0)
{
org = true;
}
else
{
org = false;
x--;
if(x == -1 && y == 1)
{
x = 15; y = 0;
while(c[x] == '\0')
{
x--;
}
lcd.noCursor();
lcd.setCursor(x, y);
lcd.print(" ");
lcd.setCursor(x, y);
lcd.cursor();
c[x] = '\0';
}
else
{
lcd.noCursor();
lcd.setCursor(x, y);
lcd.print(" ");
lcd.setCursor(x, y);
lcd.cursor();
c[16 * y + x] = '\0';
}
}
}
//HANDLES CRLF
void lcdCrLf()
{
byte skip = (16 - x);
int i;
lcd.noCursor();
for(i = 0; i < skip; i++)
{
if(i == 0)
{
c[16 * y + x] = '\r';
}
else
{
c[16 * y + x] = '\0';
}
x++;
}
if(y == 0)
{
x = 0; y = 1;
}
else
{
for(i = 0; i < 16; i++)
{
c[i] = c[16 + i];
}
for(i = 0; i < 16; i++)
{
c[16 + i] = '\0';
}
lcd.clear();
for(i = 0; i < 16; i++)
{
if(c[i] == '\r' || c[i] == '\0')
{
lcd.print(' ');
}
else
{
lcd.print(c[i]);
}
}
x = 0; y = 1;
}
lcd.setCursor(x, y);
lcd.cursor();
}
void chIgnore()
{
if(ch == PS2_TAB ){ch = '\0';} //IGNORE THESE KEYS
else if(ch == PS2_ESC ){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';}
}
void loop()
{
static boolean crLf;
if(snd == 0)
{
if(crLf == 1)
{
crLf = 0;
lcdCrLf();
ch = '\n';
ti = 0; snd = 1; //2nd byte
}
else if (keyboard.available())
{
ch = keyboard.read();
chIgnore();
if(ch != '\0')
{
if(ch == PS2_BACKSPACE || ch == PS2_DELETE)
{
lcdBs();
if(org == false)
{
ch = 0x08; //BS
ti = 0; snd = 1; //1st byte
}
}
else if(ch == '\r')
{
crLf = 1;
ti = 0; snd = 1; //1st byte
}
else
{
lcdOut();
ti = 0; snd = 1; //1st byte
}
}
}
}
delay(5);
}