Calculator


Calculator example - allows enter 2 float numbers from keypad, and shows result on LCD. 
  # - enter
  * - decimal point
  A - add
  B - subtract
  C - mutiply
  D - devide

Toolkit:SDCC 8051 Development System

Location:/bipom/devtools/SDCC/examples/lcd/calculator

Code Example


#define MAX_ROWS				4
#define MAX_COLS				4

#define STATE_IDLE				0
#define STATE_ENTER_NUM1		1
#define STATE_ENTER_NUM2		2
#define STATE_ENTER_OPERATION	3
#define STATE_SHOW_RESULT		4

#define MAX_NUM_LEN				10

                
// ******************************************************************

char ScanKeypad()
{
	char row;
	char col;

	unsigned char RowTable[] = { 0xFE, 0xFD, 0xFB, 0xF7 };
	
	char KeyTable[] = { 	'1', '2', '3', 'A',
							'4', '5', '6', 'B',	 
							'7', '8', '9', 'C',
							'*', '0', '#', 'D'
						 };	
						 
	col = 0;
	for( row=0; row<MAX_ROWS; row++ )
	{
		P2 = RowTable[row];
		
		if( !(P2 & 0x80) ) col = 4;
		if( !(P2 & 0x40) ) col = 3;
		if( !(P2 & 0x20) ) col = 2;
		if( !(P2 & 0x10) ) col = 1;
			
		if( col != 0 ) 						
		{
			delay(500);
			return KeyTable[col-1 + row*MAX_COLS];
		}					
	}
	
	return 0;
}

// ******************************************************************

void main()
{
	float num1, num2, result;
	char  num1txt[MAX_NUM_LEN];
	char  num2txt[MAX_NUM_LEN];
	char  p = 0;
	char  IsPointAdded = 0;
	
	int State = STATE_IDLE;
	
   	// Initialize the serial port 

   	serinit(CBR_19200);
    
	puts( "\rCALCULATOR SAMPLE" );
	
	// Initialize the LCD 

	LCD_Init();

	// Write a simple message to the LCD 

	LCD_Clear();
	LCD_SetTopLine();
	LCD_Write("CALCULATOR SAMPLE");
	
	delay(2000);
	
	num1 = num2 = result = 0;
	
	while(1)
	{
		char ch = ScanKeypad();
		if(ch == 0 && State != STATE_IDLE)
			continue;
			
		switch(State)
		{
		default:
		case STATE_IDLE:
			LCD_Clear();
			LCD_SetTopLine();
			LCD_Write("ENTER NUM1: ");
			
			memset(num1txt, 0, MAX_NUM_LEN);
			memset(num2txt, 0, MAX_NUM_LEN);
			IsPointAdded = 0;
			p = 0;
			
			State = STATE_ENTER_NUM1;
			break;

		case STATE_ENTER_NUM1:
			if(ch >= '0' && ch <= '9')
			{
				num1txt[p++] = ch;
				LCD_WriteData(ch);
			}

			if(ch == '*' && !IsPointAdded)
			{
				num1txt[p++] = '.';
				IsPointAdded = 1;
				LCD_WriteData('.');
			}
			
			if(ch == '#' || p >= (MAX_NUM_LEN-1))
			{
				State = STATE_ENTER_NUM2;
				p = 0;
			}

			if(State == STATE_ENTER_NUM2)			
			{
				LCD_SetBottomLine();
				LCD_Write("ENTER NUM2: ");
			}
			
			break;

		case STATE_ENTER_NUM2:
			if(ch >= '0' && ch <= '9')
			{
				num2txt[p++] = ch;
				LCD_WriteData(ch);
			}
			
			if(ch == '*' && !IsPointAdded)
			{
				num2txt[p++] = '.';
				IsPointAdded = 1;
				LCD_WriteData('.');
			}
			
			if(ch == '#' || p >= (MAX_NUM_LEN-1))
				State = STATE_ENTER_OPERATION;

			if(State == STATE_ENTER_OPERATION)			
			{
				LCD_Clear();
				LCD_SetTopLine();
				LCD_Write("ENTER OPERATION: ");
			}

			break;

		case STATE_ENTER_OPERATION:
			if(ch == 'A' || ch == 'B' || ch == 'C' || ch == 'D')
			{
				num1 = atof(num1txt);
				num2 = atof(num2txt);

				printf("\rNUM1: %f", num1);
				printf("\rNUM2: %f", num2);
				printf("\rOPERATION: %c", ch);
				
				if(ch == 'A')
				{
					LCD_WriteData('+');
					result = num1 + num2;
					printf("\rRESULT (+): %f", result);
				}
				if(ch == 'B')
				{
					LCD_WriteData('-');
					result = num1 - num2;
					printf("\rRESULT (-): %f", result);
				}
				if(ch == 'C')
				{
					LCD_WriteData('*');
					result = num1 * num2;
					printf("\rRESULT (*): %f", result);
				}
				if(ch == 'D')
				{
					LCD_WriteData('');
					result = num1  num2;
					printf("\rRESULT (/): %f", result);
				}
				
				State = STATE_SHOW_RESULT;
			}
			
			if(State == STATE_SHOW_RESULT)			
			{
				LCD_SetBottomLine();
				LCD_Printf("RESULT: %f", result);
			}
			
			break;

		case STATE_SHOW_RESULT:
			if(ch == '#')
				State = STATE_IDLE;

			break;
		}
	}
}