Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- AREA GPIO, CODE, READWRITE
- EXPORT uart_init
- EXPORT pin_connect_block_setup
- EXPORT read_from_push_btns
- EXPORT illuminate_RGB_LED
- EXPORT illuminate_LEDs
- EXPORT write_to_7_segs
- EXPORT read_character
- EXPORT output_character
- EXPORT output_string
- EXPORT read_string
- EXPORT div_and_mod
- U0LSR EQU 0x14
- null_char EQU 0x0 ; Null character (\0)
- button_result = "The number you input is: ",0
- ALIGN
- digits_SET
- clear DCD 0x0000B780
- char0 DCD 0x00003780 ; 0
- char1 DCD 0x00000300 ; 1
- char2 DCD 0x00009580 ; 2
- char3 DCD 0x00008780 ; 3
- char4 DCD 0x0000A300 ; 4
- char5 DCD 0x0000A680 ; 5
- char6 DCD 0x0000B680 ; 6
- char7 DCD 0x00000380 ; 7
- char8 DCD 0x0000B780 ; 8
- char9 DCD 0x0000A380 ; 9
- charA DCD 0x0000B380 ; A
- charB DCD 0x0000B600 ; B
- charC DCD 0x00003480 ; C
- charD DCD 0x00009700 ; D
- charE DCD 0x0000B480 ; E
- charF DCD 0x0000B080 ; F
- ALIGN
- uart_init
- STMFD sp!, {r0, r1, r2, lr}
- LDR r0, =0xE000C00C ; UART0 Line Control Register Address (U0LCR)
- LDRB r2, [r0] ; Load U0LCR into r2
- MOV r2, #131 ; Enable Divisor Latch Access Bit (DLAB)
- STRB r2, [r0]
- SUB r0, r0, #0xC ; Base Address of Lower Divisor Latch is 0xE000C000 (U0DLL)
- LDRB r1, [r0]
- MOV r1, #120
- STRB r1, [r0] ; Store LSB value for 9,600 Baud in U0DLL
- ADD r0, r0, #0x4 ; Base Address of Upper Divisor Latch is 0xE000C004 (U0DLM)
- LDRB r1, [r0]
- MOV r1, #0
- STRB r1, [r0] ; Store MSB value for 9,600 Baud in U0DLM
- ADD r0, r0, #8 ; UART0 Line Control Register Address (U0LCR)
- MOV r2, #3 ; 8-bit word length, 1 stop bit, no parity
- STRB r2, [r0] ; disable break control, disable divisor latch access
- LDMFD sp!, {r0, r1, r2, lr}
- BX lr
- ; (DIGIT) P0.2-P0.5
- ; (7-SEG) P0.7-P0.10, P0.12, P0.13
- ; (RGB LED) P0.17, P0.18, P0.21
- pin_connect_block_setup ; Conserves r0, r1, r2 and sets GPIO directions
- STMFD sp!, {r0, r1-r2}
- LDR r0, =0xE002C000 ; PINSEL0
- LDR r1, [r0] ; (DIGIT) P0.2-P0.5 & (7-SEG) P0.7-P0.10, P0.12, P0.13, P0.15
- LDR r2, =0xCF3FCFFA
- BIC r1, r1, r2 ; Clear DIGIT & 7-SEG (00 = GPIO)
- ORR r1, r1, #5 ; (UART0) P0.0, P0.1 (01 = UART0)
- STR r1, [r0]
- LDR r0, =0xE002C004 ; PINSEL1
- LDR r1, [r0] ; (RGB LED) P0.17, P0.18, P0.21
- LDR r2, =0x00000C3C
- BIC r1, r1, r2 ; Clear P0.17, P0.18, P0.21 (00 = GPIO)
- STR r1, [r0]
- LDR r0, =0xE0028008 ; IO0DIR Set pin directions
- LDR r1, [r0] ; Output (set to 1) P0.2-P0.5, P0.7-P0.10,P0.12,
- LDR r2, =0x0026B7BC
- ORR r1, r1, r2 ; P0.13, P0.15, P0.17, P0.18, P0.21
- STR r1, [r0]
- LDR r0, =0xE0028018 ; IO1DIR Set pin directions Do we need this? Yes
- LDR r1, [r0]
- LDR r2, =0x000F0000
- ORR r1, r1, r2
- STR r1, [r0]
- LDMFD sp!, {r0, r1, r2}
- BX lr
- read_from_push_btns ; Reads push buttons, returns value in r0. Conserves registers
- STMFD sp!, {lr, r0-r4}
- BL read_character
- CMP r0, #0x20 ; Check if character is Space
- LDR r1, =0xE0028010 ; Address of Port 1 Pin Value Register
- BNE read_from_push_btns
- LDREQ r2, [r1] ; Load Pin Value Register
- LDR r3, = 0x00F00000 ; Load Mask
- AND r2, r2, r3 ; Mask Pin Values to extract button values
- EOR r2, r2, r3
- MOV r0, r2, LSR #20 ; Shift button values to bits 0-3
- ; Reverse bits
- MOV r3, #0 ; Clear register for running sum
- AND r1, r0, #1 ;
- MOV r1, r1, LSL #3 ; Mask to extract bit 0 and move to bit 3
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #2 ;
- MOV r1, r1, LSL #1 ; Mask to extract bit 1 and move to bit 2
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #4 ;
- MOV r1, r1, LSR #1 ; Mask to extract bit 2 and move to bit 1
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #8 ;
- MOV r1, r1, LSR #3 ; Mask to extract bit 3 and move to bit 0
- ADD r3, r3, r1 ; Add to running sum
- MOV r0, r3 ; Move running sum back for display
- LDR r4, =button_result
- BL output_string
- CMP r0, #10 ;
- BGE greater_than_ten
- ADD r0, r0, #0x30 ;
- BL output_character ; Display digit if less than 10
- B done
- greater_than_ten
- MOV r1, r0
- MOV r0, #0x31 ;
- BL output_character ; Display 1 if digit is greater than 10
- SUB r0, r1, #10 ;
- ADD r0, r0, #0x30 ;
- BL output_character ; Then display value mod 10 if greater than 10
- done
- MOV r0, #0x0A ;
- BL output_character ;
- BL output_character
- MOV r0, #0x0D ;
- BL output_character ; New line for formatting
- LDMFD sp!, {lr, r0-r4}
- BX LR
- illuminate_RGB_LED ; Desired colour passed in r0, Conserves registers r0-r4 + lr
- STMFD sp!, {lr, r0-r4}
- LDR r1, =0xE0028004 ; IO0SET
- LDR r2, =0xE002800C ; IO0CLR
- LDR r3, [r2]
- LDR r4, [r1]
- AND r3, r3, #0x0 ; Reset Output Register
- AND r4, r4, #0x00260000 ; IO0CLR, turn off all LEDS (17. 18, 21) first
- STR r4, [r1] ; Store reset Clear register
- ; On is 0, not 1?
- CMP r0, #0x6F ; ascii o for off
- ORREQ r4, r4, #0x00260000
- STREQ r4, [r1]
- BEQ RGB_DONE
- CMP r0, #0x72 ; ascii r for red
- ORREQ r3, r3, #0x00020000 ; Output red (17)
- BEQ RGB_DONE
- CMP r0, #0x67 ; ascii g for green
- ORREQ r3, r3, #0x00200000 ; Output green (21)
- BEQ RGB_DONE
- CMP r0, #0x62 ; ascii b for blue
- ORREQ r3, r3, #0x00040000 ; Output blue (18)
- BEQ RGB_DONE
- CMP r0, #0x70 ; ascii p for purple
- ORREQ r3, r3, #0x00060000 ; Output purple (17 + 18)
- BEQ RGB_DONE
- CMP r0, #0x79 ; ascii y for yellow
- ORREQ r3, r3, #0x00220000 ; Output yellow (17 + 21)
- BEQ RGB_DONE
- CMP r0, #0x77 ; ascii w for white
- ORREQ r3, r3, #0x00260000 ; Output white (17 + 18 + 21)
- BEQ RGB_DONE
- RGB_DONE
- STR r3, [r2] ; Store colour combo in IO0SET
- LDMFD sp!, {lr, r0-r4}
- BX LR
- illuminate_LEDs ; conserves registers r0-r3, pattern in r0
- STMFD sp!, {lr, r0-r3}
- LDR r1, =0xE0028014 ; Address of Output Set Register
- LDR r2, =0xE002801C ; Address of Output Clear Register
- MOV r3, #0xF ;
- MOV r3, r3, LSL #16 ; Shift pattern to correct pins
- STR r3, [r1] ; Clear LEDs
- ; Reverse bits
- MOV r3, #0 ; Clear register for running sum
- AND r1, r0, #1 ;
- MOV r1, r1, LSL #3 ; Mask to extract bit 0 and move to bit 3
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #2 ;
- MOV r1, r1, LSL #1 ; Mask to extract bit 1 and move to bit 2
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #4 ;
- MOV r1, r1, LSR #1 ; Mask to extract bit 2 and move to bit 1
- ADD r3, r3, r1 ; Add to running sum
- AND r1, r0, #8 ;
- MOV r1, r1, LSR #3 ; Mask to extract bit 3 and move to bit 0
- ADD r3, r3, r1 ; Add to running sum
- MOV r0, r3 ; Move running sum back for display
- MOV r0, r0, LSL #16 ; Shift pattern to correct pins
- STR r0, [r2] ; Illuminate LEDs
- LDMFD sp!, {lr, r0-r3}
- BX LR
- write_to_7_segs
- STMFD sp!, {lr, r0-r5} ; Store link register and gp registers to stack
- LDR r2, =0xE0028004 ; Address of Output Set Register
- LDR r3, =0xE002800C ; Address of Output Clear Register
- LDR r4, =0x3C
- STR r4, [r2]
- CMP r1, #0x30
- LDREQ r4, =0x04
- CMP r1, #0x31
- LDREQ r4, =0x08
- CMP r1, #0x32
- LDREQ r4, =0x10
- CMP r1, #0x33
- LDREQ r4, =0x20
- STR r4, [r3]
- CMP r0, #0x30 ; Check if character is 0
- LDREQ r4, char0 ; Store seg values for 0 in r4
- CMP r0, #0x31 ; Check if character is 1
- LDREQ r4, char1 ; Store seg values for 1 in r4
- CMP r0, #0x32 ; Check if character is 2
- LDREQ r4, char2 ; Store seg values for 2 in r4
- CMP r0, #0x33 ; Check if character is 3
- LDREQ r4, char3 ; Store seg values for 3 in r4
- CMP r0, #0x34 ; Check if character is 4
- LDREQ r4, char4 ; Store seg values for 4 in r4
- CMP r0, #0x35 ; Check if character is 5
- LDREQ r4, char5 ; Store seg values for 5 in r4
- CMP r0, #0x36 ; Check if character is 6
- LDREQ r4, char6 ; Store seg values for 6 in r4
- CMP r0, #0x37 ; Check if character is 7
- LDREQ r4, char7 ; Store seg values for 7 in r4
- CMP r0, #0x38 ; Check if character is 8
- LDREQ r4, char8 ; Store seg values for 8 in r4
- CMP r0, #0x39 ; Check if character is 9
- LDREQ r4, char9 ; Store seg values for 9 in r4
- CMP r0, #0x61 ; Check if character is a
- LDREQ r4, charA ; Store seg values for a in r4
- CMP r0, #0x62 ; Check if character is b
- LDREQ r4, charB ; Store seg values for b in r4
- CMP r0, #0x63 ; Check if character is c
- LDREQ r4, charC ; Store seg values for c in r4
- CMP r0, #0x64 ; Check if character is d
- LDREQ r4, charD ; Store seg values for d in r4
- CMP r0, #0x65 ; Check if character is e
- LDREQ r4, charE ; Store seg values for e in r4
- CMP r0, #0x66 ; Check if character is f
- LDREQ r4, charF ; Store seg values for f in r4
- LDR r5, clear ;
- STR r5, [r3] ; Clear segments
- STR r4, [r2] ; Set segs to value
- LDMFD sp!, {lr, r0-r5}
- BX lr
- read_character ; RETURNS character in r0
- STMFD sp!, {lr, r1-r3}
- LDR r0, =0xE000C014 ; Load line status address into r0
- POLL
- LDRB r1, [r0] ; Load in UART0 Line Status Register
- AND r1, r1, #0x00000001 ;
- CMP r1, #0x00000001 ; Check U0LSR RSR Bit (Bit 0)
- BNE POLL ; If RDR is not set, continue polling, else store byte
- SUB r0, r0, #U0LSR ; U0RBR location = (UART0 Base + U0LSR) - U0LSR
- LDRB r0, [r0] ; Load received byte to r0, to be transmitted
- LDMFD sp!, {lr, r1-r3}
- BX lr
- read_string
- STMFD sp!, {r0, r1, r4, lr}
- read_loop
- BL read_character
- BL output_character
- STRB r0, [r4] ; Store character in memory
- ADD r4, r4, #1 ; Increment memory address
- CMP r0, #13 ; Check for Enter
- BNE read_loop ; Continue reading characters until Enter
- SUB r4, r4, #1 ;
- MOV r0, #null_char ;
- STRB r0, [r4] ; Store null character at end of string
- LDMFD sp!, {r0, r1, r4, lr}
- BX lr
- output_character ; Character PASSED in r0
- STMFD sp!, {lr, r1-r3}
- LDR r1, =0xE000C014 ; Load line status address into r1
- loop
- LDRB r2, [r1] ; Load status register into r2
- AND r3, r2, #32 ; Clear all but bit 5 (32)
- CMP r3, #32 ;
- BNE loop ; Loop back if THRE is 0
- SUB r1, r1, #0x14 ; Adjust r1 to address for transmit reg
- STRB r0, [r1] ; Store byte (r0) in transmit reg
- LDMFD sp!, {lr, r1-r3}
- BX lr
- output_string ; Base address of string PASSED in r4
- STMFD sp!, {r0-r3, r5, lr} ; Store registers on stack, r2 and r3 are from output_character
- MOV r5, #0 ; r5 is offset for string in [r4], incremented by 1?
- LDRB r0, [r4] ; Store first character in r0 for output_character
- string_loop
- BL output_character ; Subroutine stores character byte in UART0 transmit reg
- ADD r5, r5, #1 ; Increment offset (r2) by 1 (next byte)
- LDRB r0, [r4, r5] ; Store first character in r0 for output_character
- CMP r0, #null_char ; Check every r4+ and transmit, until null
- BNE string_loop
- LDMFD sp!, {r0-r3, r5, lr} ; Load lr from stack, and used registers
- BX lr
- div_and_mod
- STMFD sp!, {r2-r6, lr}
- ; The dividend is passed in r10 and the divisor in r9.
- ; The quotient is returned in r10 and the remainder in r9.
- MOV r5, #0 ; Initialize flag register to use for negating quotient
- MVN r6, #0 ; Set r6 to 0xFFFFFFFF for use in sign change
- CMP r10, #0 ; Check sign of r10
- EORLT r10, r10, r6 ; Take one's complement if r10 is negative
- ADDLT r10, r10, #1 ; Add one for two's complement
- EORLT r5, r5, #1 ; Flip flag register if negative
- CMP r9, #0 ; Check sign of r9
- EORLT r9, r9, r6 ; One's complement if r9 is negative
- ADDLT r9, r9, #1 ; Add one for two's complement
- EORLT r5, r5, #1 ; Flip flag register if negative
- MOV r2, #16 ; Initialize counter
- MOV r3, #0 ; Initialize quotient to 0
- MOV r9, r9, LSL #15 ; Shift divisor 15 places
- MOV r4, r10 ; Initialize remainder to dividend
- divide_loop
- SUB r2, r2, #1 ; Decrement counter
- SUB r4, r4, r9 ; Subtract divisor from remainder
- CMP r4, #0 ;
- BLT divide_negative ; Branch if remainder is negative
- MOV r3, r3, LSL #1 ;
- ADD r3, r3, #1 ; Shift 1 into LSB of quotient
- B next ; Branch to next
- divide_negative
- ADD r4, r4, r9 ; Reset remainder by re-adding divisor
- MOV r3, r3, LSL #1 ; Shift 0 into LSB
- next
- MOV r9, r9, LSR #1 ; Shift divisor to next bit
- CMP r2, #0 ;
- BGT divide_loop ; Loop if counter is not 0
- MOV r10, r3 ; Move quotient to r10
- MOV r9, r4 ; Move remainder to r9
- CMP r5, #1 ; Check flag register
- EOREQ r10, r10, r6 ; One's complement if flag is 1
- ADDEQ r10, r10, #1 ; Add one for two's complement
- LDMFD sp!, {r2-r6, lr}
- BX lr ; Return to the C program
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement