Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;*-------------------------------------------------------------------
- ;* Name: lab_4_program.s
- ;* Purpose: A sample style for lab-4
- ;* Term: Winter 2013
- ;*-------------------------------------------------------------------
- THUMB ; Declare THUMB instruction set
- AREA My_code, CODE, READONLY ;
- EXPORT __MAIN ; Label __MAIN is used externally
- EXPORT EINT3_IRQHandler ; We do this to override the default behaviour
- ENTRY
- __MAIN
- ; The following lines are similar to previous labs.
- ; They just turn off all LEDs
- LDR R10, =LED_BASE_ADR ; R10 is a pointer to the base address for the LEDs
- MOV R3, #0xB0000000
- STR R3, [r10, #0x20] ; Turn off three LEDs on port 1
- MOV R3, #0x0000007C
- STR R3, [R10, #0x40] ; Turn off five LEDs on port 2
- ; This line is very important in your main program
- ; Initializes R11 to a 16-bit non-zero value and NOTHING else can write to R11 !!
- MOV R11, #0xABCD ; Init the random number generator with a non-zero number
- ; Generate a 16 bit random number
- BL RNG
- ; R11 has a random number 16 bits in length. We store that in r0.
- MOV R0, R11
- ; We will use these values later.
- MOV R8, #0x64 ; 100
- MOV R12, #0x7A ; 122
- ; roundabout way of getting the the randomly generated 16 bits. We shift them 16 bits to the left to get rid of the garbage top 16 bits, then we shift back to the
- ; right to get the proper 16 bit number back.
- LSL R0, R0, #16
- LSR R0, R0, #16
- ; Now, the max number that can be generated from the random number generator is 2^16 - 1, i.e 65535. Now, first, we want to generate
- ; a 0 - 8 second delay, so we want to scale 65535 to 80000, which is why we multiply the value in r0 by 122.
- ; Then we divide by a 100, becayuse we want to scale the number
- ; up by a factor of 1.22 as the max value is 65535 to 80,000. This value, when passed to the delay method, will
- ; generate a 0 - 8 second delay
- MUL R0, R12
- UDIV R0, R8
- ; we move 20000 into r1
- MOV R1, #0x4e20
- ; offsets the delay 2 by adding 20000 to r0, so our delay will be from 2 - 10 seconds.
- ADD R0, R0, R1 ; 20000 in hex (2 seconds)
- ; R5 will count up to R0 and we'll be done it'll increment by 2500
- MOV R5, #0x9C4
- ; and R5 will count up to R7 so we'll move R0
- MOV R7, R0
- ; Now we want to turn LEDs 3 on port 1 ON and then 4 on port 2 off and switch
- loopLEDSOnAndOff
- ; ; we need the 3 leds on port 1 on first so 31, 29, 28 bits need to be 0 while the rest are 1
- ; ; that ends up being 0x4FFFFFFF
- MOV R4, #0x000F
- BL DISPLAY_NUM
- ; ; we need a delay of 0.25s which is 250ms which means 2500*0.1ms = 250ms
- MOV R0, #0x9C4 ; this 2500 in hex
- BL DELAY
- ; Let's decrement by 2500
- SUBS R7, R7, R5
- BLE randomNumberDone
- MOV R4, #0x00F0
- BL DISPLAY_NUM
- ; we'll also delay for another 0.25 seconds before looping again
- MOV R0, #0x9C4 ; this is 2500 in hex
- BL DELAY
- SUBS R7, R7, R5
- BLE randomNumberDone
- B loopLEDSOnAndOff
- randomNumberDone
- ; initialize R6 to 1, and later on check
- LDR R9, =ISER0 ;
- MOV R8, #0x200000
- STR R8, [R9] ; This will set the twenty first bit as 1
- LDR R9, =IO2IntEnf ; Pointer to GPIO Interrupt Enable for port 2 Falling Edge
- LDR R8, [R9]
- ORR R8, #0x400 ; This number, in binary, has its tenth bit as 1.
- STR R8, [R9] ; This will set the tenth bit as 1.
- ; increment this counter with a 0.1 delay and poll for INT0
- ; we'll reset out counter (R4) to 0 before we start
- ; the loop
- MOV R4, #0x0
- ; We only want to delay by 1ms, so we move 1 into r0.
- MOV R0, #0x10
- ; R5 and R7 will be used for the LEDS
- MOV R7, #0xFF
- ; R6 is initalized with 1
- MOV R6, #0x1
- flashLedsAndCount
- ; we need to flip the bits so we can use eors
- EOR R7, #0xFF ; flips port 2 leds
- MOV R5, R4
- MOV R4, R7
- BL DISPLAY_NUM
- MOV R4, R5
- ; we'll use R8 to basically count up to some frequency
- ; while also incrementing R4 (which is the elapsed time)
- MOV R8, #0x64 ; this is 100
- loopCountDelay
- ; for 1ms
- MOV R0, #0x10
- ; we start by delaying for 0.1ms.
- BL DELAY
- ; after the delay, we increment the counter.
- ADD R4, R4, #1
- ; we'll do a check in the middle of the inner loop
- ; just incase if the isr was called in here and we
- ; need to handle R6's 0 value
- CMP R6, #0x0
- BEQ displayTheNumber
- SUBS R8, R8, #0x1
- BNE loopCountDelay
- ; we should check if the ISR basically set R6 to 0 or not
- CMP R6, #0x0
- BEQ displayTheNumber
- B flashLedsAndCount
- displayTheNumber
- ; now we can display the number
- BL DISPLAY_NUM
- MOV R0, #0xc350 ; about 5 seconds delay, before we display the number again.
- BL DELAY
- B displayTheNumber
- ;*-------------------------------------------------------------------
- ; Subroutine RNG ... Generates a pseudo-Random Number in R11
- ;*-------------------------------------------------------------------
- ; R11 holds a random number as per the Linear feedback shift register (Fibonacci) on WikiPedia
- ; R11 MUST be initialized to a non-zero 16-bit value at the start of the program
- ; R11 can be read anywhere in the code but must only be written to by this subroutine
- RNG STMFD R13!,{R1-R3, R14} ; Random Number Generator
- AND R1, R11, #0x8000
- AND R2, R11, #0x2000
- LSL R2, #2
- EOR R3, R1, R2
- AND R1, R11, #0x1000
- LSL R1, #3
- EOR R3, R3, R1
- AND R1, R11, #0x0400
- LSL R1, #5
- EOR R3, R3, R1 ; The new bit to go into the LSB is present
- LSR R3, #15
- LSL R11, #1
- ORR R11, R11, R3
- LDMFD R13!,{R1-R3, R15}
- ;*-------------------------------------------------------------------
- ; Subroutine DELAY ... Causes a delay of 1ms * R0 times
- ;*-------------------------------------------------------------------
- ; aim for better than 10% accuracy
- DELAY STMFD R13!,{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
- ; About 0.1ms
- MOV R4, #0x80
- delayLoopR4Times
- SUBS R4, R4, #1
- BNE delayLoopR4Times
- SUBS R0, R0, #1
- BNE MultipleDelay
- exitDelay LDMFD R13!,{R4, R15}
- ; This procedure Displays the number in R4 onto the 8 LEDs
- ; We start by storing the registers we modify on the stack
- DISPLAY_NUM STMFD R13!,{R2, R3, R4, R5, R6, R7, R14}
- displayAgainLoop
- MOV R2, #0x0 ; This will hold the bit values for the port 1 LEDs
- MOV R3, #0x0 ; This will hold the bit values for the port 2 LEDs
- MOV R5, R4
- LSL R5, #24
- LSR R5, #24
- ; reverse the bits
- RBIT R5, R5
- LSR R5, #24
- EOR R5, R5, #0xFF
- ; grabs the last 2 bits and stores them in R6
- LSL R6, R5, #30
- ; r6 has the bits in 31 and 30 we move it down to 29 and 28
- LSR R6, R6, #2
- ; grabs the third last bit
- AND R7, R5, #0x4
- ; we move it into it`s position
- LSL R7, R7, #29
- ORR R6, R7, R6
- ; r6 now has the proper stuff for port1
- STR R6, [R10, #0x20]
- LSR R7, R5, #1
- AND R7, R7, #0x7C
- STR R7, [R10, #0x40]
- LSR R4, R4, #8 ; When we've displayed the first 8 bits, we'll remove them from the register
- CMP R4, #0 ; We compare if r4 is zero. If it is, then we are done. Otherwise, we go back and do the same for the next 8 bits.
- BEQ endDisplayLoop
- ; We need to wait 2 seconds
- ; and display the next 8 bits
- ; depending on if they exist
- MOV R0, #20000
- BL DELAY
- B displayAgainLoop
- endDisplayLoop
- ; restore the values from the stack.
- LDMFD R13!,{R2, R3, R4, R5, R6, R7, R15}
- ; The Interrupt Service Routine MUST be in the startup file for simulation
- ; to work correctly. Add it where there is the label "EINT3_IRQHandler
- ;
- ;*-------------------------------------------------------------------
- ; Interrupt Service Routine (ISR) for EINT3_IRQHandler
- ;*-------------------------------------------------------------------
- ; This ISR handles the interrupt triggered when the INT0 push-button is pressed
- ; with the assumption that the interrupt activation is done in the main program
- EINT3_IRQHandler
- STMFD R13!,{R8, R9, R14} ; Use this command if you need it
- ; Lets basically just set R6 to 0
- MOV R6, #0x0
- LDR R9, =IO2IntClr ; Pointer to GPIO Interrupt Enable for port 2 Falling Edge
- LDR R8, [R9]
- ORR R8, R8, #0x400 ; This number, in binary, has its tenth bit as 1
- STR R8, [R9] ; This will set the tenth bit as 1.
- ; For debugging
- ;MOV R0, #0xc350
- ;BL DELAY
- LDMFD R13!,{R8, R9, R15} ; Use this command if you used STMFD (otherwise use BX LR)
- ;*-------------------------------------------------------------------
- ; Below is a list of useful registers with their respective memory addresses.
- ;*-------------------------------------------------------------------
- LED_BASE_ADR EQU 0x2009c000 ; Base address of the memory that controls the LEDs
- PINSEL3 EQU 0x4002C00C ; Pin Select Register 3 for P1[31:16]
- PINSEL4 EQU 0x4002C010 ; Pin Select Register 4 for P2[15:0]
- FIO1DIR EQU 0x2009C020 ; Fast Input Output Direction Register for Port 1
- FIO2DIR EQU 0x2009C040 ; Fast Input Output Direction Register for Port 2
- FIO1SET EQU 0x2009C038 ; Fast Input Output Set Register for Port 1
- FIO2SET EQU 0x2009C058 ; Fast Input Output Set Register for Port 2
- FIO1CLR EQU 0x2009C03C ; Fast Input Output Clear Register for Port 1
- FIO2CLR EQU 0x2009C05C ; Fast Input Output Clear Register for Port 2
- IO2IntEnf EQU 0x400280B4 ; GPIO Interrupt Enable for port 2 Falling Edge
- ISER0 EQU 0xE000E100 ; Interrupt Set-Enable Register 0
- IO2IntClr EQU 0x400280AC ; GPIO Interrupt Clear register for port 0
- ALIGN
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement