////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//   JI3BNB RTTY ENCODER for ARDUINO UNO <WORD-MODE-INPUT VERSION>
//   2016.06.27 v6.0
//   DESIGNED FOR AMATEUR RADIO COMMUNICATION
//   REALTIME KEYBOARD INPUT, 5BIT-BAUDOT-CODE, 45.45baud
//   LCD 20x4 (UC-204)
//   SCHEMATIC http://k183.bake-neko.net/ji3bnb/page13.html
//   ** THIS PROGRAM IS IN THE PUBLIC DOMAIN **
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////


////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                   -- BASIC SET UP AND PIN ASSIGNMENTS --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
     #include <TimerOne.h>

//   ** REQUIRE "TimerOne" LIBRARY **
//   http://playground.arduino.cc/code/timer1

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

////////////////////////////////////////////////////////////////////////////////
     #include <FlexiTimer2.h>

//   ** REQUIRE "FlexiTimer2" LIBRARY **
//   http://playground.arduino.cc/Main/FlexiTimer2

////////////////////////////////////////////////////////////////////////////////
     #include <PS2Keyboard.h>

//   ** REQUIRE "PS2Keyboard" LIBRARY **
//   http://playground.arduino.cc/Main/PS2Keyboard

     PS2Keyboard keyboard;
     const int  DataPin = 2; //IO2 = "DATA"  PIN
     const int  IRQpin  = 3; //IO3 = "CLOCK" PIN (!!DO NOT CAHNGE THIS)

     const boolean jp106 = 0;
//   SELECT 0: ENGLISH  KEYBOARD
//   SELECT 1: JAPANESE KEYBOARD 日本語キーボード

////////////////////////////////////////////////////////////////////////////////
     #include <LiquidCrystal.h>

//   20x4 LCD DISPLAY (HITACHI HD44780 INTERFACE)

     LiquidCrystal lcd(4,5,6,7,8,9,10);
//   D10 -> D7
//   D9  -> D6
//   D8  -> D5
//   D7  -> D4
//   D6  -> EN
//   D5  -> R/W
//   D4  -> RS

////////////////////////////////////////////////////////////////////////////////
//   YOU CAN DEFINE 22x MESSAGES TO EACH '1'-'0','F1'-'F12' KEY

//   NUMBER KEY '1'-'0'
     const char  n01[]  = "\rDE JI3BNB K ";
     const char  n02[]  = "\rDE JI3BNB JI3BNB K ";
     const char  n03[]  = "\rTODAY WX IS ";
     const char  n04[]  = "FINE ";
     const char  n05[]  = "CLOUDY ";
     const char  n06[]  = "RAIN ";
     const char  n07[]  = "\rTEMP IS ";
     const char  n08[]  = "\rRIG IC-7000M / ANT 15MH WHIP ";
     const char  n09[]  = "\rRRR UR 599 599 DE JI3BNB TU.. ";
     const char  n00[]  = "\rTU.. ";
     
//   FUNCTION KEY 'F1'-'F12'
     const char  f01[]  = "DE JI3BNB ";
     const char  f02[]  = "\rCQ CQ CQ DE JI3BNB JI3BNB JI3BNB JCC 2507 PSE K ";
     const char  f03[]  = "\rQRZ? SRI PSE AGN DE JI3BNB K ";
     const char  f04[]  = "\rTNX FER CALL ";
     const char  f05[]  = "GOOD MORNING ";
     const char  f06[]  = "GOOD AFTERNOON ";
     const char  f07[]  = "GOOD EVENING ";
     const char  f08[]  = "\rUR RST 599 599 599 "
                          "\rQTH JCC 2507 2507 2507 SUITA CITY OSAKA PREF. "
                          "\rOP KAZ KAZ KAZ "
                          "\rHOW COPY? BTU ";
     const char  f09[]  = "\rUR RST 579 579 579 "
                          "\rQTH JCC 2507 2507 2507 SUITA CITY OSAKA PREF. "
                          "\rOP KAZ KAZ KAZ "
                          "\rHOW COPY? BTU ";
     const char  f10[]  = "\rMY QSL CARD SURE VIA BURO ";
     const char  f11[]  = "\rTKS FB QSO HPE CU AGN ";
     const char  f12[]  = "\rTU GL SK.. ";
     
     const char* ms[]  = {n00,n01,n02,n03,n04,n05,n06,n07,n08,n09,f01,f02,f03,f04,f05,f06,f07,f08,f09,f10,f11,f12};

