tlc5920 16x8 led driver/controller
David Belohrad
david na belohrad.ch
Středa Srpen 29 09:25:54 CEST 2018
diky vsem,
uz jsem to rozjel. problemu bylo vic, ale ten hlavni bylo casovani signalu csel. nejak jsem nepochopil, ze csel by mel byt na jedne hodnote 'dost dlouho', a ze je to prave csel, ktery dela tu sloupcovou obnovovaci frekveni. takze jsem musel kod cely predelat. Kdyby nekdo potreboval FPGA implementaci, tady je. Zapojeni je v jednom z predchozich emailu (mam tam 2 tlc drivery a vsechny signaly krome vstupnich dat jsou stejne. data jsou kazdemu TLC predavana v display.data1_o a display.data2_o). Prilozeny kod je informativni (chybi deklarace ckrs_t, implementace clock_divider ...). pokud nekdo chce cely kod, rad preposlu.
import CKRSPkg::*;
module tlc5920
#(
// clock divider. Set to zero when ClkRs_ix provides 40MHz
// stream. For all faster clocks give division ratio to get to
// lower speeds
parameter g_divider = 4
)
(
// 40 MHz clock reset stream
input ckrs_t ClkRs_ix,
// data input. Logic '1' turns the particular led on (= emits
// light). The vector data are as follows:
// [column][row][red/green]
input logic [3:0][15:0][1:0] data_ib,
// interface to the chip
display_x display
);
// clock enable
logic enable,
onems = 0,
enabledly = 0;
logic sclk = 0,
latch = 0;
// counting 32bits to be shifted in one go into both registers
localparam CBITS = 7;
logic [CBITS-1:0] counter_b = '0;
logic frame;
// first index is DRIVER, second index is data to be shifted in
logic [1:0][15:0] data_b;
// first we get clock enable out of division, get maximum speed,
// which is 10MHz. This is clock into serial register
clock_divider
#(.g_divider(g_divider))
i_clock_divider_ms
(.enable_o(enable),
.*);
// millisecond counting (roughly)
logic [14:0] cntms = '0;
always_ff @(posedge ClkRs_ix.clk)
if (enable) begin
if (cntms == 15'd10000)
cntms <= '0;
else
cntms <= cntms + 15'd1;
onems <= (|cntms) ? '0 : '1;
end
typedef enum logic[5:0] {IDLE, LOAD, SHIFTSTART,
SHIFTSTOP, LATCH} state_t;
state_t state;
always_ff @(posedge ClkRs_ix.clk)
enabledly <= enable;
logic [2:0] next_csel;
always_ff @(posedge ClkRs_ix.clk)
if (onems && enable)
next_csel <= display.csel_ob3 + 3'd1;
// translate current column into next data slice
logic [1:0] nextidx;
logic nextcolor;
assign nextidx = next_csel[1:0];
logic [31:0] compact_b;
// these are 32 bits corresponding to row/color
assign compact_b = data_ib[nextidx];
// we use currentout data slice to cast the data to the led diodes outputs
always_ff @(posedge ClkRs_ix.clk)
if (state == LOAD && enabledly) begin
data_b[1] <= compact_b[31:16];
data_b[0] <= compact_b[15:0];
end else if (state == SHIFTSTOP && enable) begin
data_b[1] <= {data_b[1][14:0], 1'b0};
data_b[0] <= {data_b[0][14:0], 1'b0};
end
// simple counter to count the states
always_ff @(posedge ClkRs_ix.clk)
if (state == LOAD)
counter_b <= (CBITS)'(16);
else if (enabledly && sclk && (|counter_b))
counter_b <= counter_b - (CBITS)'(1);
// counter for columns:
always_ff @(posedge ClkRs_ix.clk or posedge ClkRs_ix.reset)
if (ClkRs_ix.reset)
display.csel_ob3 <= '0;
else if (frame && enable)
display.csel_ob3 <= display.csel_ob3 + 3'd1;
always_ff @(posedge ClkRs_ix.clk or posedge ClkRs_ix.reset) begin
if (ClkRs_ix.reset) begin
state <= IDLE;
end else if (enable) begin
frame <= '0;
sclk <= '0;
latch <= '0;
display.blank_o <= '0;
case(state)
IDLE: begin
display.blank_o <= '0;
if (onems) begin
display.blank_o <= '1;
state <= LOAD;
end
end
LOAD: begin
display.blank_o <= '1;
frame <= 1;
state <= SHIFTSTART;
end
SHIFTSTART: begin
display.blank_o <= '1;
sclk <= 1;
state <= SHIFTSTOP;
end
SHIFTSTOP: begin
display.blank_o <= '1;
sclk <= 0;
if (~(|counter_b))
state <= LATCH;
else
state <= SHIFTSTART;
end
LATCH: begin
display.blank_o <= '1;
latch <= 1;
state <= IDLE;
end
endcase // case (state)
end
end
initial begin
$display("Size of input vector: %d", $bits(data_ib));
end
assign display.latch_o = latch;
assign display.sclk_o = sclk;
assign display.data1_o = data_b[0][15];
assign display.data2_o = data_b[1][15];
endmodule // tlc5920
Daniel Valuch <balu na k-net.fr> writes:
> pisal som to pred 10 rokmi, ale reverznut by nemalo byt tazke :-)
>
> hodiny equ 30h ;aktualny cas
> minuty equ 32h
> sekundy equ 34h
> medzi_low equ 36h
> medzi_high equ 37h
> GPS_status equ 38h
> sek_tmp1 equ 39h
> sek_tmp2 equ 3Ah
>
> timeshift bit 7Ch ;time shift with respect to GMT. 0 = GMT+1, 1 = GMT+2
> timeshift_in bit p3.5 ;timeshift input
>
> text equ 40h ; zaciatok 32B bloku s aktualnym textom
>
> disp equ 40h ;zaciatok pamate s datami pre displej
> disp1 equ 40h ; znak1 H displeja 1
> disp2 equ 48h ; znak1 H displeja 2
> disp3 equ 50h ; znak1 H displeja 3
> disp4 equ 58h ; znak1 H displeja 4
> disp5 equ 60h ; znak1 H displeja 5
> disp6 equ 68h ; znak1 H displeja 6
> disp7 equ 70h ; znak1 H displeja 7
> disp8 equ 78h ; znak1 H displeja 8
>
>
> znak1 equ 80h ; zaciatok dat (bit 0) pre znak1
> znak2 equ 90h ; zaciatok dat (bit 0) pre znak2
> znak3 equ 0A0h ; zaciatok dat (bit 0) pre znak3
> znak4 equ 0B0h ; zaciatok dat (bit 0) pre znak4
>
> latch bit P2.7
> blank bit P2.5
> sclk bit P2.6
> csel0 bit P2.4
> csel1 bit P2.3
> csel2 bit P2.2
>
> RCAP2H equ 0CBh
> RCAP2L equ 0CAh
> T2MOD equ 0C9H
> T2CON equ 0C8H
> TR2 bit 0C8h.2
>
> task1flag bit 78h
> task2flag bit 79h
> task3flag bit 7Ah
> task4flag bit 7Bh
>
>
> pocet_znakov equ 32 ; pocet znakov na displeji
>
>
> org 0
>
> jmp init
>
> ;interrupt handles
> org 0bh ;------- timer 0 interrupt handle
> mov TL0,#Low T0_const
> mov TH0,#High T0_const
> push 0h ;push registra R0
> push 1h ;push registra R1
>
> jb task1flag,task1
> jb task2flag,task2
> jb task3flag,task3
> jb task4flag,task4
>
> setb task1flag
> clr task2flag
> clr task3flag
> clr task4flag
> jmp von_z_int
>
> task1:
> clr task1flag
> setb task2flag
> clr task3flag
> clr task4flag
>
> ;
> mov R0,#znak1
> mov R1,#16
>
> ; setb blank
>
> loop3: mov P0, na R0
> setb sclk
> inc R0
> clr sclk
> djnz R1,loop3
>
> setb latch
> clr latch
>
> clr csel0
> clr csel1
> clr csel2
> ; clr blank
>
> jmp von_z_int
>
> task2:
> clr task1flag
> clr task2flag
> setb task3flag
> clr task4flag
>
> ;
> mov R0,#znak2
> mov R1,#16
>
> ; setb blank
>
> loop4: mov P0, na R0
> setb sclk
> inc R0
> clr sclk
> djnz R1,loop4
>
> setb latch
> clr latch
>
> setb csel0
> clr csel1
> clr csel2
> ; clr blank
>
> jmp von_z_int
>
> task3:
> clr task1flag
> clr task2flag
> clr task3flag
> setb task4flag
>
> mov R0,#znak3
> mov R1,#16
>
> ; setb blank
>
> loop5: mov P0, na R0
> setb sclk
> inc R0
> clr sclk
> djnz R1,loop5
>
> setb latch
> clr latch
>
> clr csel0
> setb csel1
> clr csel2
> ; clr blank
>
> jmp von_z_int
>
> task4:
> setb task1flag
> clr task2flag
> clr task3flag
> clr task4flag
>
> ;
> mov R0,#znak4
> mov R1,#16
>
> ; setb blank
> loop6: mov P0, na R0
> setb sclk
> inc R0
> clr sclk
> djnz R1,loop6
>
> setb latch
> clr latch
>
> setb csel0
> setb csel1
> clr csel2
> ; clr blank
>
> jmp von_z_int
>
>
>
> von_z_int:
> clr blank
> pop 1h ;pop registra R1
> pop 0h ;pop registra R1
> reti
>
>
> On 27/08/2018 21:58, David Belohrad wrote:
>> Ahojte,
>>
>> ma prosim nekdo zkusenosti s tl5920?
>>
>> www.ti.com/lit/ds/symlink/tlc5920.pdf
>>
>>
>> nevim jak spravne formulovat muj dotaz. ... nefunguje to a asi nerozumim, jak to ma fungovat. Datasheet je velice skoupy na informace. a at delam co delam, led matrix zobrazuje hovadiny. Vyrobil jsem kus systemverilog kodu, ktery dava 'blank' signal trvale na log. L. Necham vzdy do 16 bitoveho registru nacist pro dany radek tu 16-bitovou informaci, po kazdych 16 bitech vytvorim puls na LATCH (transision L->H->L), a na kazdych 16-bitech cykluji csel vzdy dvakrat (tedy mezi dvema latch impulzy ma csel hodnotu 0,1 pak 2,3 pak 4,5), a tedy jeden 'frame' vyzaduje 4x latch - celkove 64 bitu poslanych na kazdy frame, ktery cykluje csel od nuly do sedmi.
>>
>> Kdyz to spustim a divam se na data na SIN/SOUT, vsechno vypada perfektne, logicky. Ovsem diody si delaji co chteji. nektere z nich slabe sviti, nektere silne, skoro to vypada, jako kdyby nebyl dostatecny proud tema diodama, nebo dochazelo k nejakemu mixu mezi logikou CSEL pinu a seriove linky. Napada me jenom, ze signal BLANK proste z nejakeho neznameho duvodu musi byt take pouzivan. Ja jej mam trvale na nule, protoze chci mit ty diody neustale zapnute.
>>
>> Tak me napadlo, nema k tomuto driveru nekdo kod napsany pro ... cokoliv? arduino/jakykoliv mikrokontroler, abych si mohl proverit jestli casuji jak mam? K cemu je BLANK?
>>
>> ztratil jsem s tou hovadinou cely den
>>
>> diiky.
>>
>> .d.
>> _______________________________________________
>> HW-list mailing list - sponsored by www.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
Další informace o konferenci Hw-list