From eecba580702f62612e7cf942e747249aeaba424b Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Fri, 20 Jul 2012 10:43:44 -0500 Subject: [PATCH] Refactor and clean up --- curta.c | 23 +++ curtaModel.c | 170 ++++++++++++++++++++++ curtaModel.h | 60 ++++++++ curtaEm.c => curtaUI.c | 312 +++++++++++------------------------------ curtaUI.h | 18 +++ 5 files changed, 355 insertions(+), 228 deletions(-) create mode 100644 curta.c create mode 100644 curtaModel.c create mode 100644 curtaModel.h rename curtaEm.c => curtaUI.c (64%) create mode 100644 curtaUI.h diff --git a/curta.c b/curta.c new file mode 100644 index 0000000..168bebb --- /dev/null +++ b/curta.c @@ -0,0 +1,23 @@ +// +// Author: Jeremy Rand +// Date: July 20, 2012 +// +// This is the main entry point for the Curta emulator. +// + + +#include "curtaUI.h" + + +int main(void) +{ + bool timeToQuit = false; + initUI(); + + while (!timeToQuit) { + timeToQuit= processNextEvent(); + } + + shutdownUI(); + return 0; +} diff --git a/curtaModel.c b/curtaModel.c new file mode 100644 index 0000000..a246045 --- /dev/null +++ b/curtaModel.c @@ -0,0 +1,170 @@ +// +// Author: Jeremy Rand +// Date: July 20, 2012 +// +// This is the implementation for the Curta emulator model. +// + + +#include + +#include "curtaModel.h" + + +tDigit operand[NUM_OPERAND_DIGITS]; +tDigit result[NUM_RESULT_DIGITS]; +tDigit counter[NUM_COUNTER_DIGITS]; + +tDigitPos basePos; + +tDigitPos selectedOperand; + + +static operandChangeNotif operandCallback = NULL; + + +void clearDevice(void) +{ + tDigitPos pos; + + for (pos = 0; pos < NUM_RESULT_DIGITS; pos++) { + result[pos] = 0; + } + for (pos = 0; pos < NUM_COUNTER_DIGITS; pos++) { + counter[pos] = 0; + } +} + + +void initDevice(operandChangeNotif callback) +{ + tDigitPos pos; + + operandCallback = callback; + + clearDevice(); + basePos = 0; + selectedOperand = 0; + + for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { + result[pos] = 0; + } +} + + +void incOperandPos(tDigitPos pos) +{ + if (!IS_VALID_OPERAND_POS(pos)) + return; + + if (operand[pos] == 9) + return; + + operand[pos]++; + if (operandCallback != NULL) + operandCallback(pos); +} + + +void decOperandPos(tDigitPos pos) +{ + if (!IS_VALID_OPERAND_POS(pos)) + return; + + if (operand[pos] == 0) + return; + + operand[pos]--; + if (operandCallback != NULL) + operandCallback(pos); +} + + +void shiftOperandPos(bool left) +{ + tDigitPos newPos = selectedOperand; + tDigitPos oldPos = selectedOperand; + + if (left) { + newPos++; + if (!IS_VALID_OPERAND_POS(newPos)) { + return; + } + } else { + newPos--; + if (!IS_VALID_OPERAND_POS(newPos)) { + return; + } + } + + selectedOperand = newPos; + if (operandCallback != NULL) { + operandCallback(oldPos); + operandCallback(newPos); + } +} + +void shiftResultPos(bool left) +{ + tDigitPos newPos = basePos; + if (left) { + newPos++; + if (!IS_VALID_BASE_POS(newPos)) + return; + } else { + newPos--; + if (!IS_VALID_BASE_POS(newPos)) + return; + } + basePos = newPos; +} + + +static void subOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toSub) +{ + if (toSub == 0) + return; + + if (pos >= maxPos) + return; + + digits[pos]-=toSub; + while (digits[pos] < 0) { + digits[pos]+=10; + subOperation(digits, pos+1, maxPos, 1); + } +} + + +static void addOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toAdd) +{ + if (toAdd == 0) + return; + + if (pos >= maxPos) + return; + + digits[pos]+=toAdd; + while (digits[pos] > 9) { + digits[pos]-=10; + addOperation(digits, pos+1, maxPos, 1); + } +} + + +void crank(bool isSubtract) +{ + tDigitPos pos; + if (isSubtract) { + subOperation(counter, basePos, NUM_COUNTER_DIGITS, 1); + for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { + subOperation(result, basePos+pos, NUM_RESULT_DIGITS, operand[pos]); + } + } else { + addOperation(counter, basePos, NUM_COUNTER_DIGITS, 1); + for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { + addOperation(result, basePos+pos, NUM_RESULT_DIGITS, operand[pos]); + } + } +} + diff --git a/curtaModel.h b/curtaModel.h new file mode 100644 index 0000000..2e55823 --- /dev/null +++ b/curtaModel.h @@ -0,0 +1,60 @@ +// +// Author: Jeremy Rand +// Date: July 20, 2012 +// +// This is the interface for the Curta emulator model. +// + + +#include +#include + + +#ifndef _CURTAMODEL_H +#define _CURTAMODEL_H + +#define NUM_OPERAND_DIGITS 11 +#define NUM_RESULT_DIGITS 15 +#define NUM_COUNTER_DIGITS 8 + +typedef int8_t tDigit; +typedef int8_t tDigitPos; + +extern tDigit operand[NUM_OPERAND_DIGITS]; +extern tDigit result[NUM_RESULT_DIGITS]; +extern tDigit counter[NUM_COUNTER_DIGITS]; + +#define IS_VALID_OPERAND_POS(pos) (((pos) >= 0) && ((pos) < NUM_OPERAND_DIGITS)) +#define IS_VALID_RESULT_POS(pos) (((pos) >= 0) && ((pos) < NUM_RESULT_DIGITS)) +#define IS_VALID_COUNTER_POS(pos) (((pos) >= 0) && ((pos) < NUM_COUNTER_DIGITS)) + +#define GET_OPERAND_DIGIT(pos) (operand[(pos)]) +#define GET_RESULT_DIGIT(pos) (result[(pos)]) +#define GET_COUNTER_DIGIT(pos) (counter[(pos)]) + +// Ranges from 0 to 8 +#define BASE_POS_MIN 0 +#define BASE_POS_MAX 8 +extern tDigitPos basePos; + +#define IS_VALID_BASE_POS(pos) (((pos) >= BASE_POS_MIN) && ((pos) < BASE_POS_MAX)) + +extern tDigitPos selectedOperand; +#define IS_SELECTED_OPERAND(pos) ((pos) == selectedOperand); + + +typedef void (*operandChangeNotif)(tDigitPos pos); + +extern void clearDevice(void); +extern void initDevice(operandChangeNotif callback); + +extern void incOperandPos(tDigitPos pos); +extern void decOperandPos(tDigitPos pos); + +extern void shiftOperandPos(bool left); + +extern void shiftResultPos(bool left); + +extern void crank(bool isSubtract); + +#endif diff --git a/curtaEm.c b/curtaUI.c similarity index 64% rename from curtaEm.c rename to curtaUI.c index b1721a3..41303d6 100644 --- a/curtaEm.c +++ b/curtaUI.c @@ -1,29 +1,30 @@ -#include -#include -#include +// +// Author: Jeremy Rand +// Date: July 20, 2012 +// +// This is the implementation for the Curta emulator UI. +// + + #include #include -#include +#include #include #include -#include #include #include #include +#include "curtaModel.h" +#include "curtaUI.h" + // Extern symbols for joystick and graphics drivers extern char a2e_stdjoy; extern char a2e_hi; -#define NUM_OPERAND_DIGITS 11 -#define NUM_RESULT_DIGITS 15 -#define NUM_COUNTER_DIGITS 8 -typedef int8_t tDigit; -typedef int8_t tDigitPos; typedef int8_t tAction; -typedef int8_t tJoyPos; #define ACTION_OPERAND_SHIFT_LEFT 0 #define ACTION_OPERAND_SHIFT_RIGHT 1 @@ -36,6 +37,9 @@ typedef int8_t tJoyPos; #define ACTION_CLEAR 8 #define ACTION_NULL 9 + +typedef int8_t tJoyPos; + #define JOY_POS_CENTER 0 #define JOY_POS_DOWN 1 #define JOY_POS_DOWN_LEFT 2 @@ -46,16 +50,6 @@ typedef int8_t tJoyPos; #define JOY_POS_RIGHT 7 #define JOY_POS_DOWN_RIGHT 8 -tDigit operand[NUM_OPERAND_DIGITS]; -tDigit result[NUM_RESULT_DIGITS]; -tDigit counter[NUM_COUNTER_DIGITS]; - -// Ranges from 0 to 8 -#define RESULT_POS_MIN 0 -#define RESULT_POS_MAX 8 -tDigitPos resultPos; -tDigitPos selectedOperand; - #define OPERAND_COLOR COLOR_WHITE #define OPERAND_OFFSET 4 @@ -76,148 +70,7 @@ tDigitPos selectedOperand; #define SLIDER_Y_SPACING (SLIDER_HEIGHT + (2 * SLIDER_Y_OFFSET)) -void drawOperand(tDigitPos pos); - - -void clearDevice(void) -{ - tDigitPos pos; - - for (pos = 0; pos < NUM_RESULT_DIGITS; pos++) { - result[pos] = 0; - } - for (pos = 0; pos < NUM_COUNTER_DIGITS; pos++) { - counter[pos] = 0; - } -} - - -void resetDevice(void) -{ - tDigitPos pos; - - clearDevice(); - resultPos = 0; - selectedOperand = 0; - - for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { - result[pos] = 0; - } -} - - -void incOperandPos(tDigitPos pos) -{ - if (pos >= NUM_OPERAND_DIGITS) - return; - - if (operand[pos] == 9) - return; - - operand[pos]++; - drawOperand(pos); -} - - -void decOperandPos(tDigitPos pos) -{ - if (pos >= NUM_OPERAND_DIGITS) - return; - - if (operand[pos] == 0) - return; - - operand[pos]--; - drawOperand(pos); -} - - -void shiftOperandPos(bool left) -{ - tDigitPos newPos = selectedOperand; - tDigitPos oldPos = selectedOperand; - - if (left) { - newPos++; - if (newPos >= NUM_OPERAND_DIGITS) { - return; - } - } else { - newPos--; - if (newPos < 0) { - return; - } - } - - selectedOperand = newPos; - drawOperand(oldPos); - drawOperand(newPos); -} - -void shiftResultPos(bool left) -{ - if (left) { - if (resultPos + 1 >= RESULT_POS_MAX) - return; - resultPos++; - } else { - if (resultPos <= RESULT_POS_MIN) - return; - resultPos--; - } -} - - -void subOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toSub) -{ - if (toSub == 0) - return; - - if (pos >= maxPos) - return; - - digits[pos]-=toSub; - while (digits[pos] < 0) { - digits[pos]+=10; - subOperation(digits, pos+1, maxPos, 1); - } -} - - -void addOperation(tDigit *digits, tDigitPos pos, tDigitPos maxPos, tDigit toAdd) -{ - if (toAdd == 0) - return; - - if (pos >= maxPos) - return; - - digits[pos]+=toAdd; - while (digits[pos] > 9) { - digits[pos]-=10; - addOperation(digits, pos+1, maxPos, 1); - } -} - - -void crank(bool isSubtract) -{ - tDigitPos pos; - if (isSubtract) { - subOperation(counter, resultPos, NUM_COUNTER_DIGITS, 1); - for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { - subOperation(result, resultPos+pos, NUM_RESULT_DIGITS, operand[pos]); - } - } else { - addOperation(counter, resultPos, NUM_COUNTER_DIGITS, 1); - for (pos = 0; pos < NUM_OPERAND_DIGITS; pos++) { - addOperation(result, resultPos+pos, NUM_RESULT_DIGITS, operand[pos]); - } - } -} - - -void printDigits(char *label, tDigit *digits, tDigitPos maxPos) +static void printDigits(char *label, tDigit *digits, tDigitPos maxPos) { tDigitPos pos; @@ -229,33 +82,31 @@ void printDigits(char *label, tDigit *digits, tDigitPos maxPos) } -void printState(void) +static void printState(void) { tDigitPos pos; printDigits("Counter", counter, NUM_COUNTER_DIGITS); printDigits("Result", result, NUM_RESULT_DIGITS); printf(" "); - for(pos = 0; pos < NUM_RESULT_DIGITS - resultPos; pos++) { + for(pos = 0; pos < NUM_RESULT_DIGITS - basePos; pos++) { printf(" "); } printf(" ^\n"); } -void drawOperand(tDigitPos pos) +static void drawOperand(tDigitPos pos) { char xPos; char buffer[2]; tDigit digit; - if (pos < 0) - return; - if (pos >= NUM_OPERAND_DIGITS) + if (!IS_VALID_OPERAND_POS(pos)) return; xPos = SLIDER_X_BORDER + (SLIDER_BAR_SPACING * (NUM_OPERAND_DIGITS - pos - 1)); - digit = operand[pos]; + digit = GET_OPERAND_DIGIT(pos); // Clear old bar tgi_setcolor(COLOR_BLACK); @@ -288,7 +139,7 @@ void drawOperand(tDigitPos pos) } -tJoyPos getJoyPos(char joyState) +static tJoyPos getJoyPos(char joyState) { if (JOY_BTN_UP(joyState)) { if (JOY_BTN_LEFT(joyState)) { @@ -318,7 +169,7 @@ tJoyPos getJoyPos(char joyState) } -tAction getNextAction(void) +static tAction getNextAction(void) { static bool firstCall = true; static char oldJoyState; @@ -448,11 +299,13 @@ tAction getNextAction(void) } -void graphicalInterface(void) +void initUI(void) { // Install drivers tDigitPos pos; + initDevice(drawOperand); + joy_install(&a2e_stdjoy); tgi_install(&a2e_hi); @@ -466,66 +319,69 @@ void graphicalInterface(void) asm ("STA %w", 0xc053); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printState(); +} - while (true) { - if ((kbhit()) && - (cgetc() == ' ')) { - break; - } - switch (getNextAction()) { - case ACTION_NULL: - break; - case ACTION_OPERAND_SHIFT_LEFT: - shiftOperandPos(true); - break; - case ACTION_OPERAND_SHIFT_RIGHT: - shiftOperandPos(false); - break; +bool processNextEvent(void) +{ + bool timeToQuit = false; - case ACTION_OPERAND_INC: - incOperandPos(selectedOperand); - break; - - case ACTION_OPERAND_DEC: - decOperandPos(selectedOperand); - break; - - case ACTION_RESULT_SHIFT_LEFT: - shiftResultPos(true); - printState(); - break; - - case ACTION_RESULT_SHIFT_RIGHT: - shiftResultPos(false); - printState(); - break; - - case ACTION_ADD: - crank(false); - printState(); - break; - - case ACTION_SUBTRACT: - crank(true); - printState(); - break; - - case ACTION_CLEAR: - clearDevice(); - printState(); - break; - } + // Exit on ESC + if ((kbhit()) && + (cgetc() == 27)) { + timeToQuit = true; } - + switch (getNextAction()) { + case ACTION_NULL: + break; + case ACTION_OPERAND_SHIFT_LEFT: + shiftOperandPos(true); + break; + + case ACTION_OPERAND_SHIFT_RIGHT: + shiftOperandPos(false); + break; + + case ACTION_OPERAND_INC: + incOperandPos(selectedOperand); + break; + + case ACTION_OPERAND_DEC: + decOperandPos(selectedOperand); + break; + + case ACTION_RESULT_SHIFT_LEFT: + shiftResultPos(true); + printState(); + break; + + case ACTION_RESULT_SHIFT_RIGHT: + shiftResultPos(false); + printState(); + break; + + case ACTION_ADD: + crank(false); + printState(); + break; + + case ACTION_SUBTRACT: + crank(true); + printState(); + break; + + case ACTION_CLEAR: + clearDevice(); + printState(); + break; + } + return timeToQuit; +} + + +void shutdownUI(void) +{ // Uninstall drivers tgi_uninstall(); joy_uninstall(); } - - -int main(void) -{ - graphicalInterface(); - return 0; -} diff --git a/curtaUI.h b/curtaUI.h new file mode 100644 index 0000000..06212f5 --- /dev/null +++ b/curtaUI.h @@ -0,0 +1,18 @@ +// +// Author: Jeremy Rand +// Date: July 20, 2012 +// +// This is the interface for the Curta emulator UI. +// + +#include + + +#ifndef _CURTAUI_H +#define _CURTAUI_H + +extern void initUI(void); +extern void shutdownUI(void); +extern bool processNextEvent(void); + +#endif