initial calculator code
This commit is contained in:
parent
bdecc32b86
commit
ecb0492534
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ STCCODESIZE ?= 13000
|
|||||||
SDCCOPTS ?= --code-size $(STCCODESIZE) --xram-size 0 --stack-auto
|
SDCCOPTS ?= --code-size $(STCCODESIZE) --xram-size 0 --stack-auto
|
||||||
FLASHFILE ?= main.hex
|
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))
|
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);
|
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;
|
const char *s;
|
||||||
for (s = string; *s; s++) {
|
for (s = string; *s && max_chars > 0; s++, max_chars--) {
|
||||||
TERMIO_PutChar(*s);
|
TERMIO_PutChar(*s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,8 +251,8 @@ short TERMIO_PutChar(unsigned char letter) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCD_ClearToEnd(void){
|
void LCD_ClearToEnd(uint8_t curr_row){
|
||||||
while (col != 0){
|
while (col != 0 && row == curr_row){
|
||||||
TERMIO_PutChar(' ');
|
TERMIO_PutChar(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,10 @@ void LCD_Clear(void);
|
|||||||
void LCD_GoTo(unsigned int row, unsigned int col);
|
void LCD_GoTo(unsigned int row, unsigned int col);
|
||||||
void LCD_SingleLineGoTo(unsigned int row_to);
|
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);
|
short TERMIO_PutChar(unsigned char letter);
|
||||||
void LCD_OutNibble(uint8_t x);
|
void LCD_OutNibble(uint8_t x);
|
||||||
void LCD_ClearToEnd(void);
|
void LCD_ClearToEnd(uint8_t curr_row);
|
||||||
|
|
||||||
unsigned char LCD_Timeout_Error(void);
|
unsigned char LCD_Timeout_Error(void);
|
||||||
|
|
||||||
|
212
src/main.c
212
src/main.c
@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "decn/decn.h"
|
||||||
|
#include "calc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define FOSC 11583000
|
#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()
|
int main()
|
||||||
{
|
{
|
||||||
uint32_t i;
|
enum {
|
||||||
uint8_t j;
|
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;
|
const uint8_t* keys;
|
||||||
uint8_t key_i;
|
uint8_t key_i;
|
||||||
Timer0Init(); // display refresh & switch read
|
Timer0Init(); // display refresh & switch read
|
||||||
@ -106,6 +122,14 @@ int main()
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
LCD_GoTo(0,0);
|
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
|
//keyboard debug
|
||||||
keys = DebugGetKeys();
|
keys = DebugGetKeys();
|
||||||
for (key_i = 0; key_i < 5; key_i++){
|
for (key_i = 0; key_i < 5; key_i++){
|
||||||
@ -136,17 +160,199 @@ int main()
|
|||||||
new_key_empty = 1;
|
new_key_empty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_KEYS
|
||||||
LCD_GoTo(1,j);
|
LCD_GoTo(1,j);
|
||||||
|
#endif
|
||||||
|
//find first key pressed in array (if any)
|
||||||
for (i_key = 0; i_key < 20; i_key++){
|
for (i_key = 0; i_key < 20; i_key++){
|
||||||
if (new_keys & ((uint32_t) 1 << i_key)){
|
if (new_keys & ((uint32_t) 1 << i_key)){
|
||||||
|
#ifdef DEBUG_KEYS
|
||||||
TERMIO_PutChar(KEY_MAP[i_key]);
|
TERMIO_PutChar(KEY_MAP[i_key]);
|
||||||
j++;
|
j++;
|
||||||
j &= 0x0f;
|
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;
|
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)
|
||||||
}
|
}
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user