////////////////////////////////////////////////////////////////////////////////
//   D12 : ENCODER OUTPUT (AFSK AUDIO)

////////////////////////////////////////////////////////////////////////////////
//   D13 : ENCODER OUTPUT (0/5V TTL LEVEL)

////////////////////////////////////////////////////////////////////////////////
//   A0(=D14) : ESC INDICATOR

//   THIS INDICATOR MEANS "NOW IN <22CH MESSAGE MODE>"

////////////////////////////////////////////////////////////////////////////////
//   A1(=D15) : TX INDICATOR

//   ALSO PTT CONTROL VOLTAGE 

////////////////////////////////////////////////////////////////////////////////
//   A4(=D18) : TX SW

//   CONNECT TO GND WHEN TX

////////////////////////////////////////////////////////////////////////////////
//   "BAUDOT" CODE HAS SOME TYPES OF VARIATION

     const boolean  usFig  = 1;
//   SELECT 0: "TONO THETA-5000E" COMPATIBLE (ALSO "MixW" COMPATIBLE)
//   SELECT 1: "Fldigi" COMPATIBLE (=USTTY, POPULARLY USED)

////////////////////////////////////////////////////////////////////////////////
//   DIDDLE ENABLE AND INTERVAL PERIOD

     boolean    ddl     = 1;   //ENABLE
     const int  ddItv   = 260; //INTERVAL (ms)

////////////////////////////////////////////////////////////////////////////////
//   SPECIAL KEYS

//   [Esc]        :  GO INTO OR GO OUT OF <22CH MESSAGE MODE>
//   [DOWN ARROW] :  ENTER <WITHOUT> LINE FEED

////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                  -- GLOBAL VARIABLES, FLAGS, COUNTERS etc --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
boolean  space;
boolean  shift;
boolean  crLf;
boolean  fig_1;
int      fig_2;
byte     x;
byte     y;
byte     x4 = 1;
char     ch;
char     ch2;
uint8_t  baudot;
uint8_t  baudot_;

volatile boolean  snd;
volatile byte     ti;
volatile int      ddCnt;
volatile byte     tRx;
volatile byte     tRL;


////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                               -- setup() --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
void setup()
{
        keyboard.begin(DataPin, IRQpin);
        lcd.begin(20, 4);
        pinMode(12, OUTPUT);
        pinMode(13, OUTPUT);
        pinMode(14, OUTPUT);
        pinMode(15, OUTPUT);
        digitalWrite(13, 1);
        digitalWrite(18, 1); //INTERNAL PULL UP
        
        Timer1.initialize();
        
        FlexiTimer2::set(1, timer2_interrupt);
        FlexiTimer2::start();
        
        lcd.cursor();
        lcd.setCursor(0, 3);
        lcd.print(">6.0 READY");  //OPENING MESSAGE
        lcd.setCursor(0, 0);
        delay(1000);
        
        lcd.clear();
        lcd.setCursor(0, 3);
        lcd.print('>');
        lcd.setCursor(0, 0);
}


////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                           -- timer_interrupt --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
//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(tRx == 0 && digitalRead(18) == 0)
        {
                tRx = 1;
                tRL = 1;
        }
        else if(tRx == 1 || tRx == 2)
        {
                if(ddCnt < 2000)
                {
                        ddCnt++;
                }
                if(snd == 1)
                {
                        switch(ti)
                        {
                                case 0:
                                        ddCnt = 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++;
                }
        }
}


