void init_port(); // port initialization function
void init_lcd(); // lcd initialization function
void delay1(volatile int time); // delay function
void lcd_cmd(volatile char cmd); // lcd command function
void lcd_print(volatile long printNumber); // lcd number print function
void lcd_print_char(volatile char ptr); // lcd character print function
volatile char checkKey(); // keyboard scanning function
void calculateNumber(volatile char key); // function for calculate the pressed number
void calculateResult(); // function for the result calculation
volatile char *dirf, *outf, *dirk, *outk, *dira, *outa, *dirc, *inc;
volatile long number, num1, num2, result, temp;
volatile char action, resultFlag; // 'action' is the operation type variable
int main() { //////////////////// MAIN FUNCION ///////////////////////////
Serial.begin(9600);
Serial.println(" key A = '+' key B = '-' key C = '*'");
Serial.println(" key D = '/' key # = '=' key * = 'Clear'");
Serial.println("It performs only two number operation at a time. To do multiple operations, perform operation between result and another number:" );
Serial.println(" Ex- 1st stage: 3+5=8" );
Serial.println(" 2nd stage: *5=40" );
Serial.println(" 3rd stage: -25=15 and so on....." );
volatile char key;
init_port();
init_lcd();
while(1){
key=checkKey();
if(key){
calculateNumber(key);
lcd_cmd(0x01); // to clear the screen
if(num1>0) lcd_print(num1);
else if(num1<0){lcd_print_char('-'); temp=num1-1; temp=~temp; lcd_print(temp); temp=0;}
if(action) lcd_print_char(action);
if(num2) lcd_print(num2);
lcd_print(number);
if(resultFlag){
lcd_cmd(0xc0);
lcd_print_char('=');
if(result>0) lcd_print(result);
else if(result<0){lcd_print_char('-'); temp=result-1; temp=~temp; lcd_print(temp); temp=0;}
else {lcd_print_char('0'); result=num1=num2=0;}
resultFlag=0;
}
}
}
}
void calculateNumber(volatile char key){ //////// NUMBER CALCULATION FUNCTION
if((key=='+')||(key=='-')||(key=='*')||(key=='/')){
if(result){num1=result; number=result=num2=0; action=key;}
else {num1=number; number=0; action=key;}
}
else if(key=='='){num2=number; number=0; resultFlag=1; calculateResult();}
else if(key=='c'){number=num1=num2=result=action=0;}
else{
if(number==0) number=key-48;
else number=(number*10) + (key-48);
}
delay1(1500); // key debouncing delay
}
void calculateResult(){ //////////////////// RESULT CALCULATION FUNCTION
if(action=='+') result=num1+num2;
else if(action=='-') result=num1-num2;
else if(action=='*') result=num1*num2;
else if(action=='/') result=num1/num2;
}
void lcd_print(volatile long printNumber){////////////// NUMBER PRINT FUNCION
volatile char i=0, j, num[20], revNum[20], length=0;
while(printNumber){
revNum[i++]=printNumber%10; // the reverse number
printNumber/=10;
length++;
}
length--; // number length
for(i=0, j=length; i<=length; i++, j--){ // the actual number
num[i]=revNum[j] + 48;
}
for(i=0; i<=length; i++){ // print the number
*outf=num[i];
*outk=2; delay1(1);
*outk=3; delay1(1);
*outk=2; delay1(1);
}
}
void lcd_print_char(volatile char ptr){///////////// CHARACTER PRINT FUNCTION
*outf=ptr;
*outk=2; delay1(1);
*outk=3; delay1(1);
*outk=2; delay1(1);
}
volatile char checkKey(){///////////////////////// KEYBOARD SCANNING FUNCTION
volatile char row, col, key;
for(row=0; row<4; row++){
*outa= 1 << row;
if(*inc){ col=*inc; break;}
}
if(row==0){
if(col==1) key='1';
else if(col==2) key='2';
else if(col==4) key='3';
else if(col==8) key='+';
}
else if(row==1){
if(col==1) key='4';
else if(col==2) key='5';
else if(col==4) key='6';
else if(col==8) key='-';
}
else if(row==2){
if(col==1) key='7';
else if(col==2) key='8';
else if(col==4) key='9';
else if(col==8) key='*';
}
else if(row==3){
if(col==1) key='c';
else if(col==2) key='0';
else if(col==4) key='=';
else if(col==8) key='/';
}
else key=0;
return key;
}
////////////////////////////////DISPLAY AND PORT FUNCTIONS/////////////////////////////
void init_lcd(){
lcd_cmd(0x38);
lcd_cmd(0x0c);
lcd_cmd(0x01);
}
void lcd_cmd(volatile char cmd){
*outf=cmd;
*outk=0; delay1(1);
*outk=1; delay1(1);
*outk=0; delay1(1);
}
void init_port(){
dira=0x21; *dira=0xff; outa=0x22;
dirc=0x27; *dirc=0; inc=0x26;
dirf=0x30; *dirf=0xff; outf=0x31;
dirk=0x107; *dirk=0x03; outk=0x108;
}
void delay1(volatile int time){
volatile long i;
while(time--)
for(i=0; i<100; i++);
}