/*
 *Aufgabe 5.3
 *
 *  Created on: 16.01.2021
 *      Author: Julia Kisela
 */
.text /* Specify that code goes in text segment */

.equ IOPIN0, 0xE0028000 // Port 0 Pin value register address
.equ IODIR1, 0xE0028018 // Port 1 Direction register address
.equ IOSET1, 0xE0028014 // Port 1 Output set register address
.equ IOCLR1, 0xE002801C // Port 1 Output clear register
.equ BUTTON_1, 0x00000400 // Button 1 mask
.equ BUTTON_2, 0x00000800 // Button 2 mask
.equ BUTTON_3, 0x00001000 // Button 3 mask
.equ BUTTON_4, 0x00002000 // Button 4 mask

.code 32 /* Select ARM instruction set */

.global _startup /* Specify global symbol */
_startup:
	ldr sp, =0x40001000

	ldr r1, =IODIR1 // point to port 1 direction register
	ldr r2, =IOSET1 // pointer to port 1 pin set control register
	ldr r3, =IOCLR1 // pointer to port 1 pin clear control register
	ldr r4, =IOPIN0 // pointer to port 0 input register
	ldr r5, =BUTTON_1 // load Button 1 mask to register r1
	ldr r6, =BUTTON_2 // load Button 2 mask to register r2
	ldr r7, =BUTTON_3 // load Button 3 mask to register r3
	ldr r8, =BUTTON_4 // load Button 4 mask to register r4

	ldr r0, =0x00ff0000 // set P1.16 to P1.23 as ...
	str r0, [r1] // ... outputs

loop:
	mov r9, #0x10000 // LED 1 (or 2)
	mov r10, r5 // button 1
	bl read_button

	mov r9, #0x10000
	mov r9, r9, lsl #2 // LED 3 (or 4)
	mov r10, r6 // button 2
	bl read_button

	mov r9, #0x10000
	mov r9, r9, lsl #4 // LED 5 (or 6)
	mov r10, r7 // button 3
	bl read_button

	mov r9, #0x10000
	mov r9, r9, lsl #6 // LED 7 (or 8)
	mov r10, r8 // button 1
	bl read_button

	b loop

stop:
nop
bal stop

// read_button: read button with mask from r10, turn LED stored in r9 or r9 << 1 on
// doesn't use standard call convention because the provided example code isn't compatible with it
read_button:
	stmfd sp!, {lr} /* Speichern des lr auf Stack */
	ldr r0, [r4] // Load pushbutton values to register r0 (IOPIN0)
	ands r0, r10, r0 // check if button 1 is pressed
	beq noled // branch if not
	str r9, [r2] // button pressed, turn selected pin on (IOSET1)
	mov r9, r9, lsl #1 // increment output value
	str r9, [r3] // turn selected pin off (IOCLR1)
	b led_done
noled: // button not pressed
	str r9, [r3] // turn selected pin off
	mov r9, r9, lsl #1 // increment output value
	str r9, [r2] // turn selected pin on
led_done:
	ldmfd sp!, {pc} /* Lesen des pc vom Stack */

.end
