TLC5940/41 Driver
mhm21
Posts: 14
Hello all, I am starting this thread for constructive feedback on my TLC5940 driver. Currently it have written the vast majority in assembly so that I might quickly index through a large LED matrix (32x32). This chip seemed like a wonderful place to learn about the counter modules as it requires a grey scale clock pulse to be emitted and monitored at as high a frequency as possible. I am using the counterA in NCO mode to generate a 3MHz square wave (max SPI frequency supported by the chip) and counter B in rising edge detection mode to determine when 4096 pulses have elapsed.
Within the grey scale timing window, a counter is monitored for changes to any individual channel. If a change is detected, it is written and latched to the chip. This data then becomes valid on the next grey scale cycle. As it stands, the grey scale timing and channel update runs at 7.3kHz. Not terrible, but I suppose there is room for improvement. Extensions for multiple chips can be realized by changing the number of channels in the constant block. I have yet to test beyond two chips in series, but I suspect that the driver might need to be changed to support larger number of chips.
I had hoped this module would be useful for others, so I plan to upload it to OBEX if it is well received. What changes should be made to make it more useful/usable/better/faster/stronger/etc. ? Is there a more elegant way to do the initial channel declarations? I feel like these are using up a lot of valuable space.
Within the grey scale timing window, a counter is monitored for changes to any individual channel. If a change is detected, it is written and latched to the chip. This data then becomes valid on the next grey scale cycle. As it stands, the grey scale timing and channel update runs at 7.3kHz. Not terrible, but I suppose there is room for improvement. Extensions for multiple chips can be realized by changing the number of channels in the constant block. I have yet to test beyond two chips in series, but I suspect that the driver might need to be changed to support larger number of chips.
I had hoped this module would be useful for others, so I plan to upload it to OBEX if it is well received. What changes should be made to make it more useful/usable/better/faster/stronger/etc. ? Is there a more elegant way to do the initial channel declarations? I feel like these are using up a lot of valuable space.
Con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 CHANNELS = 16 VAR LONG SIN,SCLK,XLAT,BLANK,GSCLK,SOUT LONG REFRESH,CHANNEL_IN[CHANNELS] BYTE COG PUB Start(SIN_,SCLK_,XLAT_,BLANK_,GSCLK_,SOUT_) : Pass 'Pin declarations SIN := SIN_ SCLK := SCLK_ XLAT := XLAT_ BLANK := BLANK_ GSCLK := GSCLK_ SOUT := SOUT_ 'Starts new cog and returns true if successful Stop cog := cognew(@START_TLC,@SIN) Pass := @refresh PUB Set_Channel(chan,val) CHANNEL_IN[chan] := val refresh ++ PUB Stop if COG cogstop(COG~) DAT org 0 START_TLC mov P1,par rdlong dummy,P1 mov SIN_MASK,#1 shl SIN_MASK,dummy add P1,#4 rdlong dummy,P1 mov SCLK_MASK,#1 shl SCLK_MASK,dummy add P1,#4 rdlong dummy,P1 mov XLAT_MASK,#1 shl XLAT_MASK,dummy add P1,#4 rdlong dummy,P1 mov BLANK_MASK,#1 shl BLANK_MASK,dummy add P1,#4 rdlong dummy,P1 mov GSCLK_MASK,#1 shl GSCLK_MASK,dummy add ctra_,dummy ' Setup counter pins add ctrb_,dummy andn dira,GSCLK_MASK ' Set pin directions or dira,BLANK_MASK or dira,SCLK_MASK or dira,SIN_MASK or dira,XLAT_MASK mov ctra,ctra_ ' Start counters in correct mode mov frqa,frqa_ ' Counter A is in NCO mode at 3 MHz (max SPI frequency of TLC5940) mov ctrb,ctrb_ ' Counter B is in rising edge detection mode, used to count to 4096 for the grey scale clock mov frqb,frqb_ ' Counter B adds 1 to PHSB on every rising edge '--------------------------------------------------------- MAIN_LOOP :Loop mov ti,cnt mov phsb,#0 ' Reset counter or dira,GSCLK_MASK ' Turn on 3 MHz output waveform call #READ_ARRAY ' If new data, update channels :gs_loop cmp resolution,phsb wc ' If PHSB is => 4096, turn off and strobe blanking pin if_nc jmp #:gs_loop andn dira,GSCLK_MASK or outa,BLANK_MASK andn outa,BLANK_MASK sub ti,cnt wrlong ti,p1 jmp #:Loop MAIN_LOOP_RET ret '--------------------------------------------------------- READ_ARRAY mov p1,par add p1,#(6*4) mov RFRSH,#0 ' Clear refresh count wrlong RFRSH,p1 add p1,#4 mov array_count,CC ' Number of longs to read, sequentially or outa,SCLK_MASK ' Drive SCLK high, mysterious 193'rd pulse in data sheet andn outa,SCLK_MASK ' Drive SCLK low :read_loop mov mask,twelve_bit_mask ' Setup masks mov bits,#12 ' Loop counter rdlong channel,p1 ' Reads channel values sequentially add p1,#4 ' Increment pointer to next long in memory (channels) :Sin_loop test channel,mask wz if_nz or outa,SIN_MASK ' Toggle data pin if_z andn outa,SIN_MASK or outa,SCLK_MASK ' Drive SCLK high andn outa,SCLK_MASK ' Drive SCLK low shr mask,#1 ' Shift mask to next bit, 12 bit total resolution djnz bits,#:SIN_LOOP djnz array_count,#:read_loop or outa,XLAT_MASK andn outa,XLAT_MASK READ_ARRAY_RET ret 'Variables '----------------------------------------------------------------------------------- P1 LONG 0 ti LONG 0 SIN_MASK LONG 0 SCLK_MASK LONG 0 XLAT_MASK LONG 0 BLANK_MASK LONG 0 GSCLK_MASK LONG 0 SOUT_MASK LONG 0 mask LONG 0 ' Used as 12 bit channel mask twelve_bit_mask LONG 1<<12 resolution LONG 4096 ' Used for grey scale counter bits LONG 0 array_count LONG 0 ' Determines how many channels to read channel LONG 0 CC LONG CHANNELS RFRSH LONG 0 ' Determines update interval dummy LONG 0 ctra_ LONG %00100 << 26 ' NCO mode ctrb_ LONG %01010 << 26 ' Rising edge detection mode frqa_ LONG 1610612736 ' 30 MHz frqb_ LONG 1 ' 1 increment for each edge FIT 496
spin
17K