Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;*----------------------------------------------------------------------------
- ;* Name: Lab_2_program.s
- ;* Purpose: This code template is for Lab 2
- ;* Author: Eric Praetzel and Rasoul Keshavarzi
- ;* Lab 2 code added by: Jobair Hassan, Maaz Ali
- ;*----------------------------------------------------------------------------*/
- THUMB ; Declare THUMB instruction set
- AREA My_code, CODE, READONLY ;
- EXPORT __MAIN ; Label __MAIN is used externally q
- ENTRY
- __MAIN
- ; The following lines are similar to Lab-1 but use an address, in r4, to make it easier.
- ; Note that one still needs to use the offsets of 0x20 and 0x40 to access the ports
- ;
- ; Turn off all LEDs
- MOV R2, #0xC000 ; move 0xC000 into R2
- MOV R3, #0xB0000000 ; This value, when stored in the addresses for ports, will turn off the LED
- MOV R4, #0x0
- MOVT R4, #0x2009
- ADD R4, R4, R2 ; 0x2009C000 - the base address for dealing with the ports
- STR R3, [r4, #0x20] ; Turn off the three LEDs on port 1
- MOV R3, #0x0000007C
- STR R3, [R4, #0x40] ; Turn off five LEDs on port 2
- ResetLUT
- LDR R5, =InputLUT ; assign R5 to the address at label LUT. This address contains the word for which we will flash the morse code of.
- ;;;;;;;;;;;;;;;;;
- ; Gets the next character and converts it into morse code sequence, and stores this into R1.
- ;;;;;;;;;;;;;;;;;
- NextChar
- LDRB R0, [R5] ; Read a character to convert to Morse
- ADD R5, #1 ; point to next value for number of delays, jump by 1 byte
- TEQ R0, #0 ; If we hit 0 (null at end of the string) then reset to the start of lookup table
- BNE ProcessChar ; If we have a character process it
- MOV R0, #4 ; delay 4 extra spaces (7 total) between words
- BL DELAY
- BEQ ResetLUT
- ProcessChar BL CHAR2MORSE ; convert ASCII to Morse pattern in R1
- ; First - loop until we have a 1 bit to send
- ;
- ; This is confusing as we're shifting a 32-bit value left, but the data is ONLY in the lowest 16 bits, so test starting at bit 15 for 1 or 0
- ; Then loop thru all of the data bits:
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ; This is the main section of the program. What it essentially does is call methods like LED_ON, LED_OFF and DELAY
- ; and converts the morse code bits found in R1 into blinking LEDS depending on the bit sequence (1 or 0)
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ; We're going to assign 15 to R9 and let it count down to 0 (16 bits which is a half word, so it'll go through all of the relevant bits in R1
- MOV R9, #0xF
- ; R8 is used is a flag (to skip the first n 0 bits)
- MOV R8, #0x0
- morseCodeToLED
- ; This is our check, if we see that the counter has
- ; reached 0, we should stop processing the current character
- ; cause we're done, and move on to the next one.
- CMP R9, #0
- BLT goToNextChar
- ; Decrementing the counter, we do this
- ; after checking the counter because we
- ; want to include the 0th bit as well
- SUB R9, R9, #1
- ; We're basically initializing R6 to contain a bit sequence
- ; where the 15th bit is a 1 (00...001...000)
- ; then we'll do a bit wise and to check if the 15th bit of
- ; the morse code sequence is a 1 or a 0, depending on the result
- ; we'll either turn on the LED, or turn off the led
- ; Just before that, we make sure we do a left shift on the R1 register
- ; so the next time we go through the loop, we check the current 14th bit
- ; which will be the 15th bit after the shift.
- MOV R6, #0x8000 ; Init R6 with the value for the bit, 15th, which we wish to test
- ANDS R7, R1, R6 ; R7 gets R1 AND R6, Zero bit gets set telling us if the bit is 0 or 1
- LSL R1, R1, #1 ; shift R1 left by 1, store in R1
- BEQ turnLEDOFF; branch somewhere it's zero
- BNE turnLEDON; branch somewhere - it's not zero
- turnLEDOFF
- ; We want to skip the first
- ; n 0 bits, so if the first 1
- ; bit hasn't been encountered
- ; then go back to the starting of
- ; the loop
- CMP R8, #0x0
- BEQ morseCodeToLED
- ; Call the LED_OFF function
- ; to turn the LED_OFF
- BL LED_OFF
- ; Set a delay of 500ms (LED_OFF for 500ms)
- MOV R0, #1
- BL DELAY
- B restartLoop
- turnLEDON
- ; turn the LED ON
- BL LED_ON
- ; Since we've encountered a 1 bit
- ; we can set the flag to 1 so now if
- ; 0 bits are encountered, they will
- ; turn the LED_OFF for 500ms
- MOV R8, #0x1
- ; Set a delay for 500ms
- MOV R0, #1
- BL DELAY
- restartLoop
- ; Simply restart the loop
- ; the checks to exit will be
- ; done there
- B morseCodeToLED ; Process next char
- goToNextChar
- ; We're done processing the character
- ; we want to set a 1.5s delay before we
- ; start processing the next character
- BL LED_OFF
- MOV R0, #3
- BL DELAY
- B NextChar
- ENDLOOP B ENDLOOP ; This is the end of the main program
- ; Subroutines
- ;
- ; convert ASCII character to Morse pattern
- ; pass ASCII character in R0, output in R1
- ; index into MorseLuT must be by steps of 2 bytes
- CHAR2MORSE STMFD R13!,{R2, R14} ; push Link Register (return address) on stack
- ; Subtract 41 to get the index so we can use it for MorseLUT
- SUB R0, R0, #0x41
- ; Grab the address of MorseLUT into R2
- LDR R2, =MorseLUT
- ; Get the morse of sequence of the character into R1
- LDRH R1, [R2, R0, LSL #1]
- LDMFD R13!,{R2, R15} ; restore LR to R15 the Program Counter to return
- ; Turn the LED on, but deal with the stack in a simpler way
- ; NOTE: This method of returning from subroutine (BX LR) does NOT work if subroutines are nested!!
- ;
- LED_ON push {r2-r4} ; preserve R3 and R4 on the R13 stack
- ; MOV R2, #0xC000
- ; MOV R3, #0xB0000000
- ; MOV R4, #0x0
- ; MOVT R4, #0x2009
- ; ADD R4, R4, R2 ; 0x2009C000 - the base address for dealing with the ports
- ; Turn on address for LED on Port 1
- MOV R3, #0x0
- MOVT R3, #0xA000
- STR R3, [r4, #0x20] ; Turn ON the LED on port 1
- pop {r2-r4}
- BX LR ; branch to the address in the Link Register. Ie return to the caller
- ; Turn the LED off, but deal with the stack in the proper way
- ; the Link register gets pushed onto the stack so that subroutines can be nested
- ;
- LED_OFF STMFD R13!,{R3, R14} ; push R3 and Link Register (return address) on stack
- ; Turn off address for LED on Port 1
- MOV R3, #0x0
- MOVT R3, #0xB000
- STR R3, [R4, #0x20] ; Turn off the LED on port 1
- LDMFD R13!,{R3, R15} ; restore R3 and LR to R15 the Program Counter to return
- ; Delay 500ms * R0 times
- ; Use the delay loop from Lab-1 but loop R0 times around
- ;
- DELAY STMFD R13!,{R2, R4, R14}
- MultipleDelay TEQ R0, #0 ; test R0 to see if it's 0 - set Zero flag so you can use BEQ, BNE
- BEQ exitDelay
- ; This is likely about 1s, so we need to
- ; measure this to be around 500ms
- MOV R4, #0x0000
- MOVT R4, #0x000B ; 0x000577FF
- delayLoopR4Times
- SUBS R4, R4, #1
- BNE delayLoopR4Times
- SUBS R0, R0, #1
- BNE MultipleDelay
- exitDelay LDMFD R13!,{R2, R4, R15}
- ; We most likely don't need this
- ;BX LR
- ;
- ; Data used in the program
- ; DCB is Define Constant Byte size
- ; DCW is Define Constant Word (16-bit) size
- ; EQU is EQUate or assign a value. This takes no memory but instead of typing the same address in many places one can just use an EQU
- ;
- ALIGN ; make sure things fall on word addresses
- ; One way to provide a data to convert to Morse code is to use a string in memory.
- ; Simply read bytes of the string until the NULL or "0" is hit. This makes it very easy to loop until done.
- ;
- InputLUT DCB "SOS", 0 ; strings must be stored, and read, as BYTES
- ALIGN ; make sure things fall on word addresses
- MorseLUT
- DCW 0x17, 0x1D5, 0x75D, 0x75 ; A, B, C, D
- DCW 0x1, 0x15D, 0x1DD, 0x55 ; E, F, G, H
- DCW 0x5, 0x1777, 0x1D7, 0x175 ; I, J, K, L
- DCW 0x77, 0x1D, 0x777, 0x5DD ; M, N, O, P
- DCW 0x1DD7, 0x5D, 0x15, 0x7 ; Q, R, S, T
- DCW 0x57, 0x157, 0x177, 0x757 ; U, V, W, X
- DCW 0x1D77, 0x775 ; Y, Z
- ; One can also define an address using the EQUate directive
- ;
- LED_PORT_ADR EQU 0x2009c000 ; Base address of the memory that controls I/O like LEDs
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement