summaryrefslogtreecommitdiff
path: root/cmpen472hw5_McDonnell/Sources/main.asm
diff options
context:
space:
mode:
Diffstat (limited to 'cmpen472hw5_McDonnell/Sources/main.asm')
-rw-r--r--cmpen472hw5_McDonnell/Sources/main.asm284
1 files changed, 258 insertions, 26 deletions
diff --git a/cmpen472hw5_McDonnell/Sources/main.asm b/cmpen472hw5_McDonnell/Sources/main.asm
index 5ad91b3..7991c58 100644
--- a/cmpen472hw5_McDonnell/Sources/main.asm
+++ b/cmpen472hw5_McDonnell/Sources/main.asm
@@ -1,40 +1,38 @@
**************************************************************************
*
-* Title: LED Light Dimmer Loop
+* Title: Hardware Controller
*
-* Objective: CMPEN 472 Homework 4
+* Objective: CMPEN 472 Homework 5
*
* Revision: V1.0
*
-* Date: Feb. 14, 2025
+* Date: Feb. 21, 2025
*
* Programmer: Jacob McDonnell
*
* Company: The Pennsylvania State University
* Department of Computer Science and Engineering
*
-* Algorithm: Simple Parallel I/O use, time delay-loop, and PWM control
+* Algorithm: Simple Serial I/O, Parallel I/O use, time delay-loop, and PWM control
*
-* Register Use: A to control LEDS initially and for Light Level
-* X to hold the counter in the loop.
+* Register Use: A & B to control LEDS initially, Light Level, current byte, etc
+* X & Y to hold the counter in the loop and address of strings and length of string.
*
* Memory Use: RAM Locations from $3000 for data,
* RAM Locations from $3100 for program
*
* Input: Parameters hard-coded in the program - PORTB
-* Switch 1 at PORTB bit 0
-* Switch 2 at PORTB bit 1
-* Switch 3 at PORTB bit 2
-* Switch 4 at PORTB bit 3
+* Serial Port for User Input
*
* Output: LED 1 at PORTB bit 4
* LED 2 at PORTB bit 5
* LED 3 at PORTB bit 6
* LED 4 at PORTB bit 7
+* Serial Port for String Output
*
-* Observation: This program will decrease LED 4 from 100% to 0% in 400ms
-* and then increase LED 4 from 0% to 100% in 400ms. The program
-* will loop forever.
+* Observation: This program will respond to user input to turn on and off LEDs 1, 2, & 3,
+* Dim LED 4 from 100% to 0%, Dim LED 4 from 0% to 100%, and echo user input
+* back to the terminal in Type Writer Mode.
*
* Note: ON CSM-12C128 board,
* Switch 1 is at PORTB bit 0, and
@@ -79,16 +77,10 @@ Counter dc.w $0036 ; X register count number for time Delay
LEVEL dc.b $0005 ; Light Level that the LED should be
-msg dc.b 'L1: Turn on LED1',CR,LF,
- 'F1: Turn off LED1',CR,LF
- 'L2: Turn on LED2',CR,LF
- 'F2: Turn off LED2',CR,LF
- 'L3: Turn on LED3',CR,LF
- 'F3: Turn off LED3',CR,LF
- 'L4: LED4 goes from 0% light level to 100% light level in 0.4 seconds',CR,LF
- 'F4: LED4 goes from 100% light level to 0% light level in 0.4 seconds',CR,LF
- 'QUIT: Quit menu program, run \'Type writer\' program.',CR,LF,NULL
-
+str ds.b $0005 ; Array of 5 bytes to read a string
+ dc.b NULL
+lenStr dc.w $0005 ; Length of str array
+* There is a second Data Section at the end of the file.
*
**************************************************************************
* Program Section: address used [ $3100 to $3FFF ] RAM Memory
@@ -99,16 +91,195 @@ 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
+
+
mainLoop
- ldx msg
- jsr WriteString
+ ldx #msg ; Load the address of msg into X
+ jsr WriteString ; Jump to WriteString to output message on serial
+
+ ldx #str ; Load the address of str into X
+ ldy lenStr ; Load length of str into Y
+ jsr Zeros ; jump to Zeros to zero out str
+
+ ldx #str ; Reload address of str into X
+ jsr ReadString ; Jump to ReadString to read user input into str
+
+ ldx #str ; Reload Address of str into X
+ jsr CheckInput ; Jump to CheckInput to handle user input
bra mainLoop ; Loop back to mainLoop always
+TypeWriter ldx #twMsg ; Load Type Writer welcome message address
+ jsr WriteString ; Jump to WriteString to write message to serial
+twReadLoop jsr getchar ; Read Character from Serial
+ beq twReadLoop ; While Character == 0, branch to twReadLoop
+ jsr putchar ; Write Character back to terminal
+ staa PORTB ; Write Character to PORTB
+ bra twReadLoop ; Branch always to twReadLoop
**************************************************************************
* Subroutine Section: address used [ $3100 to $3FFF ] RAM Memory
*
;*************************************************************************
+; CheckInput subroutine
+;
+; This subroutine will check the input string and match the option.
+;
+; Input: Address of null terminated string in X.
+; Output: No Output, Control flow changed to proper subroutine.
+; Registers in use: X for the address of the string, Y for the address of the
+; option to compare against, and A for the return value of strcmp
+; Memory locations in use: Memory Address for serial line, address of the string
+;
+; Comments: This subroutine will not return a value, it will jump to the proper subroutine
+; based on the input given.
+;
+
+CheckInput
+ pshy ; Save Y to the stack
+ psha ; Save A to the stack
+ ldy #option1 ; Load address of option1 string into Y
+ jsr strcmp ; Compare input string and option1 string
+ bne check2 ; If not equal, branch to next check
+ ldaa #1 ; Load 1 into A to specify LED number
+ jsr TurnOnLED ; Jump to TurnOnLED to turn on LED 1
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check2 ldy #option2 ; Load address of option2 string into Y
+ jsr strcmp ; Compare input string and option2 string
+ bne check3 ; If not equal, branch to next check
+ ldaa #1 ; Load 1 into A to specify LED number
+ jsr TurnOffLED ; Jump to TurnOffLED to turn on LED 1
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check3 ldy #option3 ; Load address of option3 string into Y
+ jsr strcmp ; Compare input string and option3 string
+ bne check4 ; If not equal, branch to next check
+ ldaa #2 ; Load 2 into A to specify LED number
+ jsr TurnOnLED ; Jump to TurnOnLED to turn on LED 2
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check4 ldy #option4 ; Load address of option4 string into Y
+ jsr strcmp ; Compare input string and option4 string
+ bne check5 ; If not equal, branch to next check
+ ldaa #2 ; Load 2 into A to specify LED number
+ jsr TurnOffLED ; Jump to TurnOffLED to turn on LED 2
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check5 ldy #option5 ; Load address of option5 string into Y
+ jsr strcmp ; Compare input string and option5 string
+ bne check6 ; If not equal, branch to next check
+ ldaa #3 ; Load 3 into A to specify LED number
+ jsr TurnOnLED ; Jump to TurnOnLED to turn on LED 3
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check6 ldy #option6 ; Load address of option6 string into Y
+ jsr strcmp ; Compare input string and option6 string
+ bne check7 ; If not equal, branch to next check
+ ldaa #3 ; Load 3 into A to specify LED number
+ jsr TurnOffLED ; Jump to TurnOffLED to turn off LED 3
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check7 ldy #option7 ; Load address of option7 string into Y
+ jsr strcmp ; Compare input string and option7 string
+ bne check8 ; If not equal, branch to next check
+ jsr LowToHigh ; Jump to LowToHigh to dim LED 4 from 0% to 100%
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check8 ldy #option8 ; Load address of option8 string into Y
+ jsr strcmp ; Compare input string and option8 string
+ bne check9 ; If not equal, branch to next check
+ jsr HighToLow ; Jump to LowToHigh to dim LED 4 from 100% to 0%
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+check9 ldy #option9 ; Load address of option9 string into Y
+ jsr strcmp ; Compare input string and option9 string
+ bne none ; If not equal, branch to unknown result
+ jmp TypeWriter ; Jump to TypeWriter portion of main routine
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+none ldx #unknown ; Load address of uknown command string into X
+ jsr WriteString ; Write unknown command string to serial
+ pula ; Restore A from the stack
+ puly ; Restore Y from the stack
+ rts ; Return to caller
+
+;*************************************************************************
+; 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
+
+;*************************************************************************
+; strcmp subroutine
+;
+; This subroutine will compare two null terminated strings.
+;
+; Input: Address of 2 null terminated strings in X & Y
+; Output: 0 or 1 in accumulator A to signal same and different respectively
+; Registers in use: X & Y for the address of the strings and A & B for the current bytes
+; Memory locations in use: Memory Address for serial line, address of the strings
+;
+; Comments: This subroutine requires null terminated strings otherwise it will not work.
+;
+
+strcmp
+ pshb ; Save A to the Stack
+ pshx ; Save X to the Stack
+ pshy ; Save Y to the Stack
+cmpLoop ldaa 1,x+ ; Load byte at X into A
+ beq diffX ; If A == 0, branch to diffX
+ ldab 1,y+ ; Load byte at Y into B
+ beq diffY ; If B == 0, branch to diffY
+ sba ; Subtract B from A and store in A
+ beq cmpLoop ; If zero Loop, the characters are the same
+ ldaa #1 ; Load 1 into A to signal difference
+ puly ; Restore Y from the Stack
+ pulx ; Restore X from the Stack
+ pulb ; Restore B from the Stack
+ rts ; Return to Caller
+diffX ldaa y ; Load character at Y into A
+ beq equal ; If A == 0, Y and X are the same, branch to equal
+diffY ldaa #1 ; Load 1 into A to signal difference
+ puly ; Restore Y from the Stack
+ pulx ; Restore X from the Stack
+ pulb ; Restore B from the stack
+ rts ; Return to caller
+equal clra ; Clear A to signal similarity
+ puly ; Restore Y from the Stack
+ pulx ; Restore X from the Stack
+ pulb ; Restore B from the stack
+ rts ; Return to caller
+
+;*************************************************************************
; WriteString subroutine
;
; This subroutine will write a given null terminated string to the serial.
@@ -131,6 +302,35 @@ 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 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
+ 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
+ bra readLoop ; branch always to readLoop
+doneRead ldaa #LF ; Load Line Feed into A
+ jsr putchar ; Write LF to terminal
+ pulx ; Restore X from the stack
+ pula ; restore A from the stack
+ rts ; return to caller
+
+;*************************************************************************
; TurnOnLED subroutine
;
; This subroutine will dim turn on a specified LED
@@ -224,7 +424,7 @@ LowToHigh
psha ; Save accumulator A to the stack
ldaa #0 ; load 100 into accumulator A
increase cmpa #100 ; Compare A to 100
- beq mainLoop ; Test if A == 100, jump to mainLoop
+ beq doneInc ; Test if A == 100, jump to doneInc
staa LEVEL ; Save A to LEVEL
jsr dimmer ; jump to dimmer subroutine
jsr dimmer ; jump to dimmer subroutine
@@ -328,6 +528,38 @@ getchar brclr SCISR1,#%00100000,getchar7 ; If no input on SCI port, r
getchar7 clra ; Set A to 0
rts ; Return to caller
+**************************************************************************
+* Data Section: address used [ $3100 to $3FFF ] RAM Memory
+*
+
+; unknown: string to warn the user of unknown output
+unknown dc.b 'Error: Unknown Command',CR,LF,NULL
+
+; twMsg: welcome message when type writer loads
+twMsg dc.b 'Welcome to Type Writer, you may type below.',CR,LF,NULL
+
+; Below are strings of the options to compare in CheckInput
+option1 dc.b 'L1',NULL
+option2 dc.b 'F1',NULL
+option3 dc.b 'L2',NULL
+option4 dc.b 'F2',NULL
+option5 dc.b 'L3',NULL
+option6 dc.b 'F3',NULL
+option7 dc.b 'L4',NULL
+option8 dc.b 'F4',NULL
+option9 dc.b 'QUIT',NULL
+
+; msg: this is the main option menu string
+msg dc.b 'L1: Turn on LED1',CR,LF
+ dc.b 'F1: Turn off LED1',CR,LF
+ dc.b 'L2: Turn on LED2',CR,LF
+ dc.b 'F2: Turn off LED2',CR,LF
+ dc.b 'L3: Turn on LED3',CR,LF
+ dc.b 'F3: Turn off LED3',CR,LF
+ dc.b 'L4: LED4 goes from 0% light level to 100% light level in 0.4 seconds',CR,LF
+ dc.b 'F4: LED4 goes from 100% light level to 0% light level in 0.4 seconds',CR,LF
+ dc.b 'QUIT: Quit menu program, run Type writer program.',CR,LF,NULL
+
end ; last line of the file