************************************************************************** * * 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 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 jsr ReadDecimal ; Read Hour number exg y,d ; Exchange Y and D cpd #24 ; Compare D to 24 bhs badCommand ; If D >= 24, badCommand cpd #0 ; Compare D to 0 blt badCommand ; If D < 0, badCommand 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 jsr ReadDecimal ; Read minute number exg y,d ; Exchange Y and D cpd #60 ; Compare D to 60 bhs badCommand ; If D >= 60, badCommand cpd #0 ; Compare D to 0 blt badCommand ; If D < 0, badCommand 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 jsr ReadDecimal ; Read second number exg y,d ; Exchange Y and D cpd #60 ; Compare D to 60 bhs badCommand ; If D >= 60, badCommand cpd #0 ; Compare D to 0 blt badCommand ; If D < 0, badCommand 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 cli ; Enable interrupts 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 badCommand cli ; Reenable interrupts 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