tlc5920 16x8 led driver/controller

Pavel Hudecek edizon na seznam.cz
Pátek Srpen 31 17:07:16 CEST 2018


Tak tohle bych považoval za tak nějak samozřejmé:-) Ze všech obrázků i 
tabulek v DS též plyne, že CSEL má čistě statickou funkci, tzn. po celou 
dobu svitu tam musí být daná kombinace.

Ale uznávám, že ani samozřejmé věci někdy zas tak samozřejmé nejsou:-)

Zrovna koukám sem:
http://www.farnell.com/datasheets/2625486.pdf

A z grafů 8/13 a 9/13 to vypadá, že s CE se v rámci běžného čtení a zápisu 
musí "cvičit", což patří do kategorie "to by mě ani ve snu nenapadlo":-)

Jsem zvyklý, že tuhle nohu (není-li zvláštní důvod k jinému použití) dávám 
natvrdo na GND. Navíc v aplikaci, pro kterou jsem to chtěl, by to chtělo, 
aby ke čtení stačilo mít trvale aktivní OE a jen měnit adresy, což je u RAM 
s tímto rozhraním též normální, ale tady to asi taky nepůjde.

PH

-----Původní zpráva----- 
From: David Belohrad
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? 



Další informace o konferenci Hw-list