Last active
November 6, 2021 16:56
-
-
Save nrdmn/b1331feb1936b9bc3410f0b926b81490 to your computer and use it in GitHub Desktop.
ws2812 for avr, 16 MHz. follows gcc abi, restores interrupts if necessary. 64 bytes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.equ PORTB, 5 | |
; void ws2812(const char *ptr, const size_t n); | |
.global ws2812 | |
ws2812: | |
; Move ptr (r24, r25) to X (r26, r27) | |
movw X, r24 | |
; Move n (r22, r23) to r24, r25 | |
movw r24, r22 | |
; r1 starts out as zero | |
; Are interrupts disabled? If yes, skip | |
brid 1f | |
; If not, set r1 to 0xff | |
dec r1 | |
1: | |
; Disable interrupts | |
cli | |
2: | |
; Main loop starts here | |
; T = 11 | |
; Decrement n | |
sbiw r24, 1 | |
; T = 13 | |
; Turn off IO port in case it is still on | |
cbi PORTB, 5 | |
; T = 15 | |
; If decrement underflowed, exit loop | |
brlt 8f | |
; We're looking at a new byte here | |
; T = 16 | |
; Set our bit index to 8 ... | |
ldi r19, 8 | |
; T = 17 | |
; ... and fetch byte from *X, incrementing X afterwards | |
ld r18, X+ | |
3: | |
; T = 19 | |
; Left-shift the byte we have fetched ... | |
lsl r18 | |
; T = 0 | |
; Bit starts here | |
sbi PORTB, 5 | |
; T = 2 | |
; Wait two clock cycles | |
rjmp 4f | |
4: | |
; T = 4 | |
; ... and branch if MSB was 0 | |
brcc 7f | |
; If we're here, we're sending a '1' bit | |
; T = 5 | |
; Wait three clock cycles | |
lpm | |
; T = 8 | |
; Decrement bit index | |
dec r19 | |
; T = 9 | |
; If bit index hit zero, branch to start | |
breq 2b | |
; T = 10 | |
; Otherwise, wait three more clock cycles | |
lpm | |
5: | |
; T = 13 | |
; Turn off IO port in case it is still on | |
cbi PORTB, 5 | |
; T = 15 | |
; Wait two clock cycles | |
rjmp 6f | |
6: | |
; T = 17 | |
; Go process the next bit | |
rjmp 3b | |
7: | |
; Here, we're sending a 0 bit | |
; T = 6 | |
; Decrement bit index | |
dec r19 | |
; T = 7 | |
; Turn off IO port | |
cbi PORTB, 5 | |
; T = 9 | |
; If bit index hit zero, branch to start | |
breq 2b | |
; T = 10 | |
; Otherwise, finish this bit and process the next | |
jmp 5b | |
8: | |
; End of loop | |
; If interrupts were disabled, skip | |
sbrc r1, 0 | |
; Otherwise, re-enable them | |
sei | |
; r1 can be 0 or 0xff | |
; Either way, decrement until it is 0 again | |
; The following loop wait approximately 64 us | |
9: | |
nop | |
dec r1 | |
brne 9b | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment