********************************************************************************
* Name:         David DiPaola
*
* File:         program2.asm
*
* Due Date:     4/12/2009
*
* Description: This program prompts the user for decimal integers, stopping
*           when the user presses the return key without entering data.
*           As the user enters values, this program will check the characters
*           and convert them into decimal numbers. If the user enters a value
*           that is larger than two bytes, the program will put out an error.
*           It will also put out an error if the sum of all entered numbers
*           is larger than two bytes. If the user enters values properly,
*           this program will print the sum of all entered numbers.
*
* Input:	     The user enters integers via a text prompt displayed in a
*           serial terminal. The value is checked to determine if it can be
*           represented in two bytes, if it cannot, an error is passed to
*           the user who must then enter in a new value.
*
*              The total for all values is also checked in a similar manner.
*           Once the running total becomes too large to store in two bytes,
*           the user is asked to re-enter the last value after an error
*           notifies tham that the total value is invalid.
*
*           (Note: negative numbers are not allowed, and use of a hyphen or
*           the minus sign will result in an error in this program)
*
* Output:      The result of the summation is displayed for the user in the
*           serial terminal readout.
*
* Errors:      There are three possible errors:
*
*              If the user enters a number which cannot be represented in two
*           bytes, they will be given an error, the erroneous value will be
*           thrown away, and the user will be asked to enter a number.
*
*              If the user enters numbers whose total cannot be represented in
*           two bytes, then an error will be displayed to the user, the
*           last entered value will be thrown away, and the user will be
*           asked to enter a number.
*
*              If the user types a non-numerical character into the terminal,
*           then an error will be displayed and the user will be given
*           another prompt for a number.
********************************************************************************

********** Equates *************************
ZERO     EQU  $00          ;ZERO is a symbol for $00
ZEROZERO EQU  $0000        ;A word of zeros
TEN_W    EQU  $000A        ;TEN_W is a symbol for 0010
GETCHAR  EQU  $EE84        ;This is where we jump to to get to GETCHAR
PUTCHAR  EQU  $EE86        ;This is where we jump to to get to PUTCHAR
PRINTF   EQU  $EE88        ;This is where we jump to to get to PRINTF
CR       EQU  $000D        ;Carraige return
LF       EQU  $000A        ;Line feed
U_BOUND  EQU  $39          ;ASCII for 9
L_BOUND  EQU  $30          ;ASCII for 0
H_TO_D   EQU  $30          ;Hex to decimal

********** Variable Declarations ***********
         ORG  $2000

temp     DB   $00          ;Temporary variable to store B
value    DW   $0000        ;The running total digit value

;These are our prompt strings
prompt   DB   CR,LF,"Enter a number: ",0
bg_err   DB   CR,LF,"***Error: Number cannot be stored using 2 bytes***",0
ic_err   DB   CR,LF,"***Error: Invalid Character***",0
ow_err   DB   CR,LF,"***Error:  Total cannot be stored using 2 bytes***",0
total    DB   CR,LF,"Total = %u",CR,LF,0

sum      DW   $0000        ;The total of all entered values

********** Main ****************************
         ORG  $3000        ;Starting address

********************************************
* ASK
*
* This routine prints the prompt, and
* proceeds to taking character input.
********************************************
ASK      LDD  #prompt      ;Load the text address into D
         JSR  [PRINTF,PCR] ;Jump to PRINTF

         LDD  #ZEROZERO    ;Clear out D
         STD  value        ;Clear out value

********************************************
* KEEP_ASK
*
* This routine gets characters from the
* serial line and displays them. It also
* checks for invalid characters and
* overflows. It also adds the characters
* together to accurately represent the
* value being typed on-screen.
********************************************
KEEP_ASK LDX  GETCHAR      ;Load the address into X
         JSR  0,X          ;Jump to what X points to
         ;We've now gotten an ASCII charater, and stored it to B

         LDX  PUTCHAR      ;Load the address into X
         JSR  0,X          ;Jump to what X points to
         ;We've pushed that same character out the serial port

         CMPB #CR          ;Did the user press enter?
         BEQ  ENTER        ;Jump to the appropriate area

         CMPB #U_BOUND     ;Compare B to the upper bound
         BGT  ER_INCHR     ;B > 9, invalid character
         CMPB #L_BOUND     ;Compare B to the lower bound
         BLT  ER_INCHR     ;B < 0, invalid character

         SUBB #H_TO_D      ;Convert B to decimal
         STAB temp         ;Store B to temp

         LDD  value        ;Load the current number value into D
         LDY  #TEN_W       ;Set Y to the multiple
         EMUL              ;Multiply D and Y
         CPY  #ZEROZERO    ;If Y holds a remainder, we've overflow(ed/n)
         BNE  ER_TOBIG     ;If we do have an overflow situation, errorize
         ADDB temp         ;Add the new value to the total
         BCS  ER_TOBIG     ;If the ADD created a value that's too big...         

         STD  value        ;Stores the total to value

         BRA  KEEP_ASK     ;Grab more characters

********************************************
* ER_INCHR
*
* This routine prints an error message
* telling the user that they've entered
* an invalid character.
********************************************
ER_INCHR LDD  #ic_err      ;Load the text address into D
         JSR  [PRINTF,PCR] ;Jump to PRINTF
         BRA  ASK

********************************************
* ER_TOBIG
*
* This routine prints an error message
* telling the user that they've entered
* a value that's too big to represent using
* two bytes (one word).
********************************************
ER_TOBIG LDD  #bg_err      ;Load the "too big" error
         JSR  [PRINTF,PCR] ;Jump to PRINTF
         BRA  ASK          ;Ask the user for a new number

********************************************
* ER_OVRFW
*
* This routine prints an error message
* telling the user that the total value of
* the numbers they've entered exceeds
* what can be represented in two bytes
* (one word). It then discards the most
* recently entered value and asks the user
* for a new value.
********************************************
ER_OVRFW LDD  #ow_err      ;Load the overflow error
         JSR  [PRINTF,PCR] ;Jump to PRINTF
         BRA  ASK          ;Ask the user for a new number

********************************************
* DONE
*
* This routine ends the program with a
* software interrupt.
********************************************
DONE     SWI               ;End the program

********************************************
* ENTER
*
* When the user presses enter, this routine
* will sum the new value with the running
* total, and check if it's too big.
********************************************
ENTER    LDD  value        ;Load the current value into D

         CPD  #ZEROZERO    ;Has the user enetered nothing?
         BEQ  RESULT       ;If so, print the total

         ADDD sum          ;Add D to the sum
         STD  sum          ;Store the sum in sum
         
         LDD  value        ;Load the current value back into D
         CPD  sum          ;If sum overflows, it'll be less than D
         BGT  ER_OVRFW     ;If sum has, go to the appropriate error
         
         BRA  ASK          ;Ask the user for the next value

********************************************
* RESULT
*
* This routine prints the message telling
* the user the total sum of all entered
* values.
********************************************         
RESULT   LDD  sum          ;Load sum to be pushed
         PSHD              ;Push sum to the stack
         LDD  #total       ;Load the reuslt string to be pushed
         JSR  [PRINTF,PCR] ;Jump to PRINTF

         BRA DONE          ;End the program