////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                        -- OTHER FUNCTIONS etc --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
//LINE1-3
void lcdChU()
{
        static char dBuf[41];
        int         i;
        
        lcd.print(ch);
             if(y == 1){dBuf[     x] = ch;}
        else if(y == 2){dBuf[20 + 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)
        {
                lcd.setCursor(0, 0); for(i = 0; i < 20; i++){lcd.print(dBuf[     i]);}
                lcd.setCursor(0, 1); for(i = 0; i < 20; i++){lcd.print(dBuf[20 + i]);}
                lcd.setCursor(0, 2); for(i = 0; i < 20; i++){lcd.print(' ');}
                x = 0, y = 2;
                for(i = 0; i < 20; i++){dBuf[i] = dBuf[20 + i];}
        }
        lcd.setCursor(x, y);
}

void lcdCrLf()
{
        byte rest = (20 - x);
        ch = ' ';
        lcd.noCursor();
        for(int i = 0; i < rest; i++) //FILL THE LINE WITH SPACES, INSTEAD OF CR&LF
        {
                lcdChU();
        }
        lcd.cursor();
}

//LINE4
void lcdChL()
{
        lcd.noCursor();
        lcd.setCursor(x4, 3);
        lcd.print(ch2);
        x4++;
        lcd.setCursor(x, y);
        lcd.cursor();
}

//LOOK UP TABLE
void chTableT()
{
        if(usFig == 1) //"Fldigi" COMPATIBLE
        {
                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;
                        
                        //"Fldigi" COMPATIBLE
                        case '$' : baudot = B01001; fig_2 = 1; break;
                        case '\'': baudot = B01011; fig_2 = 1; break;
                        case '!' : baudot = B01101; fig_2 = 1; break;
                        case '"' : baudot = B10001; fig_2 = 1; break;
                        case '#' : baudot = B10100; fig_2 = 1; break;
                        case '&' : baudot = B11010; fig_2 = 1; break;
                        case ';' : baudot = B11110; fig_2 = 1; break;
                        
                        case '\r':
                                baudot = B01000; //CR
                                crLf = 1;
                                break;
                        case ' ':
                                baudot = B00100; //SPACE
                                space = 1;
                                break;
                        
                        case PS2_ESC:
                                break;
                        case 14:
                        case 15:
                        case 16:
                        case 17:
                        case 18:
                        case 19:
                        case 20:
                        case 21:
                        case 22:
                        case 23:
                        case 24:
                        case 25:
                                break;
                        
                        default:
                                ch = ' ';
                                baudot = B00100; //SPACE
                                space = 1;
                                break;
                }
        }
        else if(usFig == 0) //"TONO THETA-5000E" COMPATIBLE
        {
                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;
                        
                        //"TONO THETA-5000E" COMPATIBLE
                        case '\'': baudot = B00101; fig_2 = 1; break;
                        case '$' : baudot = B01001; fig_2 = 1; break;
                        case '!' : baudot = B01101; fig_2 = 1; break;
                        case '+' : baudot = B10001; fig_2 = 1; break;
                        case '#' : baudot = B10100; fig_2 = 1; break;
                        case '&' : baudot = B11010; fig_2 = 1; break;
                        case '=' : baudot = B11110; fig_2 = 1; break;
                        
                        case '\r':
                                baudot = B01000; //CR
                                crLf = 1;
                                break;
                        case ' ':
                                baudot = B00100; //SPACE
                                space = 1;
                                break;
                        
                        case PS2_ESC:
                                break;
                        case 14:
                        case 15:
                        case 16:
                        case 17:
                        case 18:
                        case 19:
                        case 20:
                        case 21:
                        case 22:
                        case 23:
                        case 24:
                        case 25:
                                break;
                        
                        default:
                                ch = ' ';
                                baudot = B00100; //SPACE
                                space = 1;
                                break;
                }
        }
}

