Hi again.
I sent a day old file last time and it had debugging stuff and ws2811.off
hadn't counter and zero made some problems.
Here is right version. Hopefully no more big bugs. Feel free to comment. I've
tested with small stripe and 20MHz F_CPU.
The communication timing is
zero bit: 250/1000 ns
one bit: 1000/250 ns
reset: 50+us
Best regards,
Hannu Vuolasaho
; 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.
; v. 20141113
; FIXED:
; ws2811.off ( n -- ) now has counter
; wait_cycles doesn't print debug data
; Zero check
; Rather stupid delay system.
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
.endif
.if (busy_wait & 8)
call eight_cycle_delay
.endif
.if (busy_wait & 4)
rjmp pc+1
rjmp pc+1
.endif
.if (busy_wait & 2)
rjmp pc+1
.endif
.if (busy_wait & 1)
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:
movw temp0, tosl ; len
loadtos
mov temp2, temp0
or temp2, temp1
brne PFA_WS2811_WRITE_CONTINUE ; jump end if zero given.
loadtos ; dump the temp value from tos
jmp_ DO_NEXT
PFA_WS2811_WRITE_CONTINUE:
; 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 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:
mov temp0, tosl
or temp0, tosh
; cpi temp0, 0
breq PFA_WS2811_OFF_END ; jump end if zero given.
; Reset WS2811
sbi WS2811_DDR, WS2811_BIT; Set as output
;Write zero
cbi WS2811_PORT, WS2811_BIT; Write zero
delay 50 ; Wait 50 usec
ldi temp3,24
in temp1, WS2811_PORT ; zero value
cbr temp1, (1 << WS2811_BIT)
mov temp2, temp1 ; one value
sbr temp2, (1 << WS2811_BIT)
in temp0, SREG
cli
PFA_WS2811_RESET_LOOP_CLK_5:
rjmp pc+1
rjmp pc+1
ns250_fill_delay
PFA_WS2811_RESET_LOOP_CLK_0:
out WS2811_PORT, temp2; Write one
nop
ns250_fill_delay
out WS2811_PORT, temp1; Write zero
ns1000_fill_delay
dec temp3 ; bec bit counter
brne PFA_WS2811_RESET_LOOP_CLK_5
ldi temp3,24 ; All bits sent reset counter
sbiw tosl, 1 ; decrement LED count
brne PFA_WS2811_RESET_LOOP_CLK_0
out SREG, temp0 ; All LEDs shut off, enable interrupts
ns250_fill_delay
out WS2811_PORT, temp2 ; write one
PFA_WS2811_OFF_END:
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