Not very efficient, but at least a proof it can be made functional.
But I needed already to unroll some code, while would it have been in loops, it would be too slow.
The same unrolling can be done in ASM also, and will still save some cycles, but I think I let it be for now.
[code:1:6ae7edb04b]$regfile = "xm128a1def.dat"
$crystal = 32000000
$hwstack = 64
$swstack = 40
$framesize = 40
'$noramclear
'$sim
Config Osc = Enabled , 32mhzosc = Enabled
Config Sysclock = 32mhz
Config Base = 0
'### user configurable ###
Const RGBunits = 3 ' total count of RGB units
Const rstto = 2 ' reset timeout, 1 equals one empty frame, 24 bits * 1,25µs = 30µs
'### user configurable ###
Const bytesperRGBunit = 3 ' every RGB-unit has 3 leds, every led is controlled by 1 byte
Const ledcnt = RGBunits * bytesperRGBunit ' total amount of leds
Const dbfsize = 12 ' one nibble per sent bit, 24 bit per RGB unit, 24 nibbles = 12 bytes
Const dbfsize2 = dbfsize * 2
Const USART_TXEN = 3
Const USART_CMOD0 = 6
Const USART_CMOD1 = 7
Const USART_UCPHA = 1
Const USART_UDORD = 2
Const DMA_CH0TRNIF = 0
Const DMA_CH1TRNIF = 1
Const SPItmpl = &b10001000
Const SPIhnib = &b01000000 ' SPI_Out_0 = &b1000, 1.25µs/4*1 = H0.312µs, L0.938µs
Const SPIlnib = &b00000100 ' SPI_Out_1 = &b1100, 1.25µs/4*2 = H0.625µs, L0.625µs
Declare Sub filldbuf()
Dim dblbuf_0(dbfsize) As Byte
Dim dblbuf_1(dbfsize) As Byte
Dim dblbuf(dbfsize2) As Byte At dblbuf_0(0) Overlay ' access both buffers through this one
Dim ledarr(ledcnt) As Byte
Dim ledptr As Word ' points to actual shifted out RGB data
Dim toctr As Byte
'### ISR related vars ###
Dim SPIbyte As Byte
Dim dbufptr As Byte
Dim bufb As Byte
Dim RGBtrsfr As Byte
'### ISR related vars ###
ledptr = 0
toctr = 0
ledarr(0) = 128
ledarr(1) = 170
ledarr(2) = 85
ledarr(3) = 1
ledarr(4) = 4
ledarr(5) = 32
On Dma_ch0 Dma_ch0_int
On Dma_ch1 Dma_ch1_int
'UART0 in SPI Mode, TXD --> PD3, XCK --> PD1 (unused)
Config PORTD.3 = Output ' set SPI TXD to output
USARTD0_BAUDCTRLA = 4 ' BSEL = (32MHz/(2*3.2MBaud))-1, 1/(1.25µs/4bit) = 3.2MBaud
USARTD0_BAUDCTRLB = 0 ' BSCALE = 0
USARTD0_CTRLA = 0
USARTD0_CTRLB = Bits(USART_TXEN) ' enable transmitter
USARTD0_CTRLC = Bits(USART_CMOD1 , USART_CMOD0) ' enable UART SPI-mode, MSB first, sample rising edge
Config Dma = Enabled , Doublebuf = CH01 , Cpm = CH0123
'Trigger Base Value = &H6B + Data register empty (DRE) &H01 --> &H6C
Config Dmach0 = Enabled , Burstlen = 1 , Chanrpt = Enabled , Tci = Lo , Eil = OFF , Singleshot = Enabled , _
Sar = BLOCK , Sam = INC , Dar = NONE , Dam = FIXED , Trigger = &H6C , Btc = dbfsize , Repeat = 0 , Sadr = Varptr(dblbuf_0(0)) , Dadr = Varptr(usartD0_data)
Config Dmach1 = Enabled , Burstlen = 1 , Chanrpt = Enabled , Tci = Lo , Eil = OFF , Singleshot = Enabled , _
Sar = BLOCK , Sam = INC , Dar = NONE , Dam = FIXED , Trigger = &H6C , Btc = dbfsize , Repeat = 0 , Sadr = Varptr(dblbuf_1(0)) , Dadr = Varptr(usartD0_data)
Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled
'Enable Interrupts
Config PORTE.0 = Output 'led0
Config PORTD.2 = Output
Dim A As Word
Dim C As Word
'(
Do
Waitms 500
Toggle PortE.0
Loop
')
Do
For A = 0 To 65535 ' 91ms for this loop with disabled interrupts (no DMA)
C = A ' 322ms with interrupts (with DMA), CPU 28% App <-> 72% ISR/DMA
Next A
Toggle PortD.2
Loop
End
Dma_ch0_int:
dbufptr = 0
Call filldbuf
DMA_INTFLAGS = 2 ^ DMA_CH0TRNIF
Return
Dma_ch1_int:
dbufptr = dbfsize
Call filldbuf
DMA_INTFLAGS = 2 ^ DMA_CH1TRNIF
Return
Sub filldbuf()
RGBtrsfr = 3
While RGBtrsfr > 0
If toctr = 0 Then
SPIbyte = ledarr(ledptr)
bufb = SPItmpl ' preset with template
bufb.6 = SPIbyte.7
bufb.2 = SPIbyte.6 ' set out-bits according in-bits
dblbuf(dbufptr) = bufb : Incr dbufptr ' write to double buffer, next buffer byte
bufb = SPItmpl
bufb.6 = SPIbyte.5
bufb.2 = SPIbyte.4
dblbuf(dbufptr) = bufb : Incr dbufptr
bufb = SPItmpl
bufb.6 = SPIbyte.3
bufb.2 = SPIbyte.2
dblbuf(dbufptr) = bufb : Incr dbufptr
bufb = SPItmpl
bufb.6 = SPIbyte.1
bufb.2 = SPIbyte.0
dblbuf(dbufptr) = bufb : Incr dbufptr
Incr ledptr
Else
dblbuf(dbufptr) = 0 : Incr dbufptr ' pause, set all out bytes zu zero
dblbuf(dbufptr) = 0 : Incr dbufptr
dblbuf(dbufptr) = 0 : Incr dbufptr
dblbuf(dbufptr) = 0 : Incr dbufptr
End If
Decr RGBtrsfr
Wend
If toctr > 0 Then
Decr toctr
Else
If ledptr >= ledcnt Then ' end of array ?
ledptr = 0 ' reset pointer
toctr = rstto ' prepare for WS2811 reset
End If
End If
End Sub[/code:1:6ae7edb04b]
↧