#include <LiquidCrystal.h> //include the lcd library
const byte row1=3; //keypad row pins, shared with the lcd data lines
const byte row2=4;
const byte row3=5;
const byte row4=6;
const byte col1=7; //keypad column lines
const byte col2=8;
const byte col3=9;
const byte col4=10;
LiquidCrystal lcd(12, 11, row4, row3, row2, row1); //lcd object
byte numpressed; //latest number pressed on the keypad
byte timespressed; //times the number has been pressed
byte cursorx=0; //cursor x position
byte cursory=0; //cursor y position
char letter; //stores letter that needs to be printed to the lcd
const int wait=1000; //time to wait for additional presses to same number
const int preventholddelay=150; //time to wait to prevent cycling through things too quickly
unsigned long basetime; //base time for while loop
unsigned long elapsed=0; //elapsed time in while loop
byte lastnumpressed; //the initial number pressed on the keypad
bool disablespacedelay=false; //disables the delay in the space function in the case that a different number is pressed while in while loop
const byte maxtimespressed[16]={
1,3,4,4,4,4,4,4,4,4,1,7,1,1,1,1}; //stores maximum number of times any given key can be pressed before looping back to its first letter (used by incrementtimespressed function)
char typedtext[140]; //stores typed text for printout to the serial console
int positionintypedtext=0; //position in typedtext character array
int charremaining; //remaining characters in message
bool promptkeypress=false; //used for waiting for, and keypress detection, at the end-of composition prompt
void setup(){
Serial.begin(115200); //start serial communication so that we can print the typed text to the serial console
lcd.begin(16,2); //initialize the lcd
lcd.setCursor(cursorx,cursory); //set the lcd cursor
lcd.noCursor(); //turn off the cursor
pinMode(row1,OUTPUT); //set the rows as outputs
pinMode(row2,OUTPUT);
pinMode(row3,OUTPUT);
pinMode(row4,OUTPUT);
pinMode(col1,INPUT); //set the columns as inputs
pinMode(col2,INPUT);
pinMode(col3,INPUT);
pinMode(col4,INPUT);
delay(wait);
lcd.cursor(); //turn the cursor on again after a delay equivalent to wait
rowshigh(); //sets all rows high
}
void loop(){
numpressed=16; //reset "numpressed" (16 doesn't refer to any button on the pad)
if (findpress()){ //look for presses, if one has occurred, identify it and continue
timespressed=0; //reset "timespressed"
if (numpressed==0){ //if zero on the pad was pressed,
dozero(); //print zero
letter='0'; //manually seed a zero as the character for the text storage
textstorage(1); //regular character storage
}
if (numpressed==10){ //if shift on the pad was pressed,
textstorage(2); //perform a space in storage
dospace(); //do a space
}
if (numpressed==14){ //if the arrows on the pad were pressed,
textstorage(3); //perform a backspace in storage
dobackspace(); //do a backspace
}
if (numpressed==15){ //if enter on the pad was pressed,
outputserial(); //output message and display remaining characters to serial console
}
if ((numpressed<10&&numpressed>0)||numpressed==11){ //if 1,2,3,4,5,6,7,8,9, or 11 was pressed (any one of the keys with multiple characters assigned),
lastnumpressed=numpressed; //record which number was pressed,
basetime=millis(); //and take a base time for the while loop
while (elapsed<wait){ //while below the time to wait,
if(findpress()){ //look for presses, if one has occurred, identify it and continue
if (numpressed==lastnumpressed){ //if it was the same as before,
incrementtimespressed(); //increment "timespressed"
basetime=basetime+(wait-(wait-elapsed)); //roll up the base time, to allow another wait period until next press of the same button
definepress(); //use "numpressed" and "timespressed" to define "letter"
lcd.print(letter); //print the letter that was defined
lcd.setCursor(cursorx,cursory); //maintain cursor position
rowshigh(); //return all rows high
delay(preventholddelay); //delay a little to prevent continuous cycling through "timespressed" during a single press
}
else{ //if the number that was pressed was different than before,
disablespacedelay=true; //disable the delay in the space function to allow the press to be detected a second time, at the beginning of void loop
break; //break out of the while loop
}
}
elapsed=millis()-basetime; //refresh the elapsed time for the while loop
}
elapsed=0; //reset the elapsed time for the while loop
textstorage(1); //store character
dospace(); //do a space
}
}
if (positionintypedtext==139){ //if the end of the stored text has been reached,
promptkeypress=false; //reset keypress detection
cursorx=0; //set cursor to the beginning of first row
cursory=0;
lcd.setCursor(cursorx,cursory);
lcd.print("Msg end. <>=back"); //print this out to the lcd
cursorx=0; //set cursor to the beginning of second row
cursory=1;
lcd.setCursor(cursorx,cursory);
lcd.print("enter=serial out"); //print this out to the lcd
rowshigh(); //sets all rows high
numpressed=16; //reset "numpressed" (16 doesn't refer to any button on the pad)
while(!promptkeypress){ //while no relevant keypresses have occurred,
if (findpress()){ //look for presses, if one has occurred, identify it and continue
timespressed=0; //reset "timespressed"
if (numpressed==14){ //if the arrows on the pad were pressed,
promptkeypress=true; //take note so that the while loop can be broken
textstorage(3); //perform a backspace in storage
for (int i=0;i<16;i++){ //print out to the first line on the lcd from the stored text
cursorx=i;
cursory=0;
lcd.setCursor(cursorx,cursory);
lcd.print(typedtext[108+i]);
}
for (int j=0;j<16;j++){ //print out to the second line on the lcd from the stored text
cursorx=j;
cursory=1;
lcd.setCursor(cursorx,cursory);
lcd.print(typedtext[123+j]);
}
cursorx=15; //set cursor to the beginning of second row
cursory=1;
lcd.setCursor(cursorx,cursory);
rowshigh(); //sets all rows high
}
if (numpressed==15){ //if enter on the pad was pressed,
promptkeypress=true; //take note so that the while loop can be broken
Serial.print("Final message: "); //print this to the serial console
Serial.println(typedtext); //print out all the text typed so far to the serial console
Serial.println(); //print a blank line
for (int i=0;i<140;i++){ //write all positions in the stored text to be blank
typedtext[i]=' ';
}
positionintypedtext=0; //reset the position in the stored text to the beginning
doclear();
rowshigh(); //sets all rows high
}
}
}
delay(preventholddelay); //delay a little to prevent continuous cycling
}
}