// Configuation
// Port B 0 - 3 - LED Port 4 - 7
// Port D 4 - 7 - LED Port 0 - 3
// PORT C 0 - 3 - Keypad Row 1 - 4
// Port C 4 - 5 - Keypad Col 2 - 3
// Port C 2 -3 - Keypad Col 0 - 1
// Keypad configuation
// 1 - 1; 2 - 2; 3 - 3
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
struct keys{
int rowCol;
char keyPressed;
};
void fnAdd(char a[],char b[],int firstLineLength);
void fnSub(char a[],char b[],int firstLineLength);
void fnMul(char a[],char b[],int firstLineLength);
void fnDiv(char dividend[],char divsor[],int firstLineLength);
long fnToNum(char arr[]);
bool fnValidateInput(char x[],char y[]);
void fnToCalc(char x[],char opr);
void print_string(char x[]);
void print_answer(char x[],int firstLineLength);
void movecursor(void);
void fnCalc(int,int);
void fnForCalculation(char*);
void topassCommand();
void topassData();
void passCommand(char);
void writeData(char);
void lcdReady();
void init_port(void);
//void outport(char);
void delay1(int);
char inport(void);
int scan_keypad(void);
void outportc(char);
void setup() {
char input[10] = {'0'};
int i =0;
int x;
char keys[]= { 0x00,0x00,0x00,0x00,0x00,0x00,'1', '2', '3','+','4','5', '6','-', '7', '8', '9','*', 'C', '0', '=', '/'};
//outport(0);
init_port();
lcdReady();
x = scan_keypad();
int nth_term = 0;
int y;
while(1)
{
while(x == 0)
{
x = scan_keypad();
delay(100);
y = x;
}
//Serial.println(y);
if(keys[x]== '='){
// Serial.println(x);
fnForCalculation(input);
nth_term++;
}
delay1(1);
Serial.println(keys[x]);
writeData(keys[x]);
input[i] = keys[x];
i++;
x = 0;
}
}
;
void movecursor(void)
{
topassCommand();
passCommand(0x15);
}
// void fnCalc(int x,int n){
// char keys[]= {'1', '2', '3','+','4','5', '6',"-", '7', '8', '9','*', 'C', '0', '=', '/'};
// bool toCalculate = false;
// char arr[10] = {'0'};
// char charArr[10] = {'0'};
// int index = n;
// int i;
// for(i=0;i<16;i++){
// if(i== (x)){
// arr[index] = keys[x];
// writeData(x);
// Serial.println(x);
// if(arr[index] == '='){
// toCalculate = true;
// }
// break;
// }
// }
// if(toCalculate){
// //Serial.println(keys[n]);
// for(i=0;i<(n-1);i++){
// charArr[i] = arr[i];
// }
// for(i=0;i<30;i++){
// movecursor();
// }
// // if(strstr(charArr,"+")){
// // fnToCalc(charArr,'+');
// // }
// // if(strstr(charArr,"-")){
// // fnToCalc(charArr,'-');
// // }
// // if(strstr(charArr,"*")){
// // fnToCalc(charArr,'*');
// // }
// // if(strstr(charArr,"/")){
// // fnToCalc(charArr,'/');
// // }
// }
// }
int scan_keypad()
{
int i,row,col,column,rdata;
char j,k;
for(row =0; row<4; row++)
{
outportc(~(1<<row));
for(col=0; col<4; col++)
{
column = inport();
if(column != 0x0)
{
delay1(1);
//Serial.println(column);
for(col=0; col<4; col++)
{
if(column == (1 << col))
{
rdata = ((row+1) * 4) + (col+1) + 1;
char data = rdata;
//Serial.println(data);
delay1(1);
return(rdata);
}
}
}
}
}
return(0);
}
char inport(void)
{
char indata,datad,datac;
char *portc_data = (char *)0x26;
char *portd_data = (char *)0x29;
datad = *portd_data;
datac = *portc_data;
indata = (((datac & 0x30)>>2) & 0x0F) | ((datad & 0x0C) >> 2);
indata = ~indata & 0x0F;
return(indata);
}
void init_port()
{
char *portb_dir = (char *)0x24;
char *portc_dir = (char *)0x27;
char *portd_dir = (char *)0x2A;
*portb_dir = 0xFF;
*portd_dir = 0xF0;
*portc_dir = 0x0F;
}
void outportc( char out_data)
{
char *portc_data = (char *)0x28;
*portc_data = out_data ;
}
void passCommand(char outdata){
char *portb_data = (char *)0x25;
char *portd_data = (char *)0x2B;
char data_b = *portb_data;
// Serial.println(outdata);
*portb_data = (outdata>>4) | data_b;
*portd_data = outdata<<4;
}
void writeData(char outdata){
char *portb_data = (char *)0x25;
char *portd_data = (char *)0x2B;
char data_b = *portb_data;
// Serial.println(outdata);
*portb_data = (outdata>>4) | data_b;
*portd_data = outdata<<4;
topassData();
}
void lcdReady(){
char *portb_data = (char *)0x25;
char *portd_data = (char *)0x2B;
topassCommand();
//8 bit 2 line
passCommand(0x38);
//clear display
topassCommand();
passCommand(0x01);
topassCommand();
//display on cursor blinking
passCommand(0x0F);
topassCommand();
//auto increment
passCommand(0x06);
topassCommand();
//auto increment
}
void topassData(void){
char *portb_data = (char *)0x25;
char *portd_data = (char *)0x2B;
char data_b = *portb_data;
*portb_data = 0b00010000 | data_b ;
delay(1);
*portb_data = 0b00110000 | data_b ;
delay(1);
*portb_data = 0b00010000 | data_b ;
delay1(1);
}
void topassCommand(void){
char *portb_data = (char *)0x25;
*portb_data = 0b00100000;
delay(1);
*portb_data = 0b00000000;
delay(1);
}
void delay1(int count)
{
volatile long i;
while(count)
{
for(i=0; i<1000; i++);
count--;
}
}
void loop() {
}
void print_answer(char x[],int length){
int len = 40-length;
int i;
// for(i=0;i<len;i++){
// movecursor();
// }
while(*x != 0)
{
writeData(*x);
x++;
}
}
void print_string(char *x){
while(*x != 0)
{
writeData(*x);
x++;
}
}
//Identifying the operation to be performed using a substring of input
bool fnValidateInput(char x[],char y[]){
int lenX = strlen(x);
int lenY = strlen(y);
bool isValid = true;
int i;
for(i=0;i<lenX;i++){
if(x[i]>='0' && x[i]<='9'){
continue;
}
else{
isValid = false;
break;
}
}
bool secArrValidity;
for(i=0;i<lenY;i++){
if(y[i]>='0' && y[i]<='9'){
continue;
}
else{
secArrValidity = false;
isValid = (secArrValidity);
break;
}
}
return isValid;
}
/*
function name: fnToCalc
input params: char arrays
output type: void
Description: Input string is splitted to arrays of operands and operators.
Passing the operands for validation.
In case of valid input, using operator symbol the inputs are passed to
the appropriate function to perform desired arithmetic operation.
*/
// void fnCalc(int x,int n){
// struct keys key[16];
// char arr[10] = {'0'};
// bool toCalculate = false;
// key[0].rowCol=6;
// key[0].keyPressed = '1';
// key[1].rowCol = 7;
// key[1].keyPressed = '2';
// key[2].rowCol = 8;
// key[2].keyPressed = '3';
// key[3].rowCol = 9;
// key[3].keyPressed = '+';
// key[4].rowCol = 10;
// key[4].keyPressed = '4';
// key[5].rowCol = 11;
// key[5].keyPressed = '5';
// key[6].rowCol = 12 ;
// key[6].keyPressed = '6';
// key[7].rowCol = 13;
// key[7].keyPressed = '-';
// key[8].rowCol = 14;
// key[8].keyPressed = '7';
// key[9].rowCol = 15;
// key[9].keyPressed = '8';
// key[10].rowCol = 16;
// key[10].keyPressed = '9';
// key[11].rowCol = 17;
// key[11].keyPressed = '*';
// key[12].rowCol = 18;
// key[12].keyPressed = '<';
// key[13].rowCol = 19;
// key[13].keyPressed = '0';
// key[14].rowCol = 20;
// key[14].keyPressed = '=';
// key[15].rowCol = 21;
// key[15].keyPressed = '/';
// int i;
// char pressedKeys[10];
// int pKey = 0;
// int index = n;
// for(i=0;i<16;i++){
// if(key[i].rowCol == (x)){
// //pressedKeys[pKey] = key[i].keyPressed;
// memset(pressedKeys[pKey],key[i].keyPressed,sizeof(char)*1);
// pKey++;
// //Serial.print(key[i].keyPressed);
// if(key[i].keyPressed == '+'){
// writeData('+');
// }
// else if(key[i].keyPressed == '-'){
// writeData('-');
// }
// else if(key[i].keyPressed == '*'){
// writeData('*');
// }
// else if(key[i].keyPressed == '/'){
// writeData('/');
// }
// else if(key[i].keyPressed == '=' ){
// for(i=0;i<10;i++){
// Serial.println(pressedKeys[i]);
// }
// fnForCalculation(pressedKeys);
// }else{
// writeData(key[i].keyPressed);
// }
// }
// }
// }
void fnForCalculation(char a[]){
// Serial.println(a[1]);
// char x[10] = {'0'};
// int len = strlen(a);
// int i;
// for(i=0;i<(len-1);i++){
// // x[i] == a[i];
// memset(x[i],a[i],sizeof(char)*1);
// //delay(100);
// }
//Identifying the operation to be performed using a substring of input
if(strstr(a,"+")){
fnToCalc(a,'+');
}
if(strstr(a,"-")){
fnToCalc(a,'-');
}
if(strstr(a,"*")){
fnToCalc(a,'*');
}
if(strstr(a,"/")){
fnToCalc(a,'/');
}
}
void fnToCalc(char x[],char opr){
int len,oprIndex;
len = (strlen(x));
char arr1[10],arr2[10];
int i;
for(i=0;i<(len-1);i++){
if(x[i] == opr){
oprIndex = i;
}
}
int arr2Index = 0;
for(i=0;i<len;i++){
if(i<oprIndex){
arr1[i] = x[i];
}
else if(i>oprIndex){
arr2[arr2Index] = x[i];
arr2Index++;
}
else{
continue;
}
}
int firstLineLength = strlen(arr1) + strlen(arr2)+1;
bool isValidInput = false;
if(fnValidateInput(arr1,arr2)){
isValidInput = true;
}
if((opr == '+') && isValidInput){
fnAdd(arr1,arr2,firstLineLength);
}
else if((opr == '-') && isValidInput){
fnSub(arr1,arr2,firstLineLength);
}
else if((opr == '*') && isValidInput){
fnMul(arr1,arr2,firstLineLength);
}
else if((opr == '/') && isValidInput){
fnDiv(arr1,arr2,firstLineLength);
}
else{
print_answer("Invalid input\n",firstLineLength);
}
}
/*
function name: fnAdd
input params: char arrays of operand 1 and 2
output type: void
Description: performs addition operation of each
character of the array after converting to numbers.
Carry is forwarded when looping from
one digit to next digit.
*/
void fnAdd(char a[],char b[],int firstLineLength){
int i,carry = 0;
int len1 = strlen(a);
int len2 = strlen(b);
//looplength -- determining the number of iterations
//using the length of the input arrays
int loopLength;
loopLength = len1>len2 ? len1:len2;
//The added results is stored in 'result' array
char result[20] = {'0'};
//Index of the result array incremented after every looping
int actualIndex = 0;
//Digit-by-digit operations using the indexes of input arrays
//To iterate through every element of input array, length
//of the arrays are used
int firstArrIndex = (len1-1);
int secondArrIndex = (len2-1);
while(loopLength>0){
int x,y;
//convert from character to integer
x = a[firstArrIndex] - '0';
y = b[secondArrIndex] - '0';
//Negative index value signifies there is no array
//value for that iteration in the array
//Values of x or y are declared as zero
if(firstArrIndex<0){
x = 0;
}
if(secondArrIndex<0){
y = 0;
}
//adding the two integers and carry from the previous operation
int sum = x+y+carry;
if(sum>9){
carry = sum/10;
sum = sum%10;
}
//added value is converted back to character
if(sum >0){
result[actualIndex] = (sum+'0');
}
else{
result[actualIndex] = (0+'0');
}
//Incrementing the index of the result array
actualIndex++;
//Decrementing the index values of the input arrays
firstArrIndex--;
secondArrIndex--;
//Decrementing the value of 'n'th time iterated
loopLength--;
}
//Identifying the first non-zero index to avoid preceding zeros
//of the result array
int firstNonZeroIndex;
for(i=(actualIndex-1);i>=0;i--){
if((result[i]-'0') != 0){
firstNonZeroIndex = i;
// printf("%d\n",i);
break;
}
}
// if(firstNonZeroIndex==(actualIndex-1)){
// firstNonZeroIndex = 0;
// }
// int len = 5 ;
// for(i=0;i<len;i++){
// movecursor();
// }
//Adding carry to the result array
//when the last operation is performed results in value
//greater than 10
if(carry >0 && (len1 == len2)){
char firstDigit = (carry+'0');
//printf("%c",firstDigit);
writeData(firstDigit);
}
if((firstNonZeroIndex>0) && firstNonZeroIndex<(actualIndex-1)){
for(i=(actualIndex-1);i>=firstNonZeroIndex;i--){
writeData(result[i]);
}
}
else if(firstNonZeroIndex==(actualIndex-1)){
for(i=(actualIndex-1);i>=0;i--){
writeData(result[i]);
}
}
else{
writeData(result[0]);
}
}
/**
function name: fnSub
input params: char arrays of operand 1 and 2
output type: void
Description: performs difference operation of each
character of the array after converting to numbers.
Borrow is forwaded when looping from
one digit to next digit.
**/
void fnSub(char a[],char b[],int firstLineLength){
int i;
//boolean value is set if borrow operation is performed
bool isBorrowed = false;
int len1 = strlen(a);
int len2 = strlen(b);
//looplength -- determining the number of iterations
//using the length of the input arrays
int loopLength;
loopLength = (len1>=len2 ? len1:len2);
int actualIndex = 0;
char result[20] = {'0'};
int firstArrIndex = (len1-1);
int secondArrIndex = (len2-1);
char mode;
for(i=(loopLength-1);i>=0;i--){
int x,y;
int difference;
x = a[firstArrIndex] - '0';
y = b[secondArrIndex] - '0';
if(firstArrIndex<0){
x = 0;
}
if(secondArrIndex<0){
y = 0;
}
//Determing the mode of operation
//Negative mode : first number < second number
//Positive mode : first number > second number
//Mode is determined using length of the input
//arrays and value of the last value of the digit of
//the array
int nth_positionA = a[0]-'0';
int nth_positionB = b[0] - '0';
if(len1>len2){
x = isBorrowed ? (x-1):x;
difference = x - y;
}
else if((len1 == len2) && (nth_positionA >= nth_positionB)){
x = isBorrowed ? (x-1):x;
difference = x - y;
}
else if((len1 == len2) && (nth_positionA < nth_positionB)){
y = isBorrowed ? (y-1):y;
difference = y - x;
mode = '-';
}
else{
y = isBorrowed ? (y-1):y;
difference = y - x;
mode = '-';
}
//In case of negative difference
//equivalent positive value is obtained by adding '10' to
//the value
//setting the boolean value for borrow operation as 'true'
if(difference<0){
difference += 10;
isBorrowed = true;
}
else{
isBorrowed = false;
}
result[actualIndex] = difference + '0';
actualIndex++;
firstArrIndex--;
secondArrIndex--;
}
int firstNonZeroIndex = -1;
for(i=(actualIndex-1);i>=0;i--){
if((result[i]-'0') != 0){
//printf("%c\n",result[i]);
firstNonZeroIndex = i;
break;
}
}
if(firstNonZeroIndex == (actualIndex-1)){
firstNonZeroIndex = 0;
}
// int len = 40-firstLineLength;
// for(i=0;i<len;i++){
// movecursor();
// }
if(mode=='-' && (firstNonZeroIndex>=0)){
char negative = '-';
for(i=(actualIndex-1);i>=(firstNonZeroIndex);i--){
writeData(result[i]);
}
}
else if(firstNonZeroIndex>=0){
for(i=(actualIndex-1);i>=firstNonZeroIndex;i--){
writeData(result[i]);
}
}
else{
char zero = '0';
writeData(zero);
}
}
/**
function_name : fnMul
input_params : char arrays
output_value : void
Description : Multiplying digit by digit through iterating the
input arrays. The result of each digit is maintained in a integer
array
**/
void fnMul(char a[],char b[],int firstLineLength){
int len1 = strlen(a),i;
int len2 = strlen(b);
int resultLen = len1+len2;
int result[20]={0},j;
//powerFactor -- Upon multiplication of each digit
//The place value during addition of multiplied values
//are adjusted using this integer value
int powerFactor = 0,k=resultLen-1;
int carry = 0;
int ivalue, jvalue;
//outer loop is iterated by more count than the innerloop
//for multiplication in case of unequal length of arrays/numbers
//The number of iterations are set using the length of the
//input arrays
//len1 - length of 1st array
//len2 - length of 2nd array
if(len1>len2){
ivalue = len1;
jvalue = len2;
}
else if(len1 == len2){
ivalue = len1;
jvalue = len2;
}
else{
ivalue = len2;
jvalue = len1;
}
int finalCarry = 0;
int placeCarry[10] = {0};
for(i=(ivalue-1);i>=0;i--){
for(j=(jvalue-1);j>=0;j--){
int x,y;
if(len1<len2){
x = b[i] - '0';
y = a[j] - '0';
}
else{
x = a[i]-'0';
y = b[j]-'0';
}
int mul = (x*y)+placeCarry[k];
placeCarry[k] = 0;
result[k] += (mul);
if(result[k]>9){
placeCarry[k-1] +=result[k]/10;
result[k] = result[k]%10;
}
k--;
if(k==0){
finalCarry +=placeCarry[0];
}
}
//powerfactor is incremented on looping through the successive
//digit of the multiplicand
powerFactor++;
//Index value of result array calculated by difference value of
//length of result array and powerfactor
k = resultLen - powerFactor - 1;
}
int firstNonZeroIndex = -1;
for(i=0;i<resultLen;i++){
if(result[i] != 0){
firstNonZeroIndex = i;
break;
}
}
// int len = 40-firstLineLength;
// for(i=0;i<len;i++){
// movecursor();
// }
if(finalCarry>0 ){
writeData(finalCarry);
}
if(firstNonZeroIndex>=0){
for(i=firstNonZeroIndex;i<resultLen;i++){
writeData(result[i]);
}
}
else{
char a = '0';
writeData(a);
}
}
/**
function_name: fnToNum
input_params : char array
output_type : long integer
description: Convert the string of numbers to
a long integer value
**/
long fnToNum(char arr[]){
long num = 0;
int i;
int len=0;
//Determing length of array of numbers
for(i=0;;i++){
if(!arr[i]){
break;
}
len++;
}
//On every iteration previous value is multiplied by 10
//and adding the new value to set the correct place values
//of final integer
for(i=0;i<len;i++){
int temp = (arr[i]-'0');
num = (num*10)+temp;
}
return num;
}
/**
function_name: fnDiv
input_params : char arrays
output_type : void
Description : performs division operation looping through
the each digit of the dividend and comparing it with divisor.
Based on this comparision, quotient is incremented
**/
void fnDiv(char dividend[],char divsor[],int firstLineLength){
long divisor = fnToNum(divsor);
static char quotient[10];
long temp=0;
int i=0,j=0;
while(dividend[i]){
temp = temp*10 + (dividend[i] -'0');
if(temp<divisor){
quotient[j++] = '0';
}
else{
quotient[j++] = (temp / divisor) + '0';
temp = temp % divisor;
}
i++;
}
quotient[j] = '\0';
long remainder = temp;
int firstNonZeroIndex;
for(i=0;i<=j;i++){
if(quotient[i] != '0'){
firstNonZeroIndex = i;
break;
}
}
// int len = 40-firstLineLength;
// for(i=0;i<len;i++){
// movecursor();
// }
for(i=firstNonZeroIndex;i<j;i++){
writeData(quotient[i]);
}
for(i=0;i<2;i++){
movecursor();
}
if(remainder>0){
char remainderArr[10] = {'0'};
long num = remainder;
int index = 0;
while(num>0){
int digit = num%10;
remainderArr[index] = digit+'0';
long temp = num/10;
num = temp;
}
for(i=10;i>=0;i--){
if(remainderArr[i]){
writeData(remainderArr[i]);
}
}
}
}