summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2025-03-24 21:47:56 -0400
committerJacob McDonnell <jacob@jacobmcdonnell.com>2025-03-24 21:47:56 -0400
commit6a3a34e795b745d9d488e72035b1f7ba4df6c93f (patch)
treea38440939a99f11c509f9c2222bae649d4f1361e
parent2e6e3a5d5696591b66d09939e83149b6496e02a0 (diff)
HW 8: Finished
-rw-r--r--cmpen472_hw8McDonnell/Sources/cmpen472hw8_McDonnell.asm764
-rw-r--r--cmpen472_hw8McDonnell/Sources/main.asm54
-rw-r--r--cmpen472_hw8McDonnell/bin/Project.absbin7972 -> 8176 bytes
-rw-r--r--cmpen472_hw8McDonnell/bin/Project.abs.s1968
-rw-r--r--cmpen472_hw8McDonnell/bin/main.dbg120
-rw-r--r--cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.obin7972 -> 8176 bytes
-rw-r--r--cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.sx68
-rw-r--r--cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/TargetDataWindows.tdtbin65029 -> 65147 bytes
8 files changed, 977 insertions, 97 deletions
diff --git a/cmpen472_hw8McDonnell/Sources/cmpen472hw8_McDonnell.asm b/cmpen472_hw8McDonnell/Sources/cmpen472hw8_McDonnell.asm
new file mode 100644
index 0000000..cbfe22a
--- /dev/null
+++ b/cmpen472_hw8McDonnell/Sources/cmpen472hw8_McDonnell.asm
@@ -0,0 +1,764 @@
+**************************************************************************
+*
+* Title: Calculator
+*
+* Objective: CMPEN 472 Homework 8
+*
+* Revision: V1.0
+*
+* Date: Mar. 24, 2025
+*
+* Programmer: Jacob McDonnell
+*
+* Company: The Pennsylvania State University
+* Department of Computer Science and Engineering
+*
+* Algorithm: Simple Serial I/O, Real Time Interrupts for Time Tracking
+*
+* Register Use: A & B to current byte, etc,
+* X & Y holds address of strings and length of string,
+* D to hold data for printing, reading, and updating time.
+*
+* Memory Use: RAM Locations from $3000 for data,
+* RAM Locations from $3100 for program
+*
+* Input: Serial Port for User Input
+*
+* Output: Serial Port for String Output
+*
+* Observation: The HC12 will output the time and a command prompt every second.
+* The user can input commands and the program will output a response
+* based on the input.
+*
+* Note: ON CSM-12C128 board,
+*
+* Comments: This program is developed and simulated using CodeWarrior
+* development software and targeted for Axion
+* Manufacturing's CSM-12C128 board running at 24MHz.
+*
+**************************************************************************
+* Parameter Declearation Section
+*
+* Export Symbols
+ xdef pgstart ; export 'pgstart' symbol
+ absentry pgstart ; for assembly entry point
+
+* Symbols and Macros
+PORTA equ $0000 ; i/o port A addresses
+DDRA equ $0002 ; data direction register for PORTA
+PORTB equ $0001 ; i/o port B addresses
+DDRB equ $0003 ; data direction register for PORTB
+
+SCIBDH equ $00C8 ; Serial port (SCI) Baud Register H
+SCIBDL equ $00C9 ; Serial port (SCI) Baud Register L
+SCICR2 equ $00CB ; Serial port (SCI) Control Register 2
+SCISR1 equ $00CC ; Serial port (SCI) Status Register 1
+SCIDRL equ $00CF ; Serial port (SCI) Data Register
+
+CRGFLG EQU $0037 ; Clock and Reset Generator Flags
+CRGINT EQU $0038 ; Clock and Reset Generator Interrupts
+RTICTL EQU $003B ; Real Time Interrupt Control
+
+CR equ $0d ; carriage return, ASCII 'Return' key
+LF equ $0a ; line feed, ASCII 'next line' character
+NULL equ $00 ; NULL Terminator character
+
+**************************************************************************
+* Data Section: address used [ $3000 to $30FF ] RAM Memory
+*
+ org $3000 ; Reserved RAM memory starting address
+ ; for Data for CMPEN 472 class
+buffer ds.b $0010 ; Array of 16 bytes to read a string
+ dc.b NULL ; NULL terminated
+lenBuf dc.w $0010 ; Length of buffer array
+
+buffer2 ds.b $0010 ; Array of 16 bytes for reading and reversal
+ dc.b NULL ; NULL terminated
+lenBuf2 dc.w $0010 ; length of buffer2
+
+hours dc.w $0000 ; Buffer to hold the hours of the time
+
+minutes dc.w $0000 ; Buffer to hold the minutes of the time
+
+seconds dc.w $0000 ; Buffer to hold the seconds of the time
+
+counter dc.w $0000 ; Counter for RTI ISR for 1 second
+
+numBuf dc.b $0000 ; Used by ReadDecimal for reading numbers
+
+operator dc.b $0000 ; Used by ReadDecimal for reading numbers
+
+inputBuffer ds.b $0010 ; Input Buffer Length
+
+lenInput dc.w $0010 ; Length of the Input Buffer
+
+outputBuf dc.b 'h' ; Used to control what to output on 7 segment display
+
+*
+* There is a section Data Section at the end of the file
+**************************************************************************
+* RTI Vector Section: address used [ $FFF0 to $FFF1 ] RAM Memory
+*
+ org $FFF0 ; Memory location for RTI interrupt vector section for simulator
+ dc.w rtiisr ; Real Time Interrupt vector
+*
+**************************************************************************
+* Program Section: address used [ $3100 to $3FFF ] RAM Memory
+*
+ org $3100 ; Program start address, in RAM
+pgstart lds #$3100 ; initialize the stack pointer
+
+ ldaa #%11110001 ; LED 1,2,3,4 at PORTB bit 4,5,6,7
+ staa DDRB ; set PORTB bit 4,5,6,7 as output
+
+ ldaa #$0C ; Enable SCI port Tx and Rx units
+ staa SCICR2 ; disable SCI interrupts
+
+ ldd #$0001 ; Set SCI Baud Register = $0001 => 1.5M baud at 24MHz (for simulation)
+ std SCIBDH ; SCI port baud rate change
+
+ ldx #msg ; Load the address of the welcome message into X
+ jsr WriteString ; Write the string to the serial console
+
+ bset RTICTL,%00011001; set RTI: dev=10*(2**10)=2.555msec for C128 board
+ ; 4MHz quartz oscillator clock
+ bset CRGINT,%10000000; enable RTI interrupt
+ bset CRGFLG,%10000000; clear RTI IF (Interrupt Flag)
+
+ ldaa #$FF ; Two 7 segment displays on PORTB
+ staa DDRB ; Set all of PORTB as output
+
+ ldx #inputBuffer ; Load the address of inputBuffer into X
+ ldy lenInput ; Load the length of inputBuffer into Y
+ jsr Zeros ; Zero out inputBuffer
+ cli ; Enable interrupts
+ jsr PrintTime ; Jump to PrintTime to write to serial console
+mainLoop
+ ldx #inputBuffer ; Load the address of inputBuffer into X
+ ldy lenInput ; Load the length of inputBuffer into Y
+ jsr ReadString ; Jump to ReadString to read input
+
+ ldx #inputBuffer ; Load the address of inputBuffer into X
+ jsr ExecuteCommand ; Jump to ExecuteCommand
+
+ ldx #inputBuffer ; Load the address of inputBuffer into X
+ ldy lenInput ; Load the length of inputBuffer into Y
+ jsr Zeros ; Zero out inputBuffer
+
+ sei ; Disable interrupts
+ jsr PrintTime ; Jump to PrintTime to print new time
+ cli ; Enable interrupts
+
+ bra mainLoop ; Loop back to mainLoop always
+
+TypeWrite
+ sei ; Disable Interrupts
+ bclr CRGINT,%10000000; Disable RTI interrupt
+ ldx #twMsg ; Load the address of twMsg into X
+ jsr WriteString ; Write the string to the serial console
+twLoop jsr getchar ; Read a character from the serial console
+ tsta ; Compare A to 0
+ beq twLoop ; If A == 0, branch to twLoop
+ staa PORTB ; Write A to PORTB
+ jsr putchar ; Write character to serial console
+ bra twLoop ; Branch always to twLoop
+
+**************************************************************************
+* Subroutine Section: address used [ $3100 to $3FFF ] RAM Memory
+*
+
+;*************************************************************************
+; rtiisr subroutine
+;
+; This subroutine will increment the counter, seconds, minutes, & hours counters
+; to track the time. This subroutine will be called ~400 times a second.
+;
+; Input: No input other than the timer to call the isr.
+; Output: The counter, seconds, minutes, & hours buffers will
+; be updated to track the time, the time & prompt will be
+; printed every second.
+; Registers in use: X for adding to the counter, seconds, minutes, & hours buffers.
+; Memory locations in use: Memory Address for serial line, Memory addresses for RTIISR control,
+; Buffer words for counters, seconds, minutes, & hours buffers.
+;
+; Comments: The counter buffer should be compared to 400, but for the simulator,
+; the counter is compared to 200 to better simulate 1 second on my computer.
+;
+
+rtiisr bset CRGFLG,%10000000; Clear RTI Interrupt Flag
+ ldx counter ; Load counter into X
+ inx ; Increment counter by 1
+ stx counter ; Save X to counter
+ cpx #200 ; Compare counter to 200, This is about 1 second on my computer
+ bne rtiSkip ; If counter != 200, branch to rtiSkip
+ ldx #0 ; Load 0 into X
+ stx counter ; Save X to counter
+ ldx seconds ; Load the seconds into X
+ inx ; Increment the seconds by 1
+ stx seconds ; Save the new seconds to the location
+ cpx #60 ; Compare X to 60
+ bne rtidone ; If X != 60, exit isr
+ ldx #0 ; Reset the seconds
+ stx seconds ; Save the new seconds to the location
+ ldx minutes ; load the minutes into X
+ inx ; Increment the minutes by 1
+ stx minutes ; Save the updated minutes
+ cpx #60 ; Compare the minutes to 60
+ bne rtidone ; If X != 60, exit isr
+ ldx #0 ; Reset the minutes
+ stx minutes ; Save the updated minutes
+ ldx hours ; Load the hours into X
+ inx ; Increment the hours by 1
+ stx hours ; Save the updated hours
+ cpx #24 ; Compare the hours to 24
+ bne rtidone ; If X != 24, exit the isr
+ ldx #0 ; Reset the hours
+ stx hours ; Save the updated hours
+rtidone jsr PrintTime ; Jump to PrintTime
+rtiSkip RTI ; Return from RTI ISR
+
+;*************************************************************************
+; PrintTime subroutine
+;
+; This subroutine will print the time, command prompt, and maybe an error prompt.
+;
+; Input: No input.
+; Output: The time prompt, time, command prompt, the current input,
+; and/or an error on the serial console.
+; Registers in use: A for the characters to print, X for buffer addresses,
+; Y for buffer lengths, D for the seconds/minutes/hours for calling TimeOnPortB
+; Memory locations in use: Memory Address for serial line, Buffer words for counters,
+; seconds, minutes, & hours buffers, and buffer to print time,
+; outputBuf for tracking what to output on PORTB.
+;
+; Comments: This subroutine requires TimeOnPortB subroutine and to be setup. The subroutine
+; will print the current user input if its not finished.
+;
+
+PrintTime
+ pshd ; Save D to the stack
+ pshy ; Save Y to the stack
+ pshx ; Save X to the stack
+ ldaa #CR ; Load the character CR into A
+ jsr putchar ; Write the character to the serial
+ ldaa #LF ; Load the character LF into A
+ jsr putchar ; Write the character to the serial
+ ldx #clock ; Load the address of the clock prompt into X
+ jsr WriteString ; Write the string to serial
+ ldd hours ; Load the hours into D
+ cpd #10 ; Compare D to 10
+ bhs goodHours ; If D >= goodHours
+ psha ; Save A to the stack
+ ldaa #'0' ; Load '0' character into A
+ jsr putchar ; Print '0' to the serial
+ pula ; Restore A from the stack
+goodHours ldy #buffer ; Load the address of buffer into Y
+ jsr PrintDecimalWord; Print the number to the serial
+ ldaa #':' ; Load the character ':' into A
+ jsr putchar ; Write the character to the serial
+ ldd minutes ; Load the minutes into D
+ cpd #10 ; Compare D to 10
+ bhs goodMins ; If D >= goodMins
+ psha ; Save A to the stack
+ ldaa #'0' ; Load '0' character into A
+ jsr putchar ; Print '0' to the serial
+ pula ; Restore A from the stack
+goodMins ldy #buffer ; Load the address of buffer into Y
+ jsr PrintDecimalWord; Print the number to the serial
+ ldaa #':' ; Load the character ':' into A
+ jsr putchar ; Write the character to the serial
+ ldd seconds ; Load the seconds into D
+ cpd #10 ; Compare D to 10
+ bhs goodSecs ; If D >= goodSecs
+ psha ; Save A to the stack
+ ldaa #'0' ; Load '0' character into A
+ jsr putchar ; Print '0' to the serial
+ pula ; Restore A from the stack
+goodSecs ldy #buffer ; Load the address of buffer into Y
+ jsr PrintDecimalWord; Print the number to the serial
+ ldaa #' ' ; Load ' ' character into A
+ jsr putchar ; Write the character to the serial console
+ jsr putchar ; Write the character to the serial console
+ jsr putchar ; Write the character to the serial console
+ jsr putchar ; Write the character to the serial console
+ ldx #CMD ; Load the address of CMD into X
+ jsr WriteString ; Write the string to the serial
+ ldx #inputBuffer ; Load the address of the inputBuffer into X
+ jsr WriteString ; Write the string to the serial
+ ldaa outputBuf ; Load outputBuf into A
+ cmpa #'h' ; Compare A to 'h'
+ bne pTimeIsM ; If A != 'h', branch to pTimeIsM
+ ldd hours ; Load hours into B
+ bra skipRest ; Jump to skipRest
+pTimeIsM cmpa #'m' ; Compare A to 'm'
+ bne pTimeIsS ; If A != 'm', branch to pTimeIsS
+ ldd minutes ; Load Minutes into D
+ bra skipRest ; Jump to skipRest
+pTimeIsS ldd seconds ; Load seconds into D
+skipRest jsr TimeOnPortB ; Call TimeOnPortB to output time
+ pulx ; Restore X from the stack
+ puly ; Restore Y from the stack
+ puld ; Restore D from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; TimeOnPortB subroutine
+;
+; This subroutine will output the time given on on PORTB for two seven segment displays.
+;
+; Input: Two Digit Decimal number in register D.
+; Output: The given two digit decimal number on PORTB for two 7 segment displays.
+; Registers in use: D for the input, and for math to split the digits, X for math to split digits.
+; Memory locations in use: PORTB memory location.
+;
+; Comments: This subroutine will only work with two digit decimal numbers, and one digit decimal
+; numbers (leading zeros will be added).
+;
+
+TimeOnPortB
+ pshd ; Save D to the stack
+ pshx ; Save X to the stack
+ ldx #10 ; Load 10 into X to get digit
+ idiv ; Divide D by X and save Digit into D
+ pshb ; Save B to the stack (Lower Byte of D)
+ exg x,d ; Swap X and D
+ ldx #10 ; Load 10 into X to get digit
+ lslb ; Shift B left by 1
+ lslb ; Shift B left by 1
+ lslb ; Shift B left by 1
+ lslb ; Shift B left by 1
+ orab 1,sp+ ; Or B with Digit on stack
+ stab PORTB ; Save B to PORTB
+ pulx ; Restore X from the stack
+ puld ; Restore D from the stack
+ rts ; Return from caller
+
+;*************************************************************************
+; ExecuteCommand subroutine
+;
+; This subroutine will parse user input and execute the proper command or error out.
+;
+; Input: An address of a NULL terminated string in X.
+; Output: The output of the proper command or an error message.
+; Registers in use: X for the address of the user input, A for individual characters,
+; D & Y for numbers read from user input.
+; Memory locations in use: Serial console memory locations.
+;
+; Comments: This subroutine will disable interrupts while setting the time and will
+; reenable them after setting the time.
+;
+
+ExecuteCommand
+ pshd ; Save D to the stack
+ pshy ; Save Y to the stack
+ ldaa 1,x+ ; Load the character from X into A
+ lbeq ecDone ; If A == 0, jump to ecDone
+ cmpa #'t' ; Compare A to 't'
+ bne isH ; If A != 't', branch to isH
+skipSpaces ldaa 1,+x ; Load the next character into X
+ cmpa #' ' ; Compare A to ' ' character
+ beq skipSpaces ; If A == ' ', loop to skipSpaces
+ sei ; Disable interrupts
+ ldd hours ; Load hours into D
+ pshd ; Save hours to the stack
+ jsr ReadDecimal ; Read Hour number
+ exg y,d ; Exchange Y and D
+ cpd #24 ; Compare D to 24
+ lbhs badHours ; If D >= 24, badHours
+ cpd #0 ; Compare D to 0
+ lblt badHours ; If D < 0, badHours
+ std hours ; Save D to hours
+ ldaa -1,x ; Load the next character into A
+ cmpa #':' ; Compare A to ':'
+ lbne badHours ; If A != ':', badHours
+ ldd minutes ; Load minutes into D
+ pshd ; Save minutes to the stack
+ jsr ReadDecimal ; Read minute number
+ exg y,d ; Exchange Y and D
+ cpd #60 ; Compare D to 60
+ bhs badMinutes ; If D >= 60, badMinutes
+ cpd #0 ; Compare D to 0
+ blt badMinutes ; If D < 0, badMinutes
+ std minutes ; Save D to minutes
+ ldaa -1,x ; Load the next character into A
+ cmpa #':' ; Compare A to ':'
+ bne badMinutes ; If A != ':', badMinutes
+ ldd seconds ; Load seconds into D
+ pshd ; Save seconds to the stack
+ jsr ReadDecimal ; Read second number
+ exg y,d ; Exchange Y and D
+ cpd #60 ; Compare D to 60
+ bhs badSeconds ; If D >= 60, badSeconds
+ cpd #0 ; Compare D to 0
+ blt badSeconds ; If D < 0, badSeconds
+ std seconds ; Save D to seconds
+ ldaa -1,x ; Load the next character into A
+ cmpa #NULL ; Compare A to NULL
+ bne badSeconds ; If A != ':', badSeconds
+ clra ; Set A to 0
+ staa counter ; Clear Counter
+ cli ; Enable interrupts
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
+ bra ecDone ; Branch to ecDone
+isH cmpa #'h' ; Compare A to 'h'
+ bne isM ; If A != 'h', branch to isM
+ ldab 1,x+ ; Load next character into B
+ cmpb #NULL ; Compare B to NULL
+ bne badCommand ; If B != CR, bad command
+ staa outputBuf ; Store A into outputBuf
+ bra ecDone ; Branch to ecDone
+isM cmpa #'m' ; Compare A to 'm'
+ bne isS ; If A != 'm', branch to isS
+ ldab 1,x+ ; Load next character into B
+ cmpb #NULL ; Compare B to NULL
+ bne badCommand ; If B != CR, bad command
+ staa outputBuf ; Store A into outputBuf
+ bra ecDone ; Branch to ecDone
+isS cmpa #'s' ; Compare A to 's'
+ bne isQ ; If A != 's', branch to isQ
+ ldab 1,x+ ; Load next character into B
+ cmpb #NULL ; Compare B to NULL
+ bne badCommand ; If B != CR, bad command
+ staa outputBuf ; Store A into outputBuf
+ bra ecDone ; Branch to ecDone
+isQ cmpa #'q' ; Compare A to 'q'
+ bne badCommand ; If A != 'q', branch to badCommand
+ ldab 1,x+ ; Load next character into B
+ cmpb #NULL ; Compare B to NULL
+ bne badCommand ; If B != NULL, branch to ecDone
+ jmp TypeWrite ; Jump to TypeWrite
+badSeconds puld ; Restore Seconds from the stack
+ std seconds ; Restore seconds before change
+badMinutes puld ; Restore minutes from the stack
+ std minutes ; Restore minutes before change
+badHours puld ; Restore hours from the stack
+ std hours ; Restore hours before change
+ cli ; Reenable interrupts
+badCommand pshx ; Save X to the stack
+ ldaa #' ' ; Load Space character into A
+ jsr putchar ; Jump to putchar to write space character
+ jsr putchar ; Jump to putchar to write space character
+ jsr putchar ; Jump to putchar to write space character
+ jsr putchar ; Jump to putchar to write space character
+ ldx #error ; Load the address of the error prompt into X
+ jsr WriteString ; Jump to WriteString
+ ldx #badInput ; Load the address of badInput into X
+ jsr WriteString ; Jump to WriteString
+ pulx ; Restore X from the stack
+ecDone puly ; Restore Y from the stack
+ puld ; Restore D from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; ReadDecimal subroutine
+;
+; This subroutine will read an ASCII string of a number in decimal and convert it to
+; its value.
+;
+; Input: A memory address in register X.
+; Output: The value of the number in the Y register, and any errors printed
+; to the serial line. Zero bit is set if error occurs.
+; Registers in use: X for the address of the contents and for a buffer while printing,
+; D for multiplication, B for the character, Y for output value.
+; Memory locations in use: Memory Address for serial line, address of the string
+;
+; Comments: This subroutine will return the value in the Y register, and if an error occurs,
+; the Zero bit in the CCR will be set.
+;
+
+ReadDecimal
+ pshd ; Save D to the stack
+ ldy #0 ; Clear Y register
+dHLoop ldab 1,x+ ; Read Next character from X
+ beq dHDone ; If B == 0, exit loop
+ cmpb #'+' ; Compare B to '+'
+ beq dHDone ; If B == '+', end of number
+ cmpb #'-' ; Compare B to '-'
+ beq dHDone ; If B == '-', end of number
+ cmpb #'*' ; Compare B to '*'
+ beq dHDone ; If B == '+', end of number
+ cmpb #'/' ; Compare B to '/'
+ beq dHDone ; If B == '-', end of number
+ cmpb #':' ; Compare B to ':'
+ beq dHDone ; If B == '-', end of number
+ cmpb #' ' ; Compare B to space character
+ beq dHDone ; If B == ' ', exit loop
+ cmpb #'0' ; Compare B to '0' character
+ blt dHError ; If B < '0', bad address, exit loop
+ cmpb #'9' ; Compare B to '9' character
+ bhi dHError ; If B > '9', check if 'A'-'F' characters
+ subb #'0' ; Subtract '0' from B to get true value
+ pshb ; Save B to the stack
+ ldd #10 ; load 10 into D
+ emul ; Multiply Y and D
+ exg d,y ; Transfer data from D to Y
+ pulb ; Restore b from the stack
+ aby ; Add B to Y
+ bra dHLoop ; Branch always to rHLoop
+dHDone clra ; clear A accumulator
+ tap ; Transfer A into CCR to clear zero bit
+ puld ; Restore D from the stack
+ rts ; Return to caller
+dHError ldaa #4 ; Load 4 into A to set zero bit in CCR
+ tap ; Transfer A into CCR to set zero bit and warn error
+ puld ; Restore D from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; strrev subroutine
+;
+; This subroutine will reverse a string from one buffer into another.
+;
+; Input: Address of null terminated string in X, address of a large enough
+; buffer in Y.
+; Output: The string in X reversed in Y.
+; Registers in use: X for the address of the string, Y for the address of the buffer,
+; A to read characters from the string.
+; Memory locations in use: Memory Address for serial line, address of the string & buffer
+;
+; Comments: This subroutine will not check that the output buffer is large enough, that
+; is the job of the caller.
+;
+
+strrev
+ pshx ; Save X to the stack
+ pshy ; Save Y to the stack
+ psha ; Save A to the stack
+revLoop ldaa 1,y- ; Load Character from Y into A, decrement Y
+ beq revDone ; If Character is 0, exit loop
+ staa 1,x+ ; Save character in address in X, increment X
+ bra revLoop ; Loop back always
+ clra ; Set A to Zero
+revDone staa 1,x+ ; Copy Null terminator into new string
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ pulx ; Restore X from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; PrintDecimalWord subroutine
+;
+; This subroutine will print a given word of data to the serial in binary.
+;
+; Input: 1 word of data in register D, Buffer Address in Y
+; Output: Decimal representation of the data on the serial console
+; Registers in use: Y for the address of the buffer, X to count the number of bits
+; written and for division, D for the input, A for characters.
+; Memory locations in use: Memory addresses for serial, and operator to hold sign
+;
+; Comments: This subroutine requires serial to be setup and putchar subroutine.
+;
+
+PrintDecimalWord
+ pshx ; Save X to the stack
+ pshy ; Save Y to the stack
+ pshd ; Save D (A:B) to the stack
+ cpd #0 ; Compare D to zero
+ beq dIsZero ; Branch to hIsZero
+ blt dIsNegative ; If D < 0, Jump to dIsNegative
+dAfterNeg psha ; Save A to the stack
+ pshy ; Save Y to the stack
+ pshx ; Save x to the stack
+ ldaa #'0' ; Load the '0' character into A
+ ldx #buffer2 ; Load the address of buffer2 into X
+ ldy #5 ; Load 5 into Y
+ jsr memset ; Write '0' to the first 5 bytes in buffer2
+ pulx ; Restore X from the stack
+ puly ; Restore Y from the stack
+ clra ; Set A to zero
+ staa 0,y ; Load Zero into Y for Null Terminator
+ pula ; Restore A from the stack
+dPrintLoop ldx #10 ; Load 10 in X for division
+ idiv ; Divide D / 10 to get Hex Digit
+ cpx #0 ; Compare X to 0
+ beq dCheck ; If X == 0, branch to check D is zero
+dDNotZero addb #'0' ; Add '0' to B to get ASCII Character
+ stab 1,+y ; Save character from B to Y
+ exg X,D ; Swap values in X and D
+ bra dPrintLoop ; Loop to hPrintLoop
+dCheck cpd #0 ; Compare D to 0
+ bne dDNotZero ; If D != 0, branch back to hDNotZero
+dPrintDone ldaa operator ; Load operator into A to see if negative
+ cmpa #'-' ; Compare A to '-'
+ bne dNotNeg ; If A != '-', jump to dNotNeg
+ staa 1,+y ; Save '-' into buffer
+dNotNeg ldx #buffer2 ; Load the address of buffer2 in X
+ jsr strrev ; Reverse string in Y in buffer in X
+ jsr WriteString ; Jump to write string to write the number
+ ldy lenBuf2 ; Load the length of buffer2 into Y
+ ldx #buffer2 ; Load the address of buffer2 into X
+ jsr Zeros ; Fill buffer2 with zeros
+ puld ; Restore D (A:B) from the stack
+ puly ; Restore Y from the stack
+ pulx ; Restore X from the stack
+ rts ; Return to caller
+dIsZero ldaa #'0' ; Load '0' character into A
+ jsr putchar ; Print character to the screen
+ puld ; Restore D (A:B) from the stack
+ puly ; Restore Y from the stack
+ pulx ; Restore X from the stack
+ rts ; Return to caller
+dIsNegative psha ; Save A to the stack
+ ldaa #'-' ; Load '-' into A
+ staa operator ; Save '-' to operator buffer
+ pula ; Restore A from the stack
+ nega ; Two's complement of A
+ suba #1 ; Subtract 1 from A
+ negb ; Two'complement of B
+ subb #1 ; Subtract 1 from B
+ addd #1 ; Add 1 to D
+ bra dAfterNeg ; Jump back to dAfterNeg
+
+;*************************************************************************
+; Zeros subroutine
+;
+; This subroutine will write zeros to every byte in a given array.
+;
+; Input: Address of an array in X and its length in Y
+; Output: Zeros in every byte of an array.
+; Registers in use: X for the address of the array, Y for the length, and A for 0
+; Memory locations in use: Memory Address of the array
+;
+; Comments: This subroutine requires serial to be setup and putchar subroutine.
+;
+
+Zeros
+ psha ; Save A to the Stack
+ clra ; Clear A
+zerosLoop staa 1,x+ ; Load A into byte at X
+ dbne y,zerosLoop ; Decrement Y and loop if Y != 0
+ pula ; Restore A from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; memset subroutine
+;
+; This subroutine will write a given byte to every byte in a given array.
+;
+; Input: Address of an array in X and its length in Y, the byte in A
+; Output: The given byte in every byte of an array.
+; Registers in use: X for the address of the array, Y for the length, and A for the given byte
+; Memory locations in use: Memory Address of the array
+;
+; Comments: This subroutine requires serial to be setup and putchar subroutine.
+;
+
+memset
+ staa 1,x+ ; Load A into byte at X
+ dbne y,memset ; Decrement Y and loop if Y != 0
+ rts ; Return to caller
+
+;*************************************************************************
+; WriteString subroutine
+;
+; This subroutine will write a given null terminated string to the serial.
+;
+; Input: Address of null terminated string in X
+; Output: Null terminated string written to serial
+; Registers in use: X for the address of the string and A for the current byte
+; Memory locations in use: Memory Address for serial line, address of the string
+;
+; Comments: This subroutine requires serial to be setup and putchar subroutine.
+;
+
+WriteString
+ psha ; Save A to the stack
+writeLoop ldaa 1,x+ ; Load the byte at addr in X, then add 1
+ beq doneWrite ; if A == 0, branch to doneWrite
+ jsr putchar ; Jump to putchar to write byte to serial
+ bra writeLoop ; branch always to writeLoop
+doneWrite pula ; restore A from the stack
+ rts ; return to caller
+
+;*************************************************************************
+; ReadString subroutine
+;
+; This subroutine will read a string from the serial line to a given address.
+;
+; Input: Address of an array in X
+; Output: Null terminated string in the given array
+; Registers in use: X for the address of the string Y for the length of the string,
+; and A for the current byte
+; Memory locations in use: Memory Address for serial line, address of the string
+;
+; Comments: This subroutine requires serial to be setup and getchar subroutine.
+;
+
+ReadString
+ psha ; Save accumulator A to the stack
+ pshy ; Save Y to the stack
+ pshx ; Save X to the stack
+readLoop jsr getchar ; Jump to putchar to write byte to serial
+ beq readLoop ; While A == 0, loop
+ cmpa #CR ; If A == CR, exit loop
+ beq doneRead ; Branch to doneRead if A == CR
+ staa 1,x+ ; Save the byte to the addr in X, then add 1
+ jsr putchar ; Write Character back to the terminal
+ dey ; Decrement Y by 1
+ beq doneRead ; If Y == 0, no more room, stop reading
+ bra readLoop ; branch always to readLoop
+doneRead pulx ; Restore X from the stack
+ pulY ; Restore Y from the stack
+ pula ; restore A from the stack
+ rts ; return to caller
+
+;*************************************************************************
+; putchar subroutine
+;
+; This subroutine writes a single byte to a serial line
+;
+; Input: A single ASCII byte in accumulator A
+; Output: Sends one character to SCI port
+; Registers in use: Accumulator A with input byte
+; Memory locations in use: SCISR1 and SCIDRL status and data registers
+;
+
+putchar brclr SCISR1,#%10000000,putchar ; wait for transmit buffer empty
+ staa SCIDRL ; send a character
+ rts ; Return to caller
+
+;*************************************************************************
+; putchar subroutine
+;
+; This subroutine reads one byte from the SCI port
+;
+; Input: One byte from the SCI port
+; Output: One byte in accumulator A
+; Registers in use: Accumulator A for output byte
+; Memory locations in use: SCISR1 and SCIDRL status and data registers
+;
+
+getchar brclr SCISR1,#%00100000,getchar7 ; If no input on SCI port, return 0
+ ldaa SCIDRL ; Read one byte from SCI port into A
+ rts ; Return to caller
+getchar7 clra ; Set A to 0
+ rts ; Return to caller
+
+*
+**************************************************************************
+* Data Section 2: address used [ $3100 to $3FFF ] RAM Memory
+*
+
+clock dc.b 'Clock> ',NULL ; Prompt string for clock
+
+CMD dc.b 'CMD> ',NULL ; Prompt string for CMD
+
+error dc.b 'Error> ',NULL ; Prompt string for errors
+
+badInput dc.b 'Invalid Input',NULL ; Invalid Input Prompt
+
+; twMsg: welcome message for typewrite
+twMsg dc.b CR,LF,'Clock stopped and Typewrite program started.',CR,LF
+ dc.b 'You may type below.',CR,LF,NULL
+
+; msg: this is the main option menu string
+msg dc.b 'Commands:',CR,LF
+ dc.b 't: Set the time in format HH:MM:SS',CR,LF
+ dc.b 'h: Display the hours on the 7 segment displays',CR,LF
+ dc.b 'm: Display the minutes on the 7 segment displays',CR,LF
+ dc.b 's: Display the seconds on the 7 segment displays',CR,LF
+ dc.b 'q: Stop the clock and enter typewriter',CR,LF,NULL
+
+ end ; last line of the file
diff --git a/cmpen472_hw8McDonnell/Sources/main.asm b/cmpen472_hw8McDonnell/Sources/main.asm
index 1782ad1..cbfe22a 100644
--- a/cmpen472_hw8McDonnell/Sources/main.asm
+++ b/cmpen472_hw8McDonnell/Sources/main.asm
@@ -333,6 +333,21 @@ TimeOnPortB
puld ; Restore D from the stack
rts ; Return from caller
+;*************************************************************************
+; ExecuteCommand subroutine
+;
+; This subroutine will parse user input and execute the proper command or error out.
+;
+; Input: An address of a NULL terminated string in X.
+; Output: The output of the proper command or an error message.
+; Registers in use: X for the address of the user input, A for individual characters,
+; D & Y for numbers read from user input.
+; Memory locations in use: Serial console memory locations.
+;
+; Comments: This subroutine will disable interrupts while setting the time and will
+; reenable them after setting the time.
+;
+
ExecuteCommand
pshd ; Save D to the stack
pshy ; Save Y to the stack
@@ -344,37 +359,48 @@ skipSpaces ldaa 1,+x ; Load the next character into X
cmpa #' ' ; Compare A to ' ' character
beq skipSpaces ; If A == ' ', loop to skipSpaces
sei ; Disable interrupts
+ ldd hours ; Load hours into D
+ pshd ; Save hours to the stack
jsr ReadDecimal ; Read Hour number
exg y,d ; Exchange Y and D
cpd #24 ; Compare D to 24
- bhs badCommand ; If D >= 24, badCommand
+ lbhs badHours ; If D >= 24, badHours
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ lblt badHours ; If D < 0, badHours
std hours ; Save D to hours
ldaa -1,x ; Load the next character into A
cmpa #':' ; Compare A to ':'
- bne badCommand ; If A != ':', bad command
+ lbne badHours ; If A != ':', badHours
+ ldd minutes ; Load minutes into D
+ pshd ; Save minutes to the stack
jsr ReadDecimal ; Read minute number
exg y,d ; Exchange Y and D
cpd #60 ; Compare D to 60
- bhs badCommand ; If D >= 60, badCommand
+ bhs badMinutes ; If D >= 60, badMinutes
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ blt badMinutes ; If D < 0, badMinutes
std minutes ; Save D to minutes
ldaa -1,x ; Load the next character into A
cmpa #':' ; Compare A to ':'
- bne badCommand ; If A != ':', bad command
+ bne badMinutes ; If A != ':', badMinutes
+ ldd seconds ; Load seconds into D
+ pshd ; Save seconds to the stack
jsr ReadDecimal ; Read second number
exg y,d ; Exchange Y and D
cpd #60 ; Compare D to 60
- bhs badCommand ; If D >= 60, badCommand
+ bhs badSeconds ; If D >= 60, badSeconds
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ blt badSeconds ; If D < 0, badSeconds
std seconds ; Save D to seconds
ldaa -1,x ; Load the next character into A
cmpa #NULL ; Compare A to NULL
- bne badCommand ; If A != ':', bad command
+ bne badSeconds ; If A != ':', badSeconds
+ clra ; Set A to 0
+ staa counter ; Clear Counter
cli ; Enable interrupts
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
bra ecDone ; Branch to ecDone
isH cmpa #'h' ; Compare A to 'h'
bne isM ; If A != 'h', branch to isM
@@ -403,8 +429,14 @@ isQ cmpa #'q' ; Compare A to 'q'
cmpb #NULL ; Compare B to NULL
bne badCommand ; If B != NULL, branch to ecDone
jmp TypeWrite ; Jump to TypeWrite
-badCommand cli ; Reenable interrupts
- pshx ; Save X to the stack
+badSeconds puld ; Restore Seconds from the stack
+ std seconds ; Restore seconds before change
+badMinutes puld ; Restore minutes from the stack
+ std minutes ; Restore minutes before change
+badHours puld ; Restore hours from the stack
+ std hours ; Restore hours before change
+ cli ; Reenable interrupts
+badCommand pshx ; Save X to the stack
ldaa #' ' ; Load Space character into A
jsr putchar ; Jump to putchar to write space character
jsr putchar ; Jump to putchar to write space character
diff --git a/cmpen472_hw8McDonnell/bin/Project.abs b/cmpen472_hw8McDonnell/bin/Project.abs
index 4684657..452be23 100644
--- a/cmpen472_hw8McDonnell/bin/Project.abs
+++ b/cmpen472_hw8McDonnell/bin/Project.abs
Binary files differ
diff --git a/cmpen472_hw8McDonnell/bin/Project.abs.s19 b/cmpen472_hw8McDonnell/bin/Project.abs.s19
index aad812e..6af90b5 100644
--- a/cmpen472_hw8McDonnell/bin/Project.abs.s19
+++ b/cmpen472_hw8McDonnell/bin/Project.abs.s19
@@ -2,41 +2,43 @@ S0580000433A5C55736572735C4A61636F62204D63446F6E6E656C6C5C446F63756D656E74735C43
S123300000000000000000000000000000000000000010000000000000000000000000009C
S123302000000000001000000000000000000000000000000000000000000000000000007C
S106304000106811
-S1233100CF310086F15A03860C5ACBCC00015CC8CE34921633F24C3B194C38804C37808633
-S1233120FF5A03CE3030FD30401633E310EF1631B9CE3030FD30401633FECE3030163266AB
-S1233140CE3030FD30401633E314101631B910EF20DF14104D3880CE344C1633F216341F67
-S12331609727FA5A0116341820F34C3780FE302C087E302C8E00C8263FCE00007E302CFE23
+S1233100CF310086F15A03860C5ACBCC00015CC8CE34B71634174C3B194C38804C378086E8
+S1233120FF5A03CE3030FD304016340810EF1631B9CE3030FD3040163423CE30301632665F
+S1233140CE3030FD304016340814101631B910EF20DF14104D3880CE3471163417163444D1
+S12331609727FA5A0116343D20F34C3780FE302C087E302C8E00C8263FCE00007E302CFEFE
S1233180302A087E302A8E003C262ACE00007E302AFE3028087E30288E003C2618CE000027
S12331A07E3028FE3026087E30268E00182606CE00007E30261631B90B3B3534860D163405
-S12331C018860A163418CE34281633F2FC30268C000A240736863016341832CD30001633A3
-S12331E074863A163418FC30288C000A240736863016341832CD3000163374863A163418C4
-S1233200FC302A8C000A240736863016341832CD300016337486201634181634181634188D
-S1233220163418CE34301633F2CE30301633F2B6304281682605FC3026200C816D2605FC83
+S12331C03D860A16343DCE344D163417FC30268C000A240736863016343D32CD30001633E9
+S12331E099863A16343DFC30288C000A240736863016343D32CD3000163399863A16343D0B
+S1233200FC302A8C000A240736863016343D32CD3000163399862016343D16343D16343DD4
+S123322016343DCE3455163417CE3030163417B6304281682605FC3026200C816D2605FCED
S123324030282003FC302A16324E30313A3D3B34CE000A181037B7D4CE000A58585858EAD8
-S1233260B05B01303A3D3B35A630182700B081742654A620812027FA1410163321B7E48CB6
-S12332800018247C8C00002D777C3026A61F813A266E163321B7E48C003C24648C00002D4E
-S12332A05F7C3028A61F813A2656163321B7E48C003C244C8C00002D477C302AA61F810082
-S12332C0263E10EF20588168260BE630C10026307A30422049816D260BE630C10026217ABC
-S12332E03042203A8173260BE630C10026127A3042202B81712609E630C1002603063152E9
-S123330010EF348620163418163418163418163418CE34361633F2CE343E1633F230313ABF
-S12333203D3BCD0000E630272EC12B272AC12D2726C12A2722C12F271EC13A271AC12027B4
-S123334016C1302D17C1392213C03037CC000A13B7C63319ED20CE87B7023A3D8604B70241
-S12333603A3D343536A67F27056A3020F8876A303231303D34353B8C0000274C2D533635B1
-S1233380348630CE3013CD00051633EC3031876A4032CE000A18108E00002708CB306B60E0
-S12333A0B7D420EE8C000026F3B6302F812D26026A60CE30131633621633F2FD3024CE30D0
-S12333C0131633E33A31303D86301634183A31303D36862D7A302F3240800150C001C30059
-S12333E001209B36876A300436FB323D6A300436FB3D36A630270516341820F7323D36357B
-S12334003416341F27FB810D270A6A3016341803270220ED3031323D4FCC80FC5ACF3D4FD9
-S1233420CC200396CF3D873D436C6F636B3E2000434D443E20004572726F723E2000496E98
-S123344076616C696420496E707574000D0A436C6F636B2073746F7070656420616E642093
-S12334605479706577726974652070726F6772616D20737461727465642E0D0A596F7520AA
-S12334806D617920747970652062656C6F772E0D0A00436F6D6D616E64733A0D0A743A2030
-S12334A0536574207468652074696D6520696E20666F726D61742048483A4D4D3A53530D9B
-S12334C00A683A20446973706C61792074686520686F757273206F6E20746865203720734C
-S12334E065676D656E7420646973706C6179730D0A6D3A20446973706C617920746865208A
-S12335006D696E75746573206F6E207468652037207365676D656E7420646973706C6179C4
-S1233520730D0A733A20446973706C617920746865207365636F6E6473206F6E207468658C
-S12335402037207365676D656E7420646973706C6179730D0A713A2053746F70207468658B
-S121356020636C6F636B20616E6420656E74657220747970657772697465720D0A00F6
+S1233260B05B01303A3D3B35A630182700D58174266DA620812027FA1410FC30263B163333
+S123328046B7E48C0018182400978C0000182D00907C3026A61F813A18260085FC30283BCD
+S12332A0163346B7E48C003C24738C00002D6E7C3028A61F813A2665FC302A3B163346B7A4
+S12332C0E48C003C24538C00002D4E7C302AA61F81002645877A302C10EF3A3A3A2064812A
+S12332E068260BE630C100263E7A30422055816D260BE630C100262F7A30422046817326DE
+S12333000BE630C10026207A3042203781712617E630C10026110631523A7C302A3A7C3082
+S1233320283A7C302610EF34862016343D16343D16343D16343DCE345B163417CE34631627
+S1233340341730313A3D3BCD0000E630272EC12B272AC12D2726C12A2722C12F271EC13AF7
+S1233360271AC1202716C1302D17C1392213C03037CC000A13B7C63319ED20CE87B7023A58
+S12333803D8604B7023A3D343536A67F27056A3020F8876A303231303D34353B8C00002748
+S12333A04C2D533635348630CE3013CD00051634113031876A4032CE000A18108E00002731
+S12333C008CB306B60B7D420EE8C000026F3B6302F812D26026A60CE3013163387163417E6
+S12333E0FD3024CE30131634083A31303D863016343D3A31303D36862D7A302F3240800173
+S123340050C001C30001209B36876A300436FB323D6A300436FB3D36A630270516343D2032
+S1233420F7323D36353416344427FB810D270A6A3016343D03270220ED3031323D4FCC804F
+S1233440FC5ACF3D4FCC200396CF3D873D436C6F636B3E2000434D443E20004572726F72DC
+S12334603E2000496E76616C696420496E707574000D0A436C6F636B2073746F70706564D1
+S123348020616E64205479706577726974652070726F6772616D20737461727465642E0D7E
+S12334A00A596F75206D617920747970652062656C6F772E0D0A00436F6D6D616E64733A8E
+S12334C00D0A743A20536574207468652074696D6520696E20666F726D61742048483A4DD0
+S12334E04D3A53530D0A683A20446973706C61792074686520686F757273206F6E20746841
+S1233500652037207365676D656E7420646973706C6179730D0A6D3A20446973706C61799B
+S123352020746865206D696E75746573206F6E207468652037207365676D656E742064694C
+S123354073706C6179730D0A733A20446973706C617920746865207365636F6E6473206F12
+S12335606E207468652037207365676D656E7420646973706C6179730D0A713A2053746F6D
+S1233580702074686520636C6F636B20616E6420656E74657220747970657772697465721A
+S10635A00D0A000D
S105FFF0316A70
S9030000FC
diff --git a/cmpen472_hw8McDonnell/bin/main.dbg b/cmpen472_hw8McDonnell/bin/main.dbg
index 752531b..94da668 100644
--- a/cmpen472_hw8McDonnell/bin/main.dbg
+++ b/cmpen472_hw8McDonnell/bin/main.dbg
@@ -2,22 +2,22 @@
*
* Title: Calculator
*
-* Objective: CMPEN 472 Homework 7
+* Objective: CMPEN 472 Homework 8
*
* Revision: V1.0
*
-* Date: Mar. 7, 2025
+* Date: Mar. 24, 2025
*
* Programmer: Jacob McDonnell
*
* Company: The Pennsylvania State University
* Department of Computer Science and Engineering
*
-* Algorithm: Simple Serial I/O, address poking and modifying
+* Algorithm: Simple Serial I/O, Real Time Interrupts for Time Tracking
*
* Register Use: A & B to current byte, etc,
* X & Y holds address of strings and length of string,
-* D to hold data and address of the memory location to work on.
+* D to hold data for printing, reading, and updating time.
*
* Memory Use: RAM Locations from $3000 for data,
* RAM Locations from $3100 for program
@@ -25,12 +25,10 @@
* Input: Serial Port for User Input
*
* Output: Serial Port for String Output
-* Memory locations changed if modified by user
*
-* Observation: This program is a simple 16-bit calculator. The input can be
-* any 4 digit positive decimal integer, the output can be negative.
-* The +, -, *, and / operators are supported. Only two numbers at
-* a time.
+* Observation: The HC12 will output the time and a command prompt every second.
+* The user can input commands and the program will output a response
+* based on the input.
*
* Note: ON CSM-12C128 board,
*
@@ -169,6 +167,24 @@ twLoop jsr getchar ; Read a character from the serial conso
* Subroutine Section: address used [ $3100 to $3FFF ] RAM Memory
*
+;*************************************************************************
+; rtiisr subroutine
+;
+; This subroutine will increment the counter, seconds, minutes, & hours counters
+; to track the time. This subroutine will be called ~400 times a second.
+;
+; Input: No input other than the timer to call the isr.
+; Output: The counter, seconds, minutes, & hours buffers will
+; be updated to track the time, the time & prompt will be
+; printed every second.
+; Registers in use: X for adding to the counter, seconds, minutes, & hours buffers.
+; Memory locations in use: Memory Address for serial line, Memory addresses for RTIISR control,
+; Buffer words for counters, seconds, minutes, & hours buffers.
+;
+; Comments: The counter buffer should be compared to 400, but for the simulator,
+; the counter is compared to 200 to better simulate 1 second on my computer.
+;
+
rtiisr bset CRGFLG,%10000000; Clear RTI Interrupt Flag
ldx counter ; Load counter into X
inx ; Increment counter by 1
@@ -201,6 +217,24 @@ rtiisr bset CRGFLG,%10000000; Clear RTI Interrupt Flag
rtidone jsr PrintTime ; Jump to PrintTime
rtiSkip RTI ; Return from RTI ISR
+;*************************************************************************
+; PrintTime subroutine
+;
+; This subroutine will print the time, command prompt, and maybe an error prompt.
+;
+; Input: No input.
+; Output: The time prompt, time, command prompt, the current input,
+; and/or an error on the serial console.
+; Registers in use: A for the characters to print, X for buffer addresses,
+; Y for buffer lengths, D for the seconds/minutes/hours for calling TimeOnPortB
+; Memory locations in use: Memory Address for serial line, Buffer words for counters,
+; seconds, minutes, & hours buffers, and buffer to print time,
+; outputBuf for tracking what to output on PORTB.
+;
+; Comments: This subroutine requires TimeOnPortB subroutine and to be setup. The subroutine
+; will print the current user input if its not finished.
+;
+
PrintTime
pshd ; Save D to the stack
pshy ; Save Y to the stack
@@ -267,6 +301,20 @@ skipRest jsr TimeOnPortB ; Call TimeOnPortB to output time
puld ; Restore D from the stack
rts ; Return to caller
+;*************************************************************************
+; TimeOnPortB subroutine
+;
+; This subroutine will output the time given on on PORTB for two seven segment displays.
+;
+; Input: Two Digit Decimal number in register D.
+; Output: The given two digit decimal number on PORTB for two 7 segment displays.
+; Registers in use: D for the input, and for math to split the digits, X for math to split digits.
+; Memory locations in use: PORTB memory location.
+;
+; Comments: This subroutine will only work with two digit decimal numbers, and one digit decimal
+; numbers (leading zeros will be added).
+;
+
TimeOnPortB
pshd ; Save D to the stack
pshx ; Save X to the stack
@@ -285,6 +333,21 @@ TimeOnPortB
puld ; Restore D from the stack
rts ; Return from caller
+;*************************************************************************
+; ExecuteCommand subroutine
+;
+; This subroutine will parse user input and execute the proper command or error out.
+;
+; Input: An address of a NULL terminated string in X.
+; Output: The output of the proper command or an error message.
+; Registers in use: X for the address of the user input, A for individual characters,
+; D & Y for numbers read from user input.
+; Memory locations in use: Serial console memory locations.
+;
+; Comments: This subroutine will disable interrupts while setting the time and will
+; reenable them after setting the time.
+;
+
ExecuteCommand
pshd ; Save D to the stack
pshy ; Save Y to the stack
@@ -296,37 +359,48 @@ skipSpaces ldaa 1,+x ; Load the next character into X
cmpa #' ' ; Compare A to ' ' character
beq skipSpaces ; If A == ' ', loop to skipSpaces
sei ; Disable interrupts
+ ldd hours ; Load hours into D
+ pshd ; Save hours to the stack
jsr ReadDecimal ; Read Hour number
exg y,d ; Exchange Y and D
cpd #24 ; Compare D to 24
- bhs badCommand ; If D >= 24, badCommand
+ lbhs badHours ; If D >= 24, badHours
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ lblt badHours ; If D < 0, badHours
std hours ; Save D to hours
ldaa -1,x ; Load the next character into A
cmpa #':' ; Compare A to ':'
- bne badCommand ; If A != ':', bad command
+ lbne badHours ; If A != ':', badHours
+ ldd minutes ; Load minutes into D
+ pshd ; Save minutes to the stack
jsr ReadDecimal ; Read minute number
exg y,d ; Exchange Y and D
cpd #60 ; Compare D to 60
- bhs badCommand ; If D >= 60, badCommand
+ bhs badMinutes ; If D >= 60, badMinutes
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ blt badMinutes ; If D < 0, badMinutes
std minutes ; Save D to minutes
ldaa -1,x ; Load the next character into A
cmpa #':' ; Compare A to ':'
- bne badCommand ; If A != ':', bad command
+ bne badMinutes ; If A != ':', badMinutes
+ ldd seconds ; Load seconds into D
+ pshd ; Save seconds to the stack
jsr ReadDecimal ; Read second number
exg y,d ; Exchange Y and D
cpd #60 ; Compare D to 60
- bhs badCommand ; If D >= 60, badCommand
+ bhs badSeconds ; If D >= 60, badSeconds
cpd #0 ; Compare D to 0
- blt badCommand ; If D < 0, badCommand
+ blt badSeconds ; If D < 0, badSeconds
std seconds ; Save D to seconds
ldaa -1,x ; Load the next character into A
cmpa #NULL ; Compare A to NULL
- bne badCommand ; If A != ':', bad command
+ bne badSeconds ; If A != ':', badSeconds
+ clra ; Set A to 0
+ staa counter ; Clear Counter
cli ; Enable interrupts
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
+ puld ; Restore D from the stack
bra ecDone ; Branch to ecDone
isH cmpa #'h' ; Compare A to 'h'
bne isM ; If A != 'h', branch to isM
@@ -355,8 +429,14 @@ isQ cmpa #'q' ; Compare A to 'q'
cmpb #NULL ; Compare B to NULL
bne badCommand ; If B != NULL, branch to ecDone
jmp TypeWrite ; Jump to TypeWrite
-badCommand cli ; Reenable interrupts
- pshx ; Save X to the stack
+badSeconds puld ; Restore Seconds from the stack
+ std seconds ; Restore seconds before change
+badMinutes puld ; Restore minutes from the stack
+ std minutes ; Restore minutes before change
+badHours puld ; Restore hours from the stack
+ std hours ; Restore hours before change
+ cli ; Reenable interrupts
+badCommand pshx ; Save X to the stack
ldaa #' ' ; Load Space character into A
jsr putchar ; Jump to putchar to write space character
jsr putchar ; Jump to putchar to write space character
diff --git a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.o b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.o
index 4684657..452be23 100644
--- a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.o
+++ b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.o
Binary files differ
diff --git a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.sx b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.sx
index 3f3ba82..9fb3f9a 100644
--- a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.sx
+++ b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/ObjectCode/main.asm.sx
@@ -3,40 +3,42 @@ S123300000000000000000000000000000000000000010000000000000000000000000009C
S123302000000000001000000000000000000000000000000000000000000000000000007C
S106304000106811
S105FFF0316A70
-S1233100CF310086F15A03860C5ACBCC00015CC8CE34921633F24C3B194C38804C37808633
-S1233120FF5A03CE3030FD30401633E310EF1631B9CE3030FD30401633FECE3030163266AB
-S1233140CE3030FD30401633E314101631B910EF20DF14104D3880CE344C1633F216341F67
-S12331609727FA5A0116341820F34C3780FE302C087E302C8E00C8263FCE00007E302CFE23
+S1233100CF310086F15A03860C5ACBCC00015CC8CE34B71634174C3B194C38804C378086E8
+S1233120FF5A03CE3030FD304016340810EF1631B9CE3030FD3040163423CE30301632665F
+S1233140CE3030FD304016340814101631B910EF20DF14104D3880CE3471163417163444D1
+S12331609727FA5A0116343D20F34C3780FE302C087E302C8E00C8263FCE00007E302CFEFE
S1233180302A087E302A8E003C262ACE00007E302AFE3028087E30288E003C2618CE000027
S12331A07E3028FE3026087E30268E00182606CE00007E30261631B90B3B3534860D163405
-S12331C018860A163418CE34281633F2FC30268C000A240736863016341832CD30001633A3
-S12331E074863A163418FC30288C000A240736863016341832CD3000163374863A163418C4
-S1233200FC302A8C000A240736863016341832CD300016337486201634181634181634188D
-S1233220163418CE34301633F2CE30301633F2B6304281682605FC3026200C816D2605FC83
+S12331C03D860A16343DCE344D163417FC30268C000A240736863016343D32CD30001633E9
+S12331E099863A16343DFC30288C000A240736863016343D32CD3000163399863A16343D0B
+S1233200FC302A8C000A240736863016343D32CD3000163399862016343D16343D16343DD4
+S123322016343DCE3455163417CE3030163417B6304281682605FC3026200C816D2605FCED
S123324030282003FC302A16324E30313A3D3B34CE000A181037B7D4CE000A58585858EAD8
-S1233260B05B01303A3D3B35A630182700B081742654A620812027FA1410163321B7E48CB6
-S12332800018247C8C00002D777C3026A61F813A266E163321B7E48C003C24648C00002D4E
-S12332A05F7C3028A61F813A2656163321B7E48C003C244C8C00002D477C302AA61F810082
-S12332C0263E10EF20588168260BE630C10026307A30422049816D260BE630C10026217ABC
-S12332E03042203A8173260BE630C10026127A3042202B81712609E630C1002603063152E9
-S123330010EF348620163418163418163418163418CE34361633F2CE343E1633F230313ABF
-S12333203D3BCD0000E630272EC12B272AC12D2726C12A2722C12F271EC13A271AC12027B4
-S123334016C1302D17C1392213C03037CC000A13B7C63319ED20CE87B7023A3D8604B70241
-S12333603A3D343536A67F27056A3020F8876A303231303D34353B8C0000274C2D533635B1
-S1233380348630CE3013CD00051633EC3031876A4032CE000A18108E00002708CB306B60E0
-S12333A0B7D420EE8C000026F3B6302F812D26026A60CE30131633621633F2FD3024CE30D0
-S12333C0131633E33A31303D86301634183A31303D36862D7A302F3240800150C001C30059
-S12333E001209B36876A300436FB323D6A300436FB3D36A630270516341820F7323D36357B
-S12334003416341F27FB810D270A6A3016341803270220ED3031323D4FCC80FC5ACF3D4FD9
-S1233420CC200396CF3D873D436C6F636B3E2000434D443E20004572726F723E2000496E98
-S123344076616C696420496E707574000D0A436C6F636B2073746F7070656420616E642093
-S12334605479706577726974652070726F6772616D20737461727465642E0D0A596F7520AA
-S12334806D617920747970652062656C6F772E0D0A00436F6D6D616E64733A0D0A743A2030
-S12334A0536574207468652074696D6520696E20666F726D61742048483A4D4D3A53530D9B
-S12334C00A683A20446973706C61792074686520686F757273206F6E20746865203720734C
-S12334E065676D656E7420646973706C6179730D0A6D3A20446973706C617920746865208A
-S12335006D696E75746573206F6E207468652037207365676D656E7420646973706C6179C4
-S1233520730D0A733A20446973706C617920746865207365636F6E6473206F6E207468658C
-S12335402037207365676D656E7420646973706C6179730D0A713A2053746F70207468658B
-S121356020636C6F636B20616E6420656E74657220747970657772697465720D0A00F6
+S1233260B05B01303A3D3B35A630182700D58174266DA620812027FA1410FC30263B163333
+S123328046B7E48C0018182400978C0000182D00907C3026A61F813A18260085FC30283BCD
+S12332A0163346B7E48C003C24738C00002D6E7C3028A61F813A2665FC302A3B163346B7A4
+S12332C0E48C003C24538C00002D4E7C302AA61F81002645877A302C10EF3A3A3A2064812A
+S12332E068260BE630C100263E7A30422055816D260BE630C100262F7A30422046817326DE
+S12333000BE630C10026207A3042203781712617E630C10026110631523A7C302A3A7C3082
+S1233320283A7C302610EF34862016343D16343D16343D16343DCE345B163417CE34631627
+S1233340341730313A3D3BCD0000E630272EC12B272AC12D2726C12A2722C12F271EC13AF7
+S1233360271AC1202716C1302D17C1392213C03037CC000A13B7C63319ED20CE87B7023A58
+S12333803D8604B7023A3D343536A67F27056A3020F8876A303231303D34353B8C00002748
+S12333A04C2D533635348630CE3013CD00051634113031876A4032CE000A18108E00002731
+S12333C008CB306B60B7D420EE8C000026F3B6302F812D26026A60CE3013163387163417E6
+S12333E0FD3024CE30131634083A31303D863016343D3A31303D36862D7A302F3240800173
+S123340050C001C30001209B36876A300436FB323D6A300436FB3D36A630270516343D2032
+S1233420F7323D36353416344427FB810D270A6A3016343D03270220ED3031323D4FCC804F
+S1233440FC5ACF3D4FCC200396CF3D873D436C6F636B3E2000434D443E20004572726F72DC
+S12334603E2000496E76616C696420496E707574000D0A436C6F636B2073746F70706564D1
+S123348020616E64205479706577726974652070726F6772616D20737461727465642E0D7E
+S12334A00A596F75206D617920747970652062656C6F772E0D0A00436F6D6D616E64733A8E
+S12334C00D0A743A20536574207468652074696D6520696E20666F726D61742048483A4DD0
+S12334E04D3A53530D0A683A20446973706C61792074686520686F757273206F6E20746841
+S1233500652037207365676D656E7420646973706C6179730D0A6D3A20446973706C61799B
+S123352020746865206D696E75746573206F6E207468652037207365676D656E742064694C
+S123354073706C6179730D0A733A20446973706C617920746865207365636F6E6473206F12
+S12335606E207468652037207365676D656E7420646973706C6179730D0A713A2053746F6D
+S1233580702074686520636C6F636B20616E6420656E74657220747970657772697465721A
+S10635A00D0A000D
S9033100CB
diff --git a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/TargetDataWindows.tdt b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/TargetDataWindows.tdt
index 4d2f711..3962bcd 100644
--- a/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/TargetDataWindows.tdt
+++ b/cmpen472_hw8McDonnell/cmpen472_hw8McDonnell_Data/Standard/TargetDataWindows.tdt
Binary files differ