/*
* Copyright 2018 Alexander A. Strelets. All rights reserved.
*
* Author: Alexander A. Strelets
* e-mail:
[email protected]
*
* This program is the proprietary software of the Author and/or his
* licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and the Author (an "Authorized
* License"). Except as set forth in an Authorized License, the Author
* grants no license (express or implied), right to use, or waiver of
* any kind with respect to the Software, and the Author expressly
* reserves all rights in and to the Software and all intellectual
* property rights therein.
*
* IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
* SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY THE AUTHOR AND
* DISCONTINUE ALL USE OF THE SOFTWARE.
*/
#undef __STRICT_ANSI__
#define _POSIX_SOURCE
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "adapter.h"
enum message_e { HELLO, BYE, PROMPT };
#if __linux__ || __unix__
#define SEND_EOF "Ctrl+D at a new line, or "
#elif __WINNT__ && __MINGW32__
#define SEND_EOF "Ctrl+Z at a new line and then ENTER, or "
#else
#define SEND_EOF ""
#endif
static const char *const messages[] = {
/* HELLO */
TARGET " simulator.\n"
"Type in a sequence of keystrokes and hit ENTER to confirm.\n"
"The following keys are recognized:\n"
" " KEYS "\n"
"Simulator will process them one-by-one and print the state:\n"
" " STATE "\n"
"To cancel press " SEND_EOF "Ctrl+C, or whatever you have.\n"
"Enjoy! Best regards, xoiss, Moscow, 2018.\n",
/* BYE */
"\nSee you!\n"
"And visit: http://www.phantom.sannata.ru/forum/\n",
/* PROMPT */
"> "
};
static int hide_dialogs;
static int isinteractive(void);
static int isendofstream(void);
static void print_message(enum message_e message_id);
static void process_input(void);
int main(void)
{
hide_dialogs = !isinteractive();
print_message(HELLO);
while (!isendofstream()) {
print_message(PROMPT);
process_input();
}
print_message(BYE);
return EXIT_SUCCESS;
}
static int isinteractive(void)
{
if (isatty(fileno(stdin)) == 0) {
#if __linux__ || __unix__
if (errno != EINVAL && errno != ENOTTY) {
perror("isatty");
exit(EXIT_FAILURE);
}
#endif
return 0;
}
return 1;
}
static int isendofstream(void)
{
return ferror(stdin) || feof(stdin);
}
static void print_message(enum message_e message_id)
{
if (!hide_dialogs) {
fputs(messages[message_id], stdout);
fflush(stdout);
}
}
static void process_input(void)
{
char s[256], *p, c;
while ((p = fgets(s, sizeof s, stdin)) != NULL) {
while ((c = *p++) != '\0') {
if (c == '\n') {
return;
}
if (process_key(&c)) {
fprintf(stdout, "[%c] => %s\n", c, print_state());
fflush(stdout);
}
}
}
}
/*
* Copyright 2018 Alexander A. Strelets. All rights reserved.
*
* Author: Alexander A. Strelets
* e-mail:
[email protected]
*
* This program is the proprietary software of the Author and/or his
* licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and the Author (an "Authorized
* License"). Except as set forth in an Authorized License, the Author
* grants no license (express or implied), right to use, or waiver of
* any kind with respect to the Software, and the Author expressly
* reserves all rights in and to the Software and all intellectual
* property rights therein.
*
* IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
* SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY THE AUTHOR AND
* DISCONTINUE ALL USE OF THE SOFTWARE.
*/
#include "adapter.h"
#include "simulator.h"
static const struct { char c; enum key_e key; } char2key[] = {
{ 'C', KEY_C }, { 'c', KEY_C }, { '%', KEY_PCT }, { '+', KEY_ADD },
{ '7', KEY_7 }, { '8', KEY_8 }, { '9', KEY_9 }, { '-', KEY_SUB },
{ '4', KEY_4 }, { '5', KEY_5 }, { '6', KEY_6 }, { '*', KEY_MUL },
{ '1', KEY_1 }, { '2', KEY_2 }, { '3', KEY_3 }, { '/', KEY_DIV },
{ '0', KEY_0 }, { '.', KEY_P }, { ',', KEY_P }, { '=', KEY_EQU },
};
static const struct { enum state_e state; char c; } state2char[] = {
{ ST_READY, 'R' },
{ ST_INT, 'I' },
{ ST_FRAC, 'F' },
{ ST_ERROR, 'E' },
};
static const struct { enum func_e func; char c; } func2char[] = {
{ FN_NOP, ' ' },
{ FN_ADD, '+' }, { FN_SUB, '-' }, { FN_MUL, '*' }, { FN_DIV, '/' },
{ FN_REP_ADD, '+' }, { FN_REP_SUB, '-' },
{ FN_REP_MUL, '*' }, { FN_REP_DIV, '/' },
{ FN_PCT_ADD, '+' }, { FN_PCT_SUB, '-' },
{ FN_PCT_MUL, '*' }, { FN_PCT_DIV, '/' },
};
static const struct { enum func_e func; char c; } mode2char[] = {
{ FN_NOP, ' ' },
{ FN_ADD, ' ' }, { FN_SUB, ' ' }, { FN_MUL, ' ' }, { FN_DIV, ' ' },
{ FN_REP_ADD, 'K' }, { FN_REP_SUB, 'K' },
{ FN_REP_MUL, 'K' }, { FN_REP_DIV, 'K' },
{ FN_PCT_ADD, '%' }, { FN_PCT_SUB, '%' },
{ FN_PCT_MUL, '%' }, { FN_PCT_DIV, '%' },
};
static void print_display(char **p);
static void print_register(char **p, struct reg_s *reg);
int process_key(char *c)
{
enum key_e key;
unsigned i;
for (i = 0; i < sizeof char2key / sizeof char2key[0]; ++i) {
if (char2key[i].c == *c) {
key = char2key[i].key;
key_pressed(key);
while (i-- > 0) {
if (char2key[i].key == key) {
*c = char2key[i].c;
}
}
return 1;
}
}
return 0;
}
const char *print_state(void)
{
static char s[256];
char *p = s;
char state_c = '?', func_c ='?', mode_c = '?';
unsigned i;
for (i = 0; i < sizeof state2char / sizeof state2char[0]; ++i) {
if (state2char[i].state == control.state) {
state_c = state2char[i].c;
}
}
for (i = 0; i < sizeof func2char / sizeof func2char[0]; ++i) {
if (func2char[i].func == control.func) {
func_c = func2char[i].c;
}
}
for (i = 0; i < sizeof mode2char / sizeof mode2char[0]; ++i) {
if (mode2char[i].func == control.func) {
mode_c = mode2char[i].c;
}
}
*p++ = '[';
*p++ = ' ';
print_display(&p);
*p++ = ']';
*p++ = ' ';
*p++ = ' ';
*p++ = '[';
*p++ = ' ';
print_register(&p, ®_1);
*p++ = ' ';
print_register(&p, ®_2);
*p++ = ' ';
*p++ = state_c;
*p++ = ' ';
*p++ = func_c;
*p++ = ' ';
*p++ = mode_c;
*p++ = ' ';
*p++ = ']';
*p++ = '\0';
return s;
}
static void print_display(char **p)
{
/* "- 0. 0. 0. 0. 0. 0. 0. 0. " */
int e = 0;
int i;
*(*p)++ = reg_1.neg ? '-' : ' ';
*(*p)++ = ' ';
*(*p)++ = ' ';
for (i = WIDTH - 1; i >= 0; --i) {
if (reg_1.d[i] != 0 || i == reg_1.exp) {
e = 1;
}
*(*p)++ = e ? (char)(reg_1.d[i] + '0') : ' ';
*(*p)++ = (i == reg_1.exp || control.state == ST_ERROR)
? '.' : ' ';
*(*p)++ = ' ';
}
}
static void print_register(char **p, struct reg_s *reg)
{
/* "+0000000." */
int i;
*(*p)++ = reg->neg ? '-' : '+';
for (i = WIDTH - 1; i >= 0; --i) {
*(*p)++ = (char)(reg->d[i] + '0');
if (i == reg->exp) {
*(*p)++ = '.';
}
}
}
/*
* Copyright 2018 Alexander A. Strelets. All rights reserved.
*
* Author: Alexander A. Strelets
* e-mail:
[email protected]
*
* This program is the proprietary software of the Author and/or his
* licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and the Author (an "Authorized
* License"). Except as set forth in an Authorized License, the Author
* grants no license (express or implied), right to use, or waiver of
* any kind with respect to the Software, and the Author expressly
* reserves all rights in and to the Software and all intellectual
* property rights therein.
*
* IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
* SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY THE AUTHOR AND
* DISCONTINUE ALL USE OF THE SOFTWARE.
*/
#ifndef ADAPTER_B3_23_CONSOLE_H_
#define ADAPTER_B3_23_CONSOLE_H_
#define TARGET "Elektronika B3-23"
#define KEYS "C 0 1 2 3 4 5 6 7 8 9 . , + - * / % ="
#define STATE "indicator and second registers, operational triggers"
extern int process_key(char *c);
extern const char *print_state(void);
#endif /* ADAPTER_B3_23_CONSOLE_H_ */
/*
* Copyright 2018 Alexander A. Strelets. All rights reserved.
*
* Author: Alexander A. Strelets
* e-mail:
[email protected]
*
* This program is the proprietary software of the Author and/or his
* licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and the Author (an "Authorized
* License"). Except as set forth in an Authorized License, the Author
* grants no license (express or implied), right to use, or waiver of
* any kind with respect to the Software, and the Author expressly
* reserves all rights in and to the Software and all intellectual
* property rights therein.
*
* IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
* SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY THE AUTHOR AND
* DISCONTINUE ALL USE OF THE SOFTWARE.
*/
#include "simulator.h"
struct reg_s reg_1;
struct reg_s reg_2;
struct control_s control;
enum mode_e { MD_EQU, MD_PCT };
static void process_clear(void);
static void process_number(enum key_e key);
static void process_point(void);
static void process_function(enum key_e key);
static void process_equal(void);
static void process_percent(void);
static void clear_all(void);
static void clear_display(void);
static void enter_number(int digit);
static void normalize_display(void);
static void push_argument(void);
static void exchange_arguments(void);
static int calculate(enum mode_e mode);
static int isrepeated(void);
static int ispercentage(void);
static enum func_e getfunc(void);
static void setmode(enum mode_e mode);
static int calculate_add(void);
static int calculate_sub(void);
static int calculate_mul(enum mode_e mode);
static int calculate_div(enum mode_e mode);
static int iszero(struct reg_s *reg);
static void clear(struct reg_s *reg);
static void normalize(struct reg_s *reg);
static void denormalize(struct reg_s *reg);
static int justify(struct reg_s *reg);
static void round(struct reg_s *reg);
static void equalize(struct reg_s *reg_a, struct reg_s *reg_b);
static int compare(struct reg_s *reg_a, struct reg_s *reg_b);
static void exchange(struct reg_s *reg_a, struct reg_s *reg_b);
static int add(struct reg_s *reg_dst, struct reg_s *reg_src);
static int sub(struct reg_s *reg_dst, struct reg_s *reg_src);
static int islimit_left(struct reg_s *reg);
static int islimit_right(struct reg_s *reg);
static void shift_left(struct reg_s *reg);
static void shift_right(struct reg_s *reg);
void key_pressed(enum key_e key)
{
if (key == KEY_C) {
process_clear();
return;
}
if (control.state == ST_ERROR) {
return;
}
switch (key) {
case KEY_0: case KEY_1: case KEY_2: case KEY_3: case KEY_4:
case KEY_5: case KEY_6: case KEY_7: case KEY_8: case KEY_9:
process_number(key);
break;
case KEY_P:
process_point();
break;
case KEY_ADD: case KEY_SUB: case KEY_MUL: case KEY_DIV:
process_function(key);
break;
case KEY_EQU:
process_equal();
break;
case KEY_PCT:
process_percent();
break;
default:
break;
}
}
static void process_clear(void)
{
switch (control.state) {
case ST_READY:
clear_all();
break;
case ST_INT: case ST_FRAC:
clear_display();
break;
case ST_ERROR:
break;
}
control.state = ST_READY;
}
static void process_number(enum key_e key)
{
if (control.state == ST_READY) {
clear_display();
control.state = ST_INT;
}
enter_number((int)(key - KEY_0));
}
static void process_point(void)
{
if (control.state == ST_READY) {
clear_display();
}
control.state = ST_FRAC;
}
static void process_function(enum key_e key)
{
if (isrepeated()) {
control.func = FN_NOP;
}
if (control.state != ST_READY) {
process_equal();
}
if (isrepeated() || control.func == FN_NOP) {
push_argument();
}
control.func = (key - KEY_ADD + FN_ADD);
}
static void process_equal(void)
{
int error;
normalize_display();
if (!isrepeated() && control.func != FN_NOP) {
exchange_arguments();
}
error = calculate(MD_EQU);
control.state = error ? ST_ERROR : ST_READY;
}
static void process_percent(void)
{
int error;
normalize_display();
if (control.func == FN_MUL || control.func == FN_DIV) {
exchange_arguments();
}
error = calculate(MD_PCT);
control.state = error ? ST_ERROR : ST_READY;
}
static void clear_all(void)
{
clear(®_1);
clear(®_2);
control.func = FN_NOP;
}
static void clear_display(void)
{
clear(®_1);
}
static void enter_number(int digit)
{
if (!islimit_left(®_1)) {
shift_left(®_1);
reg_1.d[0] = digit;
reg_1.exp += (control.state == ST_FRAC);
}
}
static void normalize_display(void)
{
normalize(®_1);
}
static void push_argument(void)
{
reg_2 = reg_1;
}
static void exchange_arguments(void)
{
exchange(®_1, ®_2);
}
static int calculate(enum mode_e mode)
{
int error;
if (mode == MD_EQU) {
switch (getfunc()) {
case FN_ADD:
error = calculate_add();
break;
case FN_SUB:
error = calculate_sub();
reg_1.neg ^= ispercentage();
break;
case FN_MUL:
error = calculate_mul(MD_EQU);
break;
case FN_DIV:
error = calculate_div(MD_EQU);
break;
default:
return 0;
}
} else {
switch (getfunc()) {
case FN_ADD: case FN_SUB: case FN_MUL:
error = calculate_mul(MD_PCT);
break;
case FN_DIV:
error = calculate_div(MD_PCT);
break;
default:
return 0;
}
}
setmode(mode);
if (!error) {
normalize_display();
}
return error;
}
static int isrepeated(void)
{
return control.func >= FN_REP_ADD;
}
static int ispercentage(void)
{
return control.func >= FN_PCT_ADD;
}
static enum func_e getfunc(void)
{
enum func_e func = control.func;
if (ispercentage()) {
func -= (FN_PCT_ADD - FN_ADD);
} else if (isrepeated()) {
func -= (FN_REP_ADD - FN_ADD);
}
return func;
}
static void setmode(enum mode_e mode)
{
enum func_e func = getfunc();
if (mode == MD_PCT) {
func += (FN_PCT_ADD - FN_ADD);
} else {
func += (FN_REP_ADD - FN_ADD);
}
control.func = func;
}
static int calculate_add(void)
{
int carry, borrow, reg_1b;
struct reg_s reg_2b = reg_2;
denormalize(®_1);
denormalize(®_2b);
if (reg_1.neg == reg_2b.neg) {
equalize(®_1, ®_2b);
carry = add(®_1, ®_2b);
if (carry != 0) {
shift_right(®_1);
reg_1.d[WIDTH - 1] = carry;
reg_1.exp -= 1;
if (reg_1.exp < 0) {
reg_1.exp += WIDTH;
return 1; /* overflow */
}
}
} else {
if (reg_1.exp != reg_2b.exp) {
if (reg_1.exp > reg_2b.exp) {
exchange(®_1, ®_2b);
}
reg_1b = reg_1.d[WIDTH - 1];
shift_left(®_1);
reg_1.exp += 1;
equalize(®_1, ®_2b);
borrow = sub(®_1, ®_2b);
reg_1b -= borrow;
if (reg_1b != 0) {
shift_right(®_1);
reg_1.d[WIDTH - 1] = reg_1b;
reg_1.exp -= 1;
}
} else {
if (compare(®_1, ®_2b) < 0) {
exchange(®_1, ®_2b);
}
sub(®_1, ®_2b);
}
}
return 0;
}
static int calculate_sub(void)
{
int error;
reg_2.neg = !reg_2.neg;
error = calculate_add();
reg_2.neg = !reg_2.neg;
return error;
}
static int calculate_mul(enum mode_e mode)
{
int i, digit, carry = 0, exp_2 = reg_2.exp;
struct reg_s reg_p;
clear(®_p);
reg_p.exp = justify(®_1) + justify(®_2) - (WIDTH - 1);
reg_p.neg = reg_1.neg ^ reg_2.neg;
for (i = 0; i < WIDTH; ++i) {
shift_right(®_p);
reg_p.d[WIDTH - 1] = carry;
carry = 0;
for (digit = reg_2.d[i]; digit > 0; --digit) {
carry += add(®_p, ®_1);
}
}
if (carry != 0) {
shift_right(®_p);
reg_p.d[WIDTH - 1] = carry;
reg_p.exp -= 1;
}
normalize(®_2);
reg_2.exp = exp_2;
reg_1 = reg_p;
if (mode == MD_PCT) {
reg_1.exp += 2;
}
if (reg_1.exp < 0) {
reg_1.exp += WIDTH;
return 1; /* overflow */
}
round(®_1);
return 0;
}
static int calculate_div(enum mode_e mode)
{
int i, digit, borrow, reg_1b = 0, exp_2 = reg_2.exp;
struct reg_s reg_q;
if (iszero(®_2)) {
clear(®_1);
reg_1.exp = (WIDTH - 1);
return 1; /* overflow */
}
clear(®_q);
reg_q.exp = justify(®_1) - justify(®_2) + (WIDTH - 1);
reg_q.neg = reg_1.neg ^ reg_2.neg;
if (compare(®_1, ®_2) < 0) {
reg_1b = reg_1.d[WIDTH - 1];
shift_left(®_1);
reg_q.exp += 1;
}
for (i = WIDTH - 1; i >= 0; --i) {
digit = 0;
while (reg_1b != 0 || compare(®_1, ®_2) >= 0) {
borrow = sub(®_1, ®_2);
reg_1b -= borrow;
digit += 1;
}
reg_q.d[i] = digit;
reg_1b = reg_1.d[WIDTH - 1];
shift_left(®_1);
}
digit = 0;
while (reg_1b != 0 || compare(®_1, ®_2) >= 0) {
borrow = sub(®_1, ®_2);
reg_1b -= borrow;
digit += 1;
}
if (digit >= 5) {
clear(®_1);
reg_1.d[0] = 1;
add(®_q, ®_1);
}
if (mode == MD_PCT) {
reg_q.exp -= 2;
}
normalize(®_2);
reg_2.exp = exp_2;
reg_1 = reg_q;
if (reg_1.exp < 0) {
reg_1.exp += WIDTH;
if (reg_1.exp < 0) {
reg_1.exp += WIDTH;
}
return 1; /* overflow */
}
round(®_1);
return 0;
}
static int iszero(struct reg_s *reg)
{
int i;
for (i = 0; i < WIDTH; ++i) {
if (reg->d[i] != 0) {
return 0;
}
}
return 1;
}
static void clear(struct reg_s *reg)
{
int i;
for (i = 0; i < WIDTH; ++i) {
reg->d[i] = 0;
}
reg->exp = 0;
reg->neg = 0;
}
static void normalize(struct reg_s *reg)
{
while (!islimit_right(reg)) {
shift_right(reg);
reg->exp -= 1;
}
if (iszero(reg)) {
reg->neg = 0;
}
}
static void denormalize(struct reg_s *reg)
{
while (!islimit_left(reg)) {
shift_left(reg);
reg->exp += 1;
}
}
static int justify(struct reg_s *reg)
{
int exp = reg->exp;
reg->exp = 0;
denormalize(reg);
return exp + reg->exp;
}
static void round(struct reg_s *reg)
{
while (reg->exp >= WIDTH) {
shift_right(reg);
reg->exp -= 1;
}
}
static void equalize(struct reg_s *reg_a, struct reg_s *reg_b)
{
while (reg_a->exp > reg_b->exp) {
shift_right(reg_a);
reg_a->exp -= 1;
}
while (reg_a->exp < reg_b->exp) {
shift_right(reg_b);
reg_b->exp -= 1;
}
}
static int compare(struct reg_s *reg_a, struct reg_s *reg_b)
{
int i;
for (i = WIDTH - 1; i >= 0; --i) {
if (reg_a->d[i] > reg_b->d[i]) {
return 1;
}
if (reg_a->d[i] < reg_b->d[i]) {
return -1;
}
}
return 0;
}
static void exchange(struct reg_s *reg_a, struct reg_s *reg_b)
{
struct reg_s reg_x = *reg_b;
*reg_b = *reg_a;
*reg_a = reg_x;
}
static int add(struct reg_s *reg_dst, struct reg_s *reg_src)
{
int i, digit, carry = 0;
for (i = 0; i < WIDTH; ++i) {
digit = reg_dst->d[i] + reg_src->d[i] + carry;
if (digit < 10) {
reg_dst->d[i] = digit;
carry = 0;
} else {
reg_dst->d[i] = digit - 10;
carry = 1;
}
}
return carry;
}
static int sub(struct reg_s *reg_dst, struct reg_s *reg_src)
{
int i, digit, borrow = 0;
for (i = 0; i < WIDTH; ++i) {
digit = reg_dst->d[i] - reg_src->d[i] - borrow;
if (digit >= 0) {
reg_dst->d[i] = digit;
borrow = 0;
} else {
reg_dst->d[i] = digit + 10;
borrow = 1;
}
}
return borrow;
}
static int islimit_left(struct reg_s *reg)
{
return reg->d[WIDTH - 1] != 0 || reg->exp == WIDTH - 1;
}
static int islimit_right(struct reg_s *reg)
{
return reg->d[0] != 0 || reg->exp == 0;
}
static void shift_left(struct reg_s *reg)
{
int i;
for (i = WIDTH - 1; i > 0; --i) {
reg->d[i] = reg->d[i - 1];
}
reg->d[0] = 0;
}
static void shift_right(struct reg_s *reg)
{
int i, digit, carry;
carry = (reg->d[0] >= 5);
for (i = 0; i < WIDTH - 1; ++i) {
digit = reg->d[i + 1] + carry;
if (digit < 10) {
reg->d[i] = digit;
carry = 0;
} else {
reg->d[i] = 0;
carry = 1;
}
}
reg->d[WIDTH - 1] = carry;
}
/*
* Copyright 2018 Alexander A. Strelets. All rights reserved.
*
* Author: Alexander A. Strelets
* e-mail:
[email protected]
*
* This program is the proprietary software of the Author and/or his
* licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and the Author (an "Authorized
* License"). Except as set forth in an Authorized License, the Author
* grants no license (express or implied), right to use, or waiver of
* any kind with respect to the Software, and the Author expressly
* reserves all rights in and to the Software and all intellectual
* property rights therein.
*
* IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS
* SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY THE AUTHOR AND
* DISCONTINUE ALL USE OF THE SOFTWARE.
*/
#ifndef SIMULATOR_B3_23_H_
#define SIMULATOR_B3_23_H_
enum key_e {
KEY_C,
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
KEY_P,
KEY_ADD, KEY_SUB, KEY_MUL, KEY_DIV,
KEY_EQU,
KEY_PCT
};
#define WIDTH (8)
struct reg_s {
int d[WIDTH]; /* digits of the value, #0 - the rightmost digit */
int exp; /* number of digits to the left of the point */
int neg; /* if the value is negative */
};
extern struct reg_s reg_1; /* displayed argument */
extern struct reg_s reg_2; /* second argument, the constant */
enum state_e {
ST_READY = 0, /* after power-on, clear entry, or calculation */
ST_INT, /* entering the integer part of an argument */
ST_FRAC, /* entering the fractional part, point is set */
ST_ERROR /* error after calculation */
};
enum func_e {
FN_NOP = 0, /* no operation */
FN_ADD, FN_SUB, FN_MUL, FN_DIV, /* chained calculations */
FN_REP_ADD, FN_REP_SUB, /* repeated calculations */
FN_REP_MUL, FN_REP_DIV,
FN_PCT_ADD, FN_PCT_SUB, /* percentage calculations */
FN_PCT_MUL, FN_PCT_DIV
};
struct control_s {
enum state_e state;
enum func_e func;
};
extern struct control_s control;
extern void key_pressed(enum key_e key);
#endif /* SIMULATOR_B3_23_H_ */