From ecb0492534658f885b26a361559321f3888f99d2 Mon Sep 17 00:00:00 2001 From: Jeff Wang Date: Sun, 31 Mar 2019 19:20:28 -0400 Subject: [PATCH] initial calculator code --- Makefile | 2 +- src/calc.c | 98 ++++++++++++++++++++++++ src/calc.h | 22 ++++++ src/lcd.c | 8 +- src/lcd.h | 4 +- src/main.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 src/calc.c create mode 100644 src/calc.h diff --git a/Makefile b/Makefile index bd09088..5e85620 100644 --- a/Makefile +++ b/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)) diff --git a/src/calc.c b/src/calc.c new file mode 100644 index 0000000..8b55d08 --- /dev/null +++ b/src/calc.c @@ -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) +} + + diff --git a/src/calc.h b/src/calc.h new file mode 100644 index 0000000..6077669 --- /dev/null +++ b/src/calc.h @@ -0,0 +1,22 @@ +/* + * calc.h + * + * Created on: Mar 28, 2019 + */ + +#ifndef SRC_CALC_H_ +#define SRC_CALC_H_ + +#include +#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_ */ diff --git a/src/lcd.c b/src/lcd.c index 4578dbc..6c6ebae 100644 --- a/src/lcd.c +++ b/src/lcd.c @@ -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(' '); } } diff --git a/src/lcd.h b/src/lcd.h index 1ce06a1..f80253b 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -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); diff --git a/src/main.c b/src/main.c index 9fd3167..490b8bf 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,8 @@ #include #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) } /* ------------------------------------------------------------------------- */