void chConvt()
{
        if(jp106 == 1) //JP106 KEYBOARD
        {
                switch(ch2){ 
                        case '@' : ch2 = '"' ; break;
                        case '^' : ch2 = '&' ; break;
                        case '&' : ch2 = '\''; break;
                        case '*' : ch2 = '(' ; break;
                        case '(' : ch2 = ')' ; break;
                        case ')' : ch2 = '~' ; break;
                        case '_' : ch2 = '=' ; break;
                        case '=' : ch2 = '^' ; break;
                        case '+' : ch2 = '\0'; break;
                        case '[' : ch2 = '@' ; break;
                        case '{' : ch2 = '`' ; break;
                        case ']' : ch2 = '[' ; break;
                        case '}' : ch2 = '{' ; break;
                        case ':' : ch2 = '+' ; break;
                        case '\'': ch2 = ':' ; break;
                        case '"' : ch2 = '*' ; break;
                        case '\\': ch2 = ']' ; break;
                        case '|' : ch2 = '}' ; break;
                }
        }
        if(usFig == 1) //"Fldigi" COMPATIBLE
        {
                if(ch2 >= 97 && ch2 <= 122) //CONVERT LOWER CASE TO UPPER CASE
                {
                        ch2 = ch2 - 32;
                }
                else if(ch2 == PS2_TAB       ){ch2 = '\0';} //IGNORE THESE KEYS
                else if(ch2 == PS2_PAGEUP    ){ch2 = '\0';}
                else if(ch2 == PS2_PAGEDOWN  ){ch2 = '\0';}
                else if(ch2 == PS2_UPARROW   ){ch2 = '\0';}
                else if(ch2 == PS2_LEFTARROW ){ch2 = '\0';}
                else if(ch2 == PS2_RIGHTARROW){ch2 = '\0';}
                else if(ch2 == '%'           ){ch2 = '\0';}
                else if(ch2 == '='           ){ch2 = '\0';}
                else if(ch2 == '^'           ){ch2 = '\0';}
                else if(ch2 == '~'           ){ch2 = '\0';}
                else if(ch2 == '|'           ){ch2 = '\0';}
                else if(ch2 == '@'           ){ch2 = '\0';}
                else if(ch2 == '`'           ){ch2 = '\0';}
                else if(ch2 == '['           ){ch2 = '\0';}
                else if(ch2 == '{'           ){ch2 = '\0';}
                else if(ch2 == '+'           ){ch2 = '\0';}
                else if(ch2 == '*'           ){ch2 = '\0';}
                else if(ch2 == ']'           ){ch2 = '\0';}
                else if(ch2 == '}'           ){ch2 = '\0';}
                else if(ch2 == '<'           ){ch2 = '\0';}
                else if(ch2 == '>'           ){ch2 = '\0';}
                else if(ch2 == '\\'          ){ch2 = '\0';}
                else if(ch2 == '_'           ){ch2 = '\0';}
        }
        else if(usFig == 0) //"TONO THETA-5000E" COMPATIBLE
        {
                if(ch2 >= 97 && ch2 <= 122) //CONVERT LOWER CASE TO UPPER CASE
                {
                        ch2 = ch2 - 32;
                }
                else if(ch2 == PS2_TAB       ){ch2 = '\0';} //IGNORE THESE KEYS
                else if(ch2 == PS2_PAGEUP    ){ch2 = '\0';}
                else if(ch2 == PS2_PAGEDOWN  ){ch2 = '\0';}
                else if(ch2 == PS2_UPARROW   ){ch2 = '\0';}
                else if(ch2 == PS2_LEFTARROW ){ch2 = '\0';}
                else if(ch2 == PS2_RIGHTARROW){ch2 = '\0';}
                else if(ch2 == '"'           ){ch2 = '\0';}
                else if(ch2 == '%'           ){ch2 = '\0';}
                else if(ch2 == '^'           ){ch2 = '\0';}
                else if(ch2 == '~'           ){ch2 = '\0';}
                else if(ch2 == '|'           ){ch2 = '\0';}
                else if(ch2 == '@'           ){ch2 = '\0';}
                else if(ch2 == '`'           ){ch2 = '\0';}
                else if(ch2 == '['           ){ch2 = '\0';}
                else if(ch2 == '{'           ){ch2 = '\0';}
                else if(ch2 == ';'           ){ch2 = '\0';}
                else if(ch2 == '*'           ){ch2 = '\0';}
                else if(ch2 == ']'           ){ch2 = '\0';}
                else if(ch2 == '}'           ){ch2 = '\0';}
                else if(ch2 == '<'           ){ch2 = '\0';}
                else if(ch2 == '>'           ){ch2 = '\0';}
                else if(ch2 == '\\'          ){ch2 = '\0';}
                else if(ch2 == '_'           ){ch2 = '\0';}
        }
}

void chFlush()
{
        while(keyboard.available())
        {
                ch = keyboard.read();
        }
}

void chSend1()
{
        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)
        {
                lcdChU();
        }
        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)
}

void chSend2()
{
        if(shift == 1) //2ND BYTE AFTER SENDING SHIFT CODE
        {
                baudot = baudot_; //RESTORE
                lcdChU();
                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)
        }
}


////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//                             -- MAIN LOOP --
//
////////////////////////////////////////////////////////////////////////////////
                                        ////////////////////////////////////////
void loop()
{
        static boolean esc;
        
        if(tRx == 1) //RX to TX
        {
                if(snd == 0)
                {
                        if(tRL == 1) //1st loop
                        {
                                chFlush();
                                digitalWrite(15, 1);
                                Timer1.attachInterrupt(timer1_interrupt, MARK);
                                delay(180);
                                //-----
                                baudot = B01000; //-- CR --
                                ti = 0; snd = 1;
                                //-----
                                tRL = 2;
                        }
                        else if(tRL == 2) //2nd loop
                        {
                                lcdCrLf();
                                //-----
                                baudot = B00010; //-- LF --
                                ti = 0; snd = 1;
                                //-----
                                tRL = 3;
                        }
                        else if(tRL == 3) //3rd loop
                        {
                                fig_1 = 0;
                                //-----
                                baudot = B11111; //-- LTR (INITIALIZE "HIS/ HER" RECIEVER) --
                                ti = 0; snd = 1;
                                //-----
                                tRx = 2;
                        }
                }
        }
        else if(tRx == 2) //TX
        {
                static int  msNo = -1;
                static char mnBuf[8];
                static byte m;
                static byte n;
                static byte o;
                
                if(esc == 1)
                {
                        if(snd == 0)
                        {
                                if(shift == 1 || crLf == 1) //TOP PRIORITY (WHEN 2ND BYTE IS NEEDED)
                                {
                                        chSend2();
                                }
                                else if(msNo >= 0) //HANDLES FIXED MESSAGES (MAIN)
                                {
                                        if(digitalRead(18) == 1) //CHECK SW
                                        {
                                                msNo = -1;
                                                n = 0;
                                                goto exitTx;
                                        }
                                        ch = ms[msNo][m]; //READ OUT
                                        if(ch == '\0') //END OF SENTENCE
                                        {
                                                msNo = -1;
                                                if(n == 0) //NO MESSAGE-NUMBER IS STORED FROM THE FIRST, EXIT
                                                {
                                                        esc = 0; digitalWrite(14, 0);
                                                }
                                        }
                                        while(keyboard.available()) //ALWAYS CHECK KEYBOARD
                                        {
                                                ch2 = keyboard.read();
                                                if(ch2 == PS2_ESC) //WHEN [Esc] IS TYPED, STOP IMMEDIATELY, AND EXIT
                                                {
                                                        msNo = -1;
                                                        n = 0;
                                                        esc = 0; digitalWrite(14, 0);
                                                }
                                                else if(ch2 >= 48 && ch2 <= 57) //'0'-'9'
                                                {
                                                        if(n < 7)
                                                        {
                                                                mnBuf[n] = ch2; //REGISTER ADDITIONAL MESSAGE-NUMBERS, 7 NUMBERS AT MAXIMUM
                                                                n++;
                                                        }
                                                }
                                                else if(ch2 >= 14 && ch2 <= 25) //'F1'-'F12'
                                                {
                                                        if(n < 7)
                                                        {
                                                                mnBuf[n] = ch2; //REGISTER ADDITIONAL MESSAGE-NUMBERS, 7 NUMBERS AT MAXIMUM
                                                                n++;
                                                        }
                                                }
                                        }
                                        if(msNo >= 0) //--SEND STORED MESSAGE--
                                        {
                                                chTableT();
                                                chSend1();
                                                m++;
                                        }
                                }
                                else if(n > 0) //COMPLETED SENDING <ONE> FIXED MESSAGE, AND OTHERS STILL REMAIN
                                {
                                        ch = mnBuf[o]; //READ OUT
                                        if(ch >= 48 && ch <= 57) //'0'-'9'
                                        {
                                                msNo = ch - 48; //SPECIFY THE NEXT
                                                m = 0;
                                                o++;
                                        }
                                        else if(ch >= 14 && ch <= 25) //'F1'-'F12'
                                        {
                                                msNo = ch - 4; //SPECIFY THE NEXT
                                                m = 0;
                                                o++;
                                        }
                                        else if(ch == '\0') //THE END OF THE MESSAGE-NUMBERS, EXIT
                                        {
                                                n = 0;
                                                esc = 0; digitalWrite(14, 0);
                                        }
                                }
                                else if (keyboard.available()) //COMPLETED SENDING <ALL> FIXED MESSAGES, AND KEYBOARD IS TYPED
                                {
                                        if(digitalRead(18) == 1) //CHECK SW
                                        {
                                                goto exitTx;
                                        }
                                        ch = keyboard.read();
                                        if(ch == PS2_ESC) //GO OUT OF [Esc] MODE
                                        {
                                                esc = 0;
                                                digitalWrite(14, 0);
                                        }
                                        else if(ch >= 48 && ch <= 57) //'0'-'9'
                                        {
                                                msNo = ch - 48; //WHEN esc=1 AND A MESSAGE KEY IS TYPED, START SENDING A NEW ONE
                                                //--Ini
                                                m = 0;
                                                o = 0;
                                                for(int i = 0; i < 7; i++)
                                                {
                                                        mnBuf[i] = '\0';
                                                }
                                                //--
                                        }
                                        else if(ch >= 14 && ch <= 25) //'F1'-'F12'
                                        {
                                                msNo = ch - 4; //WHEN esc=1 AND A MESSAGE KEY IS TYPED, START SENDING A NEW ONE
                                                //--Ini
                                                m = 0;
                                                o = 0;
                                                for(int i = 0; i < 7; i++)
                                                {
                                                        mnBuf[i] = '\0';
                                                }
                                                //--
                                        }
                                }
                                else
                                {
                                        if(digitalRead(18) == 1) //CHECK SW
                                        {
                                                goto exitTx;
                                        }
                                        else //NOTHING TO PROCESS, DIDDLE
                                        {
                                                if(ddl == 1 && ddCnt > ddItv)
                                                {
                                                        fig_1 = 0;
                                                        baudot = B11111; //LTR (DIDDLE)
                                                        ti = 0; snd = 1;
                                                }
                                        }
                                } 
                        }
                }
                else if(esc == 0)
                {
                        static byte sWait;
                        static byte wdNo;
                        static byte w;
                        static char sBuf[8][21];
                        static char iBuf[21];
                        
                        if(keyboard.available())
                        {
                                ch2 = keyboard.read();
                                chConvt();
                                if(ch2 != '\0')
                                {
                                        if(ch2 >= 14 && ch2 <= 25) //IF A FUNCTION KEY IS TYPED, START 22CH MESSAGE MODE
                                        {
                                                msNo = ch2 - 4;
                                                //--Ini
                                                m = 0;
                                                o = 0;
                                                for(int i = 0; i < 7; i++)
                                                {
                                                        mnBuf[i] = '\0';
                                                }
                                                //--
                                                
                                                //---sBuf ALL CLEAR
                                                sWait = 0;
                                                for(wdNo = 0; wdNo < 8; wdNo++)
                                                {
                                                        //---sBuf CLEAR [wdNo]
                                                        for(int i = 0; i < 20; i++)
                                                        {
                                                                sBuf[wdNo][i] = '\0';
                                                        }
                                                        //---
                                                }
                                                //---
                                                w = 0;
                                                esc = 1;
                                                digitalWrite(14, 1);
                                        }
                                        else if(ch2 == PS2_ESC) //CHANGE TO [Esc] MODE
                                        {
                                                //---sBuf ALL CLEAR
                                                sWait = 0;
                                                for(wdNo = 0; wdNo < 8; wdNo++)
                                                {
                                                        //---sBuf CLEAR [wdNo]
                                                        for(int i = 0; i < 20; i++)
                                                        {
                                                                sBuf[wdNo][i] = '\0';
                                                        }
                                                        //---
                                                }
                                                //---
                                                w = 0;
                                                esc = 1;
                                                digitalWrite(14, 1);
                                        }
                                        else if(sWait < 8 && x4 < 21)  //STORE 8 WORDS AT MAXIMUM
                                        {
                                                if(ch2 == ' ' || ch2 == '\r' || ch2 == PS2_DOWNARROW)
                                                {
                                                        if(ch2 != PS2_DOWNARROW)
                                                        {
                                                                iBuf[x4 - 1] = ch2;
                                                        }
                                                        if(sWait == 0)
                                                        {
                                                                w = 0;
                                                        }
                                                        sWait++;
                                                        int i = 0;
                                                        while(iBuf[i] != '\0')
                                                        {
                                                                sBuf[sWait - 1][i] = iBuf[i];
                                                                i++;
                                                        }
                                                        
                                                        //---iBuf CLEAR
                                                        for(int i = 0; i < 20; i++)
                                                        {
                                                                iBuf[i] = '\0';
                                                        }
                                                        //---
                                                        
                                                        //---LINE4 CLEAR
                                                        lcd.noCursor();
                                                        lcd.setCursor(1, 3);
                                                        for(int i = 0; i < 19; i++)
                                                        
                                                        {
                                                                lcd.print(' ');
                                                        }
                                                        x4 = 1;
                                                        lcd.setCursor(x, y);
                                                        lcd.cursor();
                                                        //---
                                                }
                                                else if(ch2 == PS2_BACKSPACE) //HANDLES [Delete] or [Back space] KEY
                                                {
                                                        if(x4 > 1)
                                                        {
                                                                x4--;
                                                                iBuf[x4 - 1] = '\0';
                                                                lcd.noCursor();
                                                                lcd.setCursor(x4, 3);
                                                                lcd.print(' ');
                                                                lcd.setCursor(x, y);
                                                                lcd.cursor();
                                                        }
                                                }
                                                else if(x4 < 20)
                                                {
                                                        iBuf[x4 - 1] = ch2;
                                                        lcdChL();
                                                }
                                        }
                                }
                        }
                        else if(snd == 0)
                        {
                                if(shift == 1 || crLf == 1) //TOP PRIORITY (WHEN 2ND BYTE IS NEEDED)
                                {
                                        chSend2();
                                }
                                else if(sWait > 0)
                                {
                                        if(digitalRead(18) == 1) //CHECK SW
                                        {
                                                //---sBuf ALL CLEAR
                                                sWait = 0;
                                                for(wdNo = 0; wdNo < 8; wdNo++)
                                                {
                                                        //---sBuf CLEAR [wdNo]
                                                        for(int i = 0; i < 20; i++)
                                                        {
                                                                sBuf[wdNo][i] = '\0';
                                                        }
                                                        //---
                                                }
                                                //---
                                                w = 0;
                                                goto exitTx;
                                        }
                                        wdNo = 0;
                                        ch = sBuf[wdNo][w]; //RAED OUT
                                        if(ch == '\0')
                                        {
                                                sWait--;
                                                for(wdNo = 0; wdNo < sWait; wdNo++)
                                                {
                                                        //---sBuf CLEAR [wdNo]
                                                        for(int i = 0; i < 20; i++)
                                                        {
                                                                sBuf[wdNo][i] = '\0';
                                                        }
                                                        //---
                                                        w = 0;
                                                        while(sBuf[wdNo + 1][w] != '\0')
                                                        {
                                                                sBuf[wdNo][w] = sBuf[wdNo + 1][w]; //---SHIFT TO "LEFT"
                                                                w++;
                                                        }
                                                }
                                                //---sBuf CLEAR [wdNo]
                                                for(int i = 0; i < 20; i++)
                                                {
                                                        sBuf[wdNo][i] = '\0';
                                                }
                                                //---
                                                w = 0;
                                        }
                                        else
                                        {
                                                chTableT();
                                                chSend1();
                                                w++;
                                        }
                                }
                                else
                                {
                                        if(digitalRead(18) == 1) //CHECK SW
                                        {
                                                exitTx: //-LABEL-
                                                delay(370);          //LONG TONE
                                                digitalWrite(15, 0); //CARRIER OFF
                                                Timer1.detachInterrupt();
                                                esc = 0; digitalWrite(14, 0);
                                                snd = 0;
                                                tRx = 0;
                                        }
                                        else //NOTHING TO SEND, DIDDLE
                                        {
                                                if(ddl == 1 && ddCnt > ddItv)
                                                {
                                                        fig_1 = 0;
                                                        baudot = B11111; //LTR (DIDDLE)
                                                        ti = 0; snd = 1;
                                                }
                                        }
                                }
                        }
                }
        }
        delay(3);
}

//   -- END OF THE SKETCH --
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////