initial calculator code
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ STCCODESIZE ?= 13000 | ||||
| SDCCOPTS ?= --code-size $(STCCODESIZE) --xram-size 0 --stack-auto | ||||
| FLASHFILE ?= main.hex | ||||
|  | ||||
| SRC = src/lcd.c src/key.c src/utils.c src/decn/decn.c | ||||
| SRC = src/lcd.c src/key.c src/utils.c src/decn/decn.c src/calc.c | ||||
|  | ||||
| OBJ=$(patsubst src%.c,build%.rel, $(SRC)) | ||||
|  | ||||
|  | ||||
							
								
								
									
										98
									
								
								src/calc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/calc.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| /* | ||||
|  * calc.c | ||||
|  * | ||||
|  *  Created on: Mar 28, 2019 | ||||
|  */ | ||||
|  | ||||
| #include "decn/decn.h" | ||||
|  | ||||
| #define STACK_SIZE 4 //must be a power of 2 | ||||
|  | ||||
| #define STACK_X 0 | ||||
| #define STACK_Y 1 | ||||
| #define STACK_Z 2 | ||||
| #define STACK_T 3 | ||||
|  | ||||
| //stack "grows" towards 0 | ||||
| __xdata dec80 Stack[STACK_SIZE]; //0->x, 1->y, 2->z, 3->t initially | ||||
| uint8_t StackPtr = 0; | ||||
|  | ||||
| #define stack(x) Stack[(StackPtr + (x)) & (STACK_SIZE-1)] | ||||
|  | ||||
| static void pop(){ | ||||
| 	copy_decn(&stack(STACK_X), &stack(STACK_T)); //duplicate t into x (which becomes new t) | ||||
| 	StackPtr++; //adjust pointer | ||||
| } | ||||
|  | ||||
| void push_decn(const char* signif_str, int16_t exponent, uint8_t no_lift){ | ||||
| 	if (!no_lift){ | ||||
| 		StackPtr--; | ||||
| 	} | ||||
| 	build_dec80(&stack(STACK_X), signif_str, exponent); | ||||
| } | ||||
|  | ||||
| void clear_x(void){ | ||||
| 	set_dec80_zero(&stack(STACK_X)); | ||||
| } | ||||
|  | ||||
| void set_x(const char* signif_str, int16_t exponent){ | ||||
| 	build_dec80(&stack(STACK_X), signif_str, exponent); | ||||
| } | ||||
|  | ||||
| __xdata dec80* get_x(void){ | ||||
| 	return &stack(STACK_X); | ||||
| } | ||||
| __xdata dec80* get_y(void){ | ||||
| 	return &stack(STACK_Y); | ||||
| } | ||||
|  | ||||
| static void do_binary_op(void (*f_ptr)(dec80*, const dec80*)){ | ||||
| 	f_ptr(&stack(STACK_Y), &stack(STACK_X)); | ||||
| 	pop(); | ||||
| } | ||||
|  | ||||
| void process_cmd(char cmd){ | ||||
| 	//process cmd | ||||
| 	switch(cmd){ | ||||
| 		////////// | ||||
| 		case '+':{ | ||||
| 			do_binary_op(add_decn); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case '*':{ | ||||
| 			do_binary_op(mult_decn); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case '-':{ | ||||
| 			negate_decn(&stack(STACK_X)); | ||||
| 			do_binary_op(add_decn); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case '/':{ | ||||
| 			do_binary_op(div_decn); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case '=':{ | ||||
| 			StackPtr--; | ||||
| 			copy_decn(&stack(STACK_X), &stack(STACK_Y)); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case 'c':{ | ||||
| 			set_dec80_zero(&stack(STACK_X)); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case '<':{ //use as +/- | ||||
| 			negate_decn(&stack(STACK_X)); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 		case 'r':{ //use as swap | ||||
| 			dec80 tmp; | ||||
| 			copy_decn(&tmp, &stack(STACK_X)); | ||||
| 			copy_decn(&stack(STACK_X), &stack(STACK_Y)); | ||||
| 			copy_decn(&stack(STACK_Y), &tmp); | ||||
| 		} break; | ||||
| 		////////// | ||||
| 	} //switch(cmd) | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/calc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/calc.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| /* | ||||
|  * calc.h | ||||
|  * | ||||
|  *  Created on: Mar 28, 2019 | ||||
|  */ | ||||
|  | ||||
| #ifndef SRC_CALC_H_ | ||||
| #define SRC_CALC_H_ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include "decn/decn.h" | ||||
|  | ||||
| void process_cmd(char cmd); | ||||
|  | ||||
| void push_decn(const char* signif_str, int16_t exponent, uint8_t no_lift); | ||||
|  | ||||
| void clear_x(void); | ||||
| void set_x(const char* signif_str, int16_t exponent); | ||||
| __xdata dec80* get_x(void); | ||||
| __xdata dec80* get_y(void); | ||||
|  | ||||
| #endif /* SRC_CALC_H_ */ | ||||
| @ -220,9 +220,9 @@ void LCD_SingleLineGoTo(unsigned int spot_to) { | ||||
| 	LCD_GoTo(spot_to / MAX_CHARS_PER_LINE, spot_to % MAX_CHARS_PER_LINE); | ||||
| } | ||||
|  | ||||
| void LCD_OutString(const char *string) { | ||||
| void LCD_OutString(const char *string, uint8_t max_chars) { | ||||
| 	const char *s; | ||||
| 	for (s = string; *s; s++) { | ||||
| 	for (s = string; *s && max_chars > 0; s++, max_chars--) { | ||||
| 		TERMIO_PutChar(*s); | ||||
| 	} | ||||
| } | ||||
| @ -251,8 +251,8 @@ short TERMIO_PutChar(unsigned char letter) { | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| void LCD_ClearToEnd(void){ | ||||
| 	while (col != 0){ | ||||
| void LCD_ClearToEnd(uint8_t curr_row){ | ||||
| 	while (col != 0 && row == curr_row){ | ||||
| 		TERMIO_PutChar(' '); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -10,10 +10,10 @@ void LCD_Clear(void); | ||||
| void LCD_GoTo(unsigned int row, unsigned int col); | ||||
| void LCD_SingleLineGoTo(unsigned int row_to); | ||||
|  | ||||
| void LCD_OutString(const char* string); | ||||
| void LCD_OutString(const char* string, uint8_t max_chars); | ||||
| short TERMIO_PutChar(unsigned char letter); | ||||
| void LCD_OutNibble(uint8_t x); | ||||
| void LCD_ClearToEnd(void); | ||||
| void LCD_ClearToEnd(uint8_t curr_row); | ||||
|  | ||||
| unsigned char LCD_Timeout_Error(void); | ||||
|  | ||||
|  | ||||
							
								
								
									
										216
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										216
									
								
								src/main.c
									
									
									
									
									
								
							| @ -6,6 +6,8 @@ | ||||
| #include <stdint.h> | ||||
| #include "lcd.h" | ||||
| #include "key.h" | ||||
| #include "decn/decn.h" | ||||
| #include "calc.h" | ||||
| #include "utils.h" | ||||
|  | ||||
| #define FOSC 11583000 | ||||
| @ -81,13 +83,27 @@ void Timer0Init(void) | ||||
| } | ||||
|  | ||||
|  | ||||
| char Buf[17]; | ||||
|  | ||||
| char Buf[DECN_BUF_SIZE]; | ||||
| __xdata char EntryBuf[MAX_CHARS_PER_LINE + 1]; | ||||
| __xdata uint8_t ExpBuf[2] = {0, 0}; | ||||
|  | ||||
| //#define DEBUG_UPTIME | ||||
| /*********************************************/ | ||||
| int main() | ||||
| { | ||||
| 	uint32_t i; | ||||
| 	uint8_t j; | ||||
| 	enum { | ||||
| 		ENTERING_DONE, | ||||
| 		ENTERING_SIGNIF_NOLIFT, | ||||
| 		ENTERING_SIGNIF, | ||||
| 		ENTERING_FRAC, | ||||
| 		ENTERING_EXP, | ||||
| 		ENTERING_EXP_NEG | ||||
| 	}; | ||||
| 	uint8_t entry_i = 0; | ||||
| 	uint8_t entering_exp = ENTERING_DONE; | ||||
| 	uint8_t no_lift = 0; | ||||
| 	uint8_t exp_i = 0; | ||||
| 	const uint8_t* keys; | ||||
| 	uint8_t key_i; | ||||
| 	Timer0Init(); // display refresh & switch read | ||||
| @ -106,6 +122,14 @@ int main() | ||||
| 	while (1) | ||||
| 	{ | ||||
| 		LCD_GoTo(0,0); | ||||
| 		//display y register on first line | ||||
| 		if (entering_exp == ENTERING_DONE){ | ||||
| 			dec80_to_str(Buf, get_y()); | ||||
| 		} else { | ||||
| 			//display x on 1st line, entered number on 2nd line | ||||
| 			dec80_to_str(Buf, get_x()); | ||||
| 		} | ||||
| 		LCD_OutString(Buf, MAX_CHARS_PER_LINE); | ||||
| 		//keyboard debug | ||||
| 		keys = DebugGetKeys(); | ||||
| 		for (key_i = 0; key_i < 5; key_i++){ | ||||
| @ -136,17 +160,199 @@ int main() | ||||
| 				new_key_empty = 1; | ||||
| 			} | ||||
|  | ||||
| #ifdef DEBUG_KEYS | ||||
| 			LCD_GoTo(1,j); | ||||
| #endif | ||||
| 			//find first key pressed in array (if any) | ||||
| 			for (i_key = 0; i_key < 20; i_key++){ | ||||
| 				if (new_keys & ((uint32_t) 1 << i_key)){ | ||||
| #ifdef DEBUG_KEYS | ||||
| 					TERMIO_PutChar(KEY_MAP[i_key]); | ||||
| 					j++; | ||||
| 					j &= 0x0f; | ||||
| #endif | ||||
| 					//process key | ||||
| 					switch(KEY_MAP[i_key]){ | ||||
| 						////////// | ||||
| 						case '0': { | ||||
| 							if (entering_exp >= ENTERING_EXP){ | ||||
| 								ExpBuf[exp_i] = 0; | ||||
| 								exp_i = (exp_i + 1) & 1; | ||||
| 							} else if (entering_exp == ENTERING_DONE){ | ||||
| 								entering_exp = ENTERING_SIGNIF; | ||||
| 								EntryBuf[entry_i] = KEY_MAP[i_key]; | ||||
| 								//do not increment entry_i from 0, until first non-0 entry | ||||
| 							} else if (entry_i != 0 && entry_i < MAX_CHARS_PER_LINE - 1 + 1){ | ||||
| 								EntryBuf[entry_i] = KEY_MAP[i_key]; | ||||
| 								entry_i++; | ||||
| 							} | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						case '1': //fallthrough | ||||
| 						case '2': //fallthrough | ||||
| 						case '3': //fallthrough | ||||
| 						case '4': //fallthrough | ||||
| 						case '5': //fallthrough | ||||
| 						case '6': //fallthrough | ||||
| 						case '7': //fallthrough | ||||
| 						case '8': //fallthrough | ||||
| 						case '9': { | ||||
| 							if (entering_exp >= ENTERING_EXP){ | ||||
| 								ExpBuf[exp_i] = KEY_MAP[i_key] - '0'; | ||||
| 								exp_i = (exp_i + 1) & 1; | ||||
| 							} else if (entering_exp == ENTERING_DONE){ | ||||
| 								entering_exp = ENTERING_SIGNIF; | ||||
| 								EntryBuf[entry_i] = KEY_MAP[i_key]; | ||||
| 								entry_i++; | ||||
| 							} else if (entry_i < MAX_CHARS_PER_LINE - 1 + 1){ | ||||
| 								EntryBuf[entry_i] = KEY_MAP[i_key]; | ||||
| 								entry_i++; | ||||
| 							} | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						case '.': { | ||||
| 							if (entering_exp == ENTERING_DONE){ | ||||
| 								EntryBuf[entry_i++] = '0'; | ||||
| 								EntryBuf[entry_i++] = '.'; | ||||
| 								entering_exp = ENTERING_FRAC; | ||||
| 							} else if (entering_exp == ENTERING_SIGNIF){ | ||||
| 								if (entry_i == 0){ | ||||
| 									EntryBuf[entry_i++] = '0'; | ||||
| 								} | ||||
| 								EntryBuf[entry_i++] = '.'; | ||||
| 								entering_exp = ENTERING_FRAC; | ||||
| 							} else if (entering_exp <= ENTERING_EXP) { | ||||
| 								entering_exp++; | ||||
| 							} else { //entering_exp == ENTERING_EXP_NEG | ||||
| 								entering_exp = ENTERING_EXP; | ||||
| 							} | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						case '=': { | ||||
| 							//track stack lift | ||||
| 							if (entering_exp != ENTERING_DONE){ | ||||
| 								//finish entry | ||||
| 								int8_t exponent; //exponent is only 2 digits | ||||
| 								exponent = 10*ExpBuf[1] + ExpBuf[0]; | ||||
| 								if (entering_exp == ENTERING_EXP_NEG){ | ||||
| 									exponent = -exponent; | ||||
| 								} | ||||
| 								EntryBuf[entry_i] = '\0'; | ||||
| 								push_decn(EntryBuf, exponent, no_lift); | ||||
| 								process_cmd(KEY_MAP[i_key]); | ||||
| 								//reset state as initial ENTERING_DONE state | ||||
| 								entering_exp = ENTERING_DONE; | ||||
| 								entry_i = 0; | ||||
| 								exp_i = 0; | ||||
| 								ExpBuf[0] = 0; | ||||
| 								ExpBuf[1] = 0; | ||||
| 							} else { | ||||
| 								//dup | ||||
| 								process_cmd(KEY_MAP[i_key]); | ||||
| 							} | ||||
| 							no_lift = 1; | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						case 'c': { | ||||
| 							if (entering_exp == ENTERING_DONE){ | ||||
| 								//clear | ||||
| 								clear_x(); | ||||
| 								no_lift = 1; | ||||
| 								entering_exp = ENTERING_SIGNIF; | ||||
| 								EntryBuf[entry_i] = '0'; | ||||
| 								//do not increment entry_i from 0, until first non-0 entry | ||||
| 							} else if (entering_exp >= ENTERING_EXP){ | ||||
| 								//go back to digit entry | ||||
| 								entering_exp--; | ||||
| 								exp_i = 0; | ||||
| 								ExpBuf[0] = 0; | ||||
| 								ExpBuf[1] = 0; | ||||
| 							} else if (entry_i > 0){ | ||||
| 								//backspace | ||||
| 								if (EntryBuf[entry_i] == '.'){ | ||||
| 									entering_exp--; | ||||
| 								} | ||||
| 								entry_i--; | ||||
| 							} | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						case '+': //fallthrough | ||||
| 						case '*': //fallthrough | ||||
| 						case '-': //fallthrough | ||||
| 						case '/': //fallthrough | ||||
| 						case '<': //fallthrough //use as +/- | ||||
| 						case 'r': { //use as swap | ||||
| 							if (entering_exp != ENTERING_DONE){ | ||||
| 								//finish entry | ||||
| 								int8_t exponent; //exponent is only 2 digits | ||||
| 								exponent = 10*ExpBuf[1] + ExpBuf[0]; | ||||
| 								if (entering_exp == ENTERING_EXP_NEG){ | ||||
| 									exponent = -exponent; | ||||
| 								} | ||||
| 								EntryBuf[entry_i] = '\0'; | ||||
| 								push_decn(EntryBuf, exponent, no_lift); | ||||
| 								process_cmd(KEY_MAP[i_key]); | ||||
| 								//reset state as initial ENTERING_DONE state | ||||
| 								entering_exp = ENTERING_DONE; | ||||
| 								entry_i = 0; | ||||
| 								exp_i = 0; | ||||
| 								ExpBuf[0] = 0; | ||||
| 								ExpBuf[1] = 0; | ||||
| 							} else { | ||||
| 								//process key | ||||
| 								process_cmd(KEY_MAP[i_key]); | ||||
| 							} | ||||
| 							no_lift = 0; | ||||
| 						} break; | ||||
| 						////////// | ||||
| 						default: process_cmd(KEY_MAP[i_key]); | ||||
| 						////////// | ||||
| 					} //switch(KEY_MAP[i_key]) | ||||
|  | ||||
| 					break; | ||||
| 				} | ||||
| 				} //if found new key pressed | ||||
| 			} //for new key array | ||||
| 		} //if (!NewKeyEmpty) | ||||
|  | ||||
| 		//print X | ||||
| 		LCD_ClearToEnd(0); //go to 2nd row | ||||
| 		if (entering_exp == ENTERING_DONE){ | ||||
| 			dec80_to_str(Buf, get_x()); | ||||
| 			LCD_OutString(Buf, MAX_CHARS_PER_LINE); | ||||
| 		} else if (entry_i == 0){ | ||||
| 			TERMIO_PutChar('0'); | ||||
| 		} else if (entering_exp < ENTERING_EXP){ | ||||
| 			uint8_t idx; | ||||
| 			for (idx = 0; idx < entry_i && idx < MAX_CHARS_PER_LINE; idx++){ | ||||
| 				TERMIO_PutChar(EntryBuf[idx]); | ||||
| 			} | ||||
| 		} else { | ||||
| 			uint8_t idx; | ||||
| 			//print significand | ||||
| 			for (idx = 0; idx < entry_i && idx < MAX_CHARS_PER_LINE - 3; idx++){ | ||||
| 				TERMIO_PutChar(EntryBuf[idx]); | ||||
| 			} | ||||
| 			//go to exponent | ||||
| 			if (idx < MAX_CHARS_PER_LINE - 3){ | ||||
| 				//clear until exponent | ||||
| 				for ( ; idx < MAX_CHARS_PER_LINE - 3; idx++){ | ||||
| 					TERMIO_PutChar(' '); | ||||
| 				} | ||||
| 			} else { | ||||
| 				LCD_GoTo(1, MAX_CHARS_PER_LINE - 3); | ||||
| 			} | ||||
| 			//print exponent sign | ||||
| 			if (entering_exp == ENTERING_EXP_NEG){ | ||||
| 				TERMIO_PutChar('-'); | ||||
| 			} else { | ||||
| 				TERMIO_PutChar(' '); | ||||
| 			} | ||||
| 			//print exp | ||||
| 			TERMIO_PutChar(ExpBuf[1] + '0'); | ||||
| 			TERMIO_PutChar(ExpBuf[0] + '0'); | ||||
| 		} | ||||
| 	} | ||||
| 		LCD_ClearToEnd(1); | ||||
| 	} //while (1) | ||||
| } | ||||
| /* ------------------------------------------------------------------------- */ | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user