/* * 2013 by Fabian Vogt */ buffer: .word 0 .global buffer current: .word 0 .global current buffer_size: .word 0 .global buffer_size pwm: .word 128 .global pwm count: .word 2 #define BKPT .long 0xE1212374 timer_fiq: .word 0x90010000 timer_load: .word 0x90010020 load_value: ldr r12, timer_load mov r9, #1 str r9, [r12, #0xC] /* Load buffer address */ ldr r9, buffer /* Load buffer size */ ldr r10, buffer_size /* Load current position */ ldr r11, current /* Add current position to buffer */ add r9, r9, r11 /* Increment current position */ add r11, r11, #1 cmp r11, r10 /* If buffer higher than size, set to beginning */ moveq r11, #0 /* Store current position */ str r11, current /* Read unaligned byte at r9 */ and r11, r9, #0b11 sub r9, r9, r11 ldr r9, [r9] mov r11, r11, LSL #3 mov r9, r9, LSR r11 /* Store new pwm value */ strb r9, pwm mov r9, #4 str r9, count subs pc, lr, #4 do_pwm: /* Only use r8 - r12! */ ldr r8, timer_fiq ldr r9, timer_load ldr r8, [r8, #0x10] ldr r9, [r9, #0x10] cmp r8, #0 bne fast_timer_1 /* This is unnecessary, but we've got enough cpu :-) */ cmp r9, #0 bne load_value /* We shouldn't get here */ subs pc, lr, #4 fast_timer_1: /* Ack IRQ */ ldr r12, timer_fiq mov r9, #1 str r9, [r12, #0xC] /* Load GPIO value */ mov r11, #0x90000000 ldr r9, [r11, #0x14] tst r9, #0x10 /* Load pwm value */ ldrb r10, pwm /* If on, compute off length */ rsbeq r10, r10, #0xFF /* Toggle GPIO */ eor r8, r9, #0x10 /* Write GPIO */ str r8, [r11, #0x14] /* It's needed, but I don't know why :-/ */ add r10, r10, #1 mov r10, r10, LSL #1 /* Write timer load */ str r10, [r12] /* return */ subs pc, lr, #4 .global do_pwm