Hello! Every system needs lights. Well With this driver there can be a lot of lights. I wrote this against 5.5 Today's big merge might make this useless or at least require some tweaking.
While writing this driver I spend some time finding from .lst file which registers are allowed to use and how the word should be written. I think there should be some documentation or tips at least how to write assembler words. I wrote some notes. It was my own stupidity to try sbiw temp0, 1 but took a while to notice and then think the alternative for it. Link to this kind of quirks and workarounds would be nice to have in docs too. I wrote some kind of ugly delay macro. Something like that could be useful. I noticed make doesn't start compilation if words/foo.asm is edited in project. Might be good idea to add that to the line. The driver can be used like this: 21 buffer: rgb : rgb-test 21 0 do rgb i + c! loop rgb 21 ws2811.write ; $ff $ff $ff $ff $ff 0 $ff 0 $ff 0 $ff $ff $ff 0 0 0 $ff 0 0 0 $ff rgb-test 5000 ms 21 ws2811.off ws2811.asm: ; Hannu Vuolasaho 2014 ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 2 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see <http://www.gnu.org/licenses/>. ; Device driver for WS2811 LED drivers. ; Rather stupid delay system. ; The 1000ns macro takes care the half clocks from 250ns delay. eight_cycle_delay: ret .macro wait_cycles .set busy_wait = ((@0 * @1) / F_CPU) .if (busy_wait & 16) call eight_cycle_delay call eight_cycle_delay .message "16 cycle" .endif .if (busy_wait & 8) call eight_cycle_delay .message "8 cycle" .endif .if (busy_wait & 4) .message "4 cycle" rjmp pc+1 rjmp pc+1 .endif .if (busy_wait & 2) .message "2 cycle" rjmp pc+1 .endif .if (busy_wait & 1) .message "1 cycle" nop .endif .endmacro .if (F_CPU < 8000000) .error "WS2811 800 kHz driver can't work. F_CPU too slow" .endif .macro ns250_fill_delay wait_cycles 3, 20000000 .endmacro .macro ns1000_fill_delay wait_cycles 9, 20000000 .endmacro .set WS2811_DDR=(WS2811_PORT-1) ;****f* WS2811.WRITE ; NAME ; WS2811.WRITE ; SYNOPSIS ; WS2811.WRITE ( addr len -- ) Write array of 8-bit RGB values to LED chain. ; DESCRIPTION ; Write RGB values to WS2811 device chain. ;****** ; ( addr len -- ) ; Hardware ; Write to WS2811 devices VE_WS2811_WRITE: .dw $ff0c .db "ws2811.write" .dw VE_HEAD .set VE_HEAD = VE_WS2811_WRITE XT_WS2811_WRITE: .dw PFA_WS2811_WRITE PFA_WS2811_WRITE: ; Reset WS2811 sbi WS2811_DDR, WS2811_BIT; Set as output ;Write zero cbi WS2811_PORT, WS2811_BIT; Write zero delay 50 ; Wait 50 usec ; Prepare to write movw temp0, tosl ; len loadtos movw Z, tosl ; addr in temp2, WS2811_PORT ; zero value cbr temp2, (1 << WS2811_BIT) mov temp3, temp2 ; one value sbr temp3, (1 << WS2811_BIT) ; Save status register and disable interrupts. This is critical. in temp4, SREG cli PFA_WS2811_WRITE_START: ldi temp6, 7 ; Bit counter to 7 ld temp5, Z+ ; Load from Z to PFA_WS2811_WRITE_CLK_6: nop PFA_WS2811_WRITE_CLK_7: nop ns1000_fill_delay out WS2811_PORT, temp2 ; Pin DOWN PFA_WS2811_WRITE_CLK_9: lsl temp5 ; MSB to carry ns250_fill_delay PFA_WS2811_WRITE_CLK_0: out WS2811_PORT, temp3 ; Pin UP ns250_fill_delay brcs PFA_WS2811_WRITE_CLK_3; If carry set jump CLK_3 out WS2811_PORT, temp2 ; Carry not set, pin DOWN PFA_WS2811_WRITE_CLK_3: dec temp6 ; Bit counter -1 brne PFA_WS2811_WRITE_CLK_6 ; Jump CLK_6 if bits left to send from byte. lsl temp5 ; MSB to carry brcc PFA_WS2811_WRITE_LOAD_CLOCK_8 ; If carry clear jump ldi temp6, 7 ; Bit counter to 7 ns1000_fill_delay out WS2811_PORT, temp2 ; Pin DOWN nop ns250_fill_delay out WS2811_PORT, temp3 ; Pin UP ns250_fill_delay subi temp0, 1 ; Byte counter -1 sbci temp1, 0 ; sbiw equivalent ;sbiw temp0, 1 ; Byte counter -1 ld temp5, Z+ ; Next byte brne PFA_WS2811_WRITE_CLK_7 ; Jump CLK_7 if byte counter 0 ns1000_fill_delay rjmp PFA_WS2811_WRITE_EXIT_CLK_8 ; jump to end PFA_WS2811_WRITE_LOAD_CLOCK_8: ns1000_fill_delay out WS2811_PORT, temp2 ; Pin DOWN ldi temp6, 7 ns250_fill_delay out WS2811_PORT, temp3 ; Pin UP nop ns250_fill_delay out WS2811_PORT, temp2 ; Pin DOWN ns1000_fill_delay subi temp0, 1 ; Byte counter -1 sbci temp1, 0 ; sbiw equivalent; ;sbiw temp0, 1 ; Byte counter -1 ld temp5, Z+ ; Next byte brne PFA_WS2811_WRITE_CLK_9 ; Jump CLK_9 if byte count != 0 PFA_WS2811_WRITE_EXIT_CLK_8: out WS2811_PORT, temp2 ; Pin DOWN nop ns250_fill_delay out WS2811_PORT, temp3 ; Pin UP out SREG, temp4 loadtos ; dump the temp value from tos jmp_ DO_NEXT ;****f* WS2811.OFF ; NAME ; WS2811.OFF ; SYNOPSIS ; WS2811.OFF ( n -- ) shut off n ws2811 leds. ; DESCRIPTION ; Simple loop which write zero to chain n * 3 times. ;****** ; ( n -- ) ; Hardware ; Write to WS2811 devices VE_WS2811_OFF: .dw $ff0a .db "ws2811.off" .dw VE_HEAD .set VE_HEAD = VE_WS2811_OFF XT_WS2811_OFF: .dw PFA_WS2811_OFF PFA_WS2811_OFF: ; Reset WS2811 sbi WS2811_DDR, WS2811_BIT; Set as output ;Write zero cbi WS2811_PORT, WS2811_BIT; Write zero delay 50 ; Wait 50 usec in temp4, SREG cli PFA_WS2811_RESET_LOOP: sbi WS2811_PORT, WS2811_BIT; Write one ns250_fill_delay cbi WS2811_PORT, WS2811_BIT; Write zero sbiw tosl, 1 wait_cycles 15, 20000000 brne PFA_WS2811_RESET_LOOP out SREG, temp0 loadtos ; dump the temp value from tos jmp_ DO_NEXT ------------------------------------------------------------------------------ Comprehensive Server Monitoring with Site24x7. Monitor 10 servers for $9/Month. Get alerted through email, SMS, voice calls or mobile push notifications. Take corrective actions from your mobile device. http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk _______________________________________________ Amforth-devel mailing list for http://amforth.sf.net/ Amforth-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/amforth-devel