Ero sivun ”Ledimatriisin ohjaaminen” versioiden välillä

Helsinki Hacklabin wikistä
Siirry navigaatioon Siirry hakuun
(Ak: Uusi sivu: {{Projekti | nimi = Ledimatriisin ohjaaminen | kuva = Ledimatriisi_abbeyroad.jpg | tyyppi = Ohje | tekijät = Jari | aloitettu = Toukokuu 2025 | tila = valmis? }} Labille saadut bonkkiledimatriisit ovat herättäneet kiinnostusta toteuttaa niiden ohjaus eri hw/sw-ympäristöihin. Aika moneen on jo toteutettukin, ja toteutukset toimivat hyvinä esimerkkeinä seuraaville toteutuksille. Silti olisi hyvä olla jonkinlainen yleiskuvaus siitä, miten matriisia yleensäkin ohjataan...)
 
Ei muokkausyhteenvetoa
Rivi 16: Rivi 16:
== Liitin ==
== Liitin ==


[[Tiedosto:Pacman_orientaatio.jpg|300px|thumb|right]]
Matriisin takana on kaksi samannäköistä liitintä. On hiukan epäselvää, mikä niiden suhde on toisiinsa, onko ne tasan samat vai ovatko ne esim. siirtorekisteriketjun eri päät. Kaikki tähänastiset toteutukset käyttävät vain toista liitintä, joten tässäkin ollaan kuin toista liitintä ei olisikaan.
Matriisin takana on kaksi samannäköistä liitintä. On hiukan epäselvää, mikä niiden suhde on toisiinsa, onko ne tasan samat vai ovatko ne esim. siirtorekisteriketjun eri päät. Kaikki tähänastiset toteutukset käyttävät vain toista liitintä, joten tässäkin ollaan kuin toista liitintä ei olisikaan.


Liitin on 34-napainen (2x17) piikkirimaliitin normaalilla 0,1” jaolla, eli tavalliset kaksiriviset perus-naaraspiikkirimat menevät siihen. Myös nauhakaapeliin puristettava 34-napainen liitin soveltuu. Kaikki kytkennät matriisiin tapahtuvat tämän yhden liittimen kautta.
Liitin on 34-napainen (2x17) piikkirimaliitin normaalilla 0,1” jaolla, eli tavalliset kaksiriviset perus-naaraspiikkirimat menevät siihen. Myös nauhakaapeliin puristettava 34-napainen liitin soveltuu. Kaikki kytkennät matriisiin tapahtuvat tämän yhden liittimen kautta.


Näytön ja liittimen orientaatio selviää oheisesta kuvasta. Kahvan vieressä olevat kolmiot osoittavat ylöspäin (kohti näytön yläreunaa). Tällöin käytetään vasemmanpuoleista liitintä ja nasta 1 on vasemmalla ylhäällä.
<div style="clear: both"></div>
<div style="clear: both"></div>
[[Tiedosto:Pacman_orientaatio.jpg|400px|thumb|right]]
Näytön ja liittimen orientaatio selviää oheisesta kuvasta. Kahvan vieressä olevat kolmiot osoittavat ylöspäin (kohti näytön yläreunaa). Tällöin käytetään vasemmanpuoleista liitintä ja nasta 1 on vasemmalla ylhäällä.


== Liittimen nastajärjestys ==
== Liittimen nastajärjestys ==


[[Tiedosto:Ledimatriisi_pinout.png|400px|thumb|right]]
[[Tiedosto:Ledimatriisi_pinout.png|250px|thumb|right]]


Liittimen kautta kulkee sekä sähköt että ohjausignaalit. Käyttösähkö on 5V ja kaikki ohjaussignaalit toimivat 5V logiikkatasoilla. Nastajärjestys on ohessa.
Liittimen kautta kulkee sekä sähköt että ohjausignaalit. Käyttösähkö on 5V ja kaikki ohjaussignaalit toimivat 5V logiikkatasoilla. Nastajärjestys on ohessa.


Koska matriisi voi viedä näytettävästä kuvasta ja kirkkaussäädöistä riippuen jopa lähemmäs 10A virtaa, on sekä +5V että GND varten varattu kummallekin 8 pinniä liittimestä. Varsinaisia ohjaussignaaleja on 13 kpl, loput pinnit on käyttämättömiä.
Koska matriisi voi viedä näytettävästä kuvasta ja kirkkaussäädöistä riippuen jopa lähemmäs 10A virtaa, on sekä +5V että GND varten varattu kummallekin 8 pinniä liittimestä. Varsinaisia ohjaussignaaleja on 13 kpl, loput pinnit on käyttämättömiä.
<div style="clear: both"></div>


== Matriisin perusominaisuudet ==
== Matriisin perusominaisuudet ==
Rivi 54: Rivi 54:


(Joku minua viisaampi voi kommentoida, menikö tuo yhtään oikein. Näin olen sen itse ymmärtänyt, tämän voi ajatella varmasti hyvinkin monella tavalla.)
(Joku minua viisaampi voi kommentoida, menikö tuo yhtään oikein. Näin olen sen itse ymmärtänyt, tämän voi ajatella varmasti hyvinkin monella tavalla.)
<div style="clear: both"></div>


== Matriisin ohjaaminen ==
== Matriisin ohjaaminen ==
[[Tiedosto:Ledimatriisi_signaalit.png|400px|thumb|right]]


Näytössä käytetylle ohjainpiirille ei löytynyt suoraan datalehteä, mutta MBI5252 on ilmeisesti riittävän lähellä. Näitä kahta dokumenttia on käytetty toteutuksessa lähteenä:
Näytössä käytetylle ohjainpiirille ei löytynyt suoraan datalehteä, mutta MBI5252 on ilmeisesti riittävän lähellä. Näitä kahta dokumenttia on käytetty toteutuksessa lähteenä:


https://www.micros.com.pl/mediaserver/UIMBI5252gp-a_0001.pdf
https://www.micros.com.pl/mediaserver/UIMBI5252gp-a_0001.pdf
<br>
https://www.neumueller.com/download/MBI5051%20MBI5052%20MBI5053%20Anwendungshinweis%20-%20Application%20Note.pdf
https://www.neumueller.com/download/MBI5051%20MBI5052%20MBI5053%20Anwendungshinweis%20-%20Application%20Note.pdf


Rivi 65: Rivi 68:


# Multipleksauksen ohjaus. Ohjainpiirit sinänsä tukevat multipleksausta, mutta ne eivät tee sitä täysin itsenäisesti, ne tarvitsevat ulkopuolelta tahdistusta. Multipleksausta on pakko tehdä koko ajan, muuten näyttö ei näytä mitään.  
# Multipleksauksen ohjaus. Ohjainpiirit sinänsä tukevat multipleksausta, mutta ne eivät tee sitä täysin itsenäisesti, ne tarvitsevat ulkopuolelta tahdistusta. Multipleksausta on pakko tehdä koko ajan, muuten näyttö ei näytä mitään.  
# Kuvadatan siirto näytön muistiin. Tässä siirretään näytettävä kuva näytölle, edellisessä kappaleessa kuvattujen periaatteiden mukaisesti.
# Kuvadatan siirto näytön muistiin. Tässä siirretään näytettävä kuva näytölle, edellisessä kappaleessa kuvattujen periaatteiden mukaisesti.


Rivi 71: Rivi 73:


Multipleksauksella ja datan siirrolla on molemmilla omat kellonsa (GCLK ja DCLK). Niiden ei tarvitse olla saman taajuisia tai muutenkaan tahdistettu toisiinsa.
Multipleksauksella ja datan siirrolla on molemmilla omat kellonsa (GCLK ja DCLK). Niiden ei tarvitse olla saman taajuisia tai muutenkaan tahdistettu toisiinsa.
[[Tiedosto:Ledimatriisi_signaalit.png|400px|thumb|right]]


Oheisessa kuvassa näkyy ohjaussignaalit. Kaikki signaalit ovat ohjaavalta prosessorilta näytölle päin, takaisin ei tule mitään.
Oheisessa kuvassa näkyy ohjaussignaalit. Kaikki signaalit ovat ohjaavalta prosessorilta näytölle päin, takaisin ei tule mitään.


=== Multipleksaus ===
=== Multipleksaus ===
[[Tiedosto:Ledimatriisi_multiplex1.png|500px|thumb|right]]
[[Tiedosto:Ledimatriisi_multiplex2.png|500px|thumb|right]]


Multipleksaukseen tarvitaan 5 signaalia:
Multipleksaukseen tarvitaan 5 signaalia:
Rivi 98: Rivi 101:


Ohessa esimerkkikuvat normaalista scanlinen vaihdosta, sekä VSYNC-käskyn sisältävästä vaihdosta. Kuvissa address-linjoja edustaa pelkkä A0/A1, muut address-linjat vaihtuvat yhtä aikaa.
Ohessa esimerkkikuvat normaalista scanlinen vaihdosta, sekä VSYNC-käskyn sisältävästä vaihdosta. Kuvissa address-linjoja edustaa pelkkä A0/A1, muut address-linjat vaihtuvat yhtä aikaa.
<div style="clear: both"></div>


[[Tiedosto:Ledimatriisi_multiplex1.png|400px|thumb|right]]
=== Kuvadatan siirto ===
[[Tiedosto:Ledimatriisi_multiplex2.png|400px|thumb|right]]
 
 


=== Kuvadatan siirto ===
[[Tiedosto:Ledimatriisi_data1.png|500px|thumb|right]]
[[Tiedosto:Ledimatriisi_data2.png|500px|thumb|right]]


Datan siirtoon käytetään 8 signaalia:
Datan siirtoon käytetään 8 signaalia:
Rivi 122: Rivi 124:
10 = reset
10 = reset
14 = pre-active (enabloi Configuration1-kirjoituksen)
14 = pre-active (enabloi Configuration1-kirjoituksen)
[[Tiedosto:Ledimatriisi_data1.png|400px|thumb|right]]


Oheisessa kuvassa on esimerkki 6 osavärin (2 pikselin) 16-bittisen kirkkausarvon shiftauksesta. Kuvassa on kaapattu vain 4 datalinjaa, koska halpisanalysaattorin kaistanleveys loppuu muuten.
Oheisessa kuvassa on esimerkki 6 osavärin (2 pikselin) 16-bittisen kirkkausarvon shiftauksesta. Kuvassa on kaapattu vain 4 datalinjaa, koska halpisanalysaattorin kaistanleveys loppuu muuten.


Kun tämä on toistettu ketjun kaikille 22 piirille, viimeisen piirin viimeisen bitin aikana lähetetään strobe-käsky nostamalla LE ylös viimeisen DCLK-pulssin ajaksi. Käskyn lähetyksen saa siis yhdistää tällä tavalla varsinaisiin shiftauspulsseihin. Tästä kuva ohessa.
Kun tämä on toistettu ketjun kaikille 22 piirille, viimeisen piirin viimeisen bitin aikana lähetetään strobe-käsky nostamalla LE ylös viimeisen DCLK-pulssin ajaksi. Käskyn lähetyksen saa siis yhdistää tällä tavalla varsinaisiin shiftauspulsseihin. Tästä kuva ohessa.
[[Tiedosto:Ledimatriisi_data2.png|400px|thumb|right]]


Tällä tavalla saatiin siis jokaisen piirin muistiin siirrettyä yhden pikselin datat. Tämä toistetaan 16 kertaa, koska kukin piiri osaa ohjata 16 pikseliä.  
Tällä tavalla saatiin siis jokaisen piirin muistiin siirrettyä yhden pikselin datat. Tämä toistetaan 16 kertaa, koska kukin piiri osaa ohjata 16 pikseliä.  

Versio 18. toukokuuta 2025 kello 10.36


Ledimatriisi abbeyroad.jpg

Ledimatriisin ohjaaminen

Tyyppi: Ohje
Tekijät: Jari
Aloitettu: Toukokuu 2025
Tila: valmis?


Labille saadut bonkkiledimatriisit ovat herättäneet kiinnostusta toteuttaa niiden ohjaus eri hw/sw-ympäristöihin. Aika moneen on jo toteutettukin, ja toteutukset toimivat hyvinä esimerkkeinä seuraaville toteutuksille. Silti olisi hyvä olla jonkinlainen yleiskuvaus siitä, miten matriisia yleensäkin ohjataan, ottamatta kantaa, mikä ohjelmointiympäristö ohjaukset tuottaa. Tämä Wiki-sivu yrittää olla tuollainen kuvaus.

Matriisien taustaa on selostettu lyhyesti tämän projektikuvauksen alkupuolella: https://wiki.helsinki.hacklab.fi/Pacman_ja_ledimatriisi

Kaikki tässä kuvattu perustuu reverse engineeraukseen ja joihinkin netistä löytyneisiin “likimain oikeisiin” dokumentteihin, joten tässä voi olla virheitä, mutta olen itse saanut matriiseja ohjattua näillä tiedoilla.

Liitin

Pacman orientaatio.jpg

Matriisin takana on kaksi samannäköistä liitintä. On hiukan epäselvää, mikä niiden suhde on toisiinsa, onko ne tasan samat vai ovatko ne esim. siirtorekisteriketjun eri päät. Kaikki tähänastiset toteutukset käyttävät vain toista liitintä, joten tässäkin ollaan kuin toista liitintä ei olisikaan.

Liitin on 34-napainen (2x17) piikkirimaliitin normaalilla 0,1” jaolla, eli tavalliset kaksiriviset perus-naaraspiikkirimat menevät siihen. Myös nauhakaapeliin puristettava 34-napainen liitin soveltuu. Kaikki kytkennät matriisiin tapahtuvat tämän yhden liittimen kautta.

Näytön ja liittimen orientaatio selviää oheisesta kuvasta. Kahvan vieressä olevat kolmiot osoittavat ylöspäin (kohti näytön yläreunaa). Tällöin käytetään vasemmanpuoleista liitintä ja nasta 1 on vasemmalla ylhäällä.

Liittimen nastajärjestys

Ledimatriisi pinout.png

Liittimen kautta kulkee sekä sähköt että ohjausignaalit. Käyttösähkö on 5V ja kaikki ohjaussignaalit toimivat 5V logiikkatasoilla. Nastajärjestys on ohessa.

Koska matriisi voi viedä näytettävästä kuvasta ja kirkkaussäädöistä riippuen jopa lähemmäs 10A virtaa, on sekä +5V että GND varten varattu kummallekin 8 pinniä liittimestä. Varsinaisia ohjaussignaaleja on 13 kpl, loput pinnit on käyttämättömiä.

Matriisin perusominaisuudet

Näytön resoluutio on 88*88 pikseliä, jokainen pikseli on RGB-ledi. Koska ohjauksen kannalta RGB-ledi vastaa kolmea tavallista erikseen ohjattavaa lediä (osavärit), on ohjattavia ledejä kaikkiaan 88*88*3 = 23 232 kpl. Jokaisen pikselin jokaiselle osavärille määritellään erikseen kirkkaus 16 bitin resoluutiolla, joten yksi kuva sisältää 23 232 * 16 = 371 712 bittiä dataa.

Näytön sisäinen elektroniikka sisältää joukon mikropiirejä, joista jokaisessa on ohjaimet 16 ledille. Tämä ei tarkoita että piirejä olisi 23 232 / 16 = 1452 kpl, vaan näyttö tekee myös multipleksausta. Jokainen ohjain ohjaa 11 lediä, joita sitten multipleksataan. Näin piirien määräksi tulee 1452 / 11 = 132 kpl.

Ohjainpiirit ovat datan syötön kannalta siirtorekistereitä: data syötetään sisään bitti kerrallaan, asettamalla bitin arvo datalinjaan ja antamalla CLK-linjaan pulssi. Kun kaikki bitit on syötetty, annetaan LE (latch enable) -linjan avulla strobe-pulssi, joka kertoo piirille, että kaikki data oli tässä.

Koska piirit ovat siirtorekistereitä, niitä voi myös ketjuttaa. Tässä näytössä ne on ketjutettu 22 piirin ketjuiksi, jolloin yksi ketju sisältää 22*16 = 352 ledin ohjaimet. Ja koska jokainen ohjain ohjaa multipleksauksen kautta 11 lediä, yksi ketju ohjaa 352*11 = 3872 lediä. Koko näytön ohjaaminen vaatii siis 23 232 / 3872 = 6 ketjua. Ketjut ovat rinnakkaiset, eli jokaisella on oma datalinja; CLK ja LE ovat yhteiset. Dataa syötetään 6 bittiä kerralla, jokaiseen ketjuun yksi bitti, ja ne kellotetaan sisään yhtä aikaa, yhteisellä CLK-pulssilla. Lopussa annettava strobe-pulssi kertoo kaikille ketjuille, että tässäpä tämä.

Ketjut on jaettu siten, että kukin ketju ohjaa yhtä osaväriä, eli tietyn pikselin kaikki 3 osaväriä ovat kolmessa ketjussa samassa kohdassa siirtorekisteriä. Ketjut on nimetty R1, G1, B1, R2, G2, B2. Dataa syötettäessä annetaan siis kerralla kahden eri pikselin kaikki osavärit.

Tämän voi ajatella myös niin, että yksi ketjukolmikko (R1,G1,B1) hoitaa puolet näytön pikseleistä (88*44 = 3872 pikseliä) ja toinen kolmikko (R2,G2,B2) toisen puolen. Koska yksi kolmikko pystyy ohjaamaan 352 pikseliä, jää kolmikolle 3872/352 = 11 vaakasuuntaista pikseliriviä eli scanlinea hoidettavaksi multipleksauksen kautta.

Kannattaa muistaa, että syötettävä data ei ole “osaväri on/off”, eli 352 bittiä per ketju, vaan jokaisen osavärin kirkkaus ilmoitetaan 16-bittisellä arvolla, joka shiftataan sisään bitti kerrallaan, eli ketjuun shiftataan 352*16 = 5632 bittiä.

Ohjainpiiri osaa hoitaa myös multipleksauksen: sillä on sisäistä muistia, jossa se säilyttää jokaisen 11 multipleksatun ledin kirkkausarvot. Joten edellä sanottu 352 16-bittistä kirkkausarvoa pitää shiftata ketjuun 11 kertaa, kullekin multipleksatulle ledille oma arvonsa. Yhteen ketjuun shiftataan siis dataa 11*352*16 = 61 952 bittiä. Koska ketjuja on 6, dataa on kaikkiaan 6 * 61 952 = 371 712 bittiä, joka saatiin jo edellä suoraan pikselimäärästä laskien. Vielä täsmää matematiikka.

Koska kuvan siirto on hidasta verrattuna multipleksaustahtiin, ohjainpiirit toteuttavat myös kaksoispuskuroinnin (double buffering): multipleksaus näyttää aina viimeisintä muistiin siirrettyä kokonaista kuvaa. Sinä aikana voidaan siirtää uutta kuvaa toiseen puskuriin, ja se tulee näkyville vasta, kun erikseen tehdään VSYNC-operaatio, joka vaihtaa puskurit keskenään.

(Joku minua viisaampi voi kommentoida, menikö tuo yhtään oikein. Näin olen sen itse ymmärtänyt, tämän voi ajatella varmasti hyvinkin monella tavalla.)

Matriisin ohjaaminen

Ledimatriisi signaalit.png

Näytössä käytetylle ohjainpiirille ei löytynyt suoraan datalehteä, mutta MBI5252 on ilmeisesti riittävän lähellä. Näitä kahta dokumenttia on käytetty toteutuksessa lähteenä:

https://www.micros.com.pl/mediaserver/UIMBI5252gp-a_0001.pdf
https://www.neumueller.com/download/MBI5051%20MBI5052%20MBI5053%20Anwendungshinweis%20-%20Application%20Note.pdf

Näytön ohjaamiseen tarvittavat toimenpiteet jakautuvat kahteen pääryhmään, jotka ovat kohtalaisen erilliset, mutta molemmat tarvitaan:

  1. Multipleksauksen ohjaus. Ohjainpiirit sinänsä tukevat multipleksausta, mutta ne eivät tee sitä täysin itsenäisesti, ne tarvitsevat ulkopuolelta tahdistusta. Multipleksausta on pakko tehdä koko ajan, muuten näyttö ei näytä mitään.
  2. Kuvadatan siirto näytön muistiin. Tässä siirretään näytettävä kuva näytölle, edellisessä kappaleessa kuvattujen periaatteiden mukaisesti.

Näytön puolesta uutta kuvadataa ei ole pakko lähettää jatkuvasti. Näyttö näyttää viimeksi muistiin siirrettyä kuvaa niin kauan kun multipleksausta tehdään. Sovelluksesta riippuu, missä tahdissa kuvan halutaan päivittyvän: reaaliaikainen peli vaatii vähintään 10 päivitystä sekunnissa, slideshow-tyyppisesssä käytössä riittää esim. yksi kuva 10 s välein.

Multipleksauksella ja datan siirrolla on molemmilla omat kellonsa (GCLK ja DCLK). Niiden ei tarvitse olla saman taajuisia tai muutenkaan tahdistettu toisiinsa.

Oheisessa kuvassa näkyy ohjaussignaalit. Kaikki signaalit ovat ohjaavalta prosessorilta näytölle päin, takaisin ei tule mitään.

Multipleksaus

Ledimatriisi multiplex1.png
Ledimatriisi multiplex2.png

Multipleksaukseen tarvitaan 5 signaalia:

  • multipleksauksen kello GCLK
  • scanlinen valinta A0...3 (address)

Multipleksauksen perusyksikkö on scanline, joita on tuo edellä mainittu 11 kpl. Address-linjoissa oleva nelibittinen arvo 0...10 kertoo, mikä scanline on tällä hetkellä menossa. Arvoa pitää askeltaa numerojärjestyksessä aina scanlinen vaihtuessa. Kun se vaihtuu 10 → 0, on koko kuvan kaikki scanlinet näytetty kerran ja aloitetaan alusta (frame vaihtuu).

GCLK on varsinainen multipleksauskello. Tämän tahdissa ohjainpiiri ajaa kai ledeihin menevää PWM:ää, sisäinen toiminta ei ole ihan selvää. Sen pitää olla riittävän nopea, jotta kuva ei näytä värisevältä. Nyrkkisääntönä on käytetty vähintään 1 MHz, datalehden mukaan max 16 MHz.

Yhden scanlinen aikana pitää tehdä 3 asiaa:

  1. GCLK:iin generoidaan 256 pulssia
  2. Address-linjoja askelletaan seuraavaan arvoon
  3. generoidaan vielä yksi GCLK pulssi (257. pulssi); tällä on jotain erillisiä ajoitusvaatimuksia (dead time) datalehdessä

Ainakin vähän hitaampien prosessoreiden kanssa tämän perusongelmana on, että GCLK-pulssit pitää tulla nopeasti ( > 1 MHz) mutta sitten kun niitä on tullut täsmälleen 256 kpl, niiden pitää loppua, jotta voidaan tehdä kaksi jälkimmäistä kohtaa. Tämän toteuttaminen ei aina ole triviaalia.

Silloin kun on tarve tehdä VSYNC-operaatio eli kuvapuskurin vaihto (tehdään yleensä silloin, kun uusi kuva on saatu siirrettyä kokonaan näytölle), se pitää tahdistaa multipleksaukseen. VSYNCin saa tehdä vain juuri ennen framen vaihtumista, eli kun address-arvo on vaihtumassa 10 → 0. Se tehdään lähettämällä kohtien 1 ja 2 välissä VSYNC-käsky, sen jälkeen kohdat 2 ja 3 suoritetaan normaalisti. Tämän tahdistuksen takia VSYNC-käskyn lähetys on toteutettava osaksi multipleksausta, vaikka se on periaatteessa kuvadatan siirtoon liittyvä operaatio.

VSYNC-käsky tapahtuu lähettämällä 2 pulssia DLCK:ia siten, että LE on sinä aikana ylhäällä. Käskyjä on muitakin ja niistä puhutaan lisää jäljempänä.

Ohessa esimerkkikuvat normaalista scanlinen vaihdosta, sekä VSYNC-käskyn sisältävästä vaihdosta. Kuvissa address-linjoja edustaa pelkkä A0/A1, muut address-linjat vaihtuvat yhtä aikaa.

Kuvadatan siirto

Ledimatriisi data1.png
Ledimatriisi data2.png

Datan siirtoon käytetään 8 signaalia:

  • DR1,DG1,DB1;DR2,DG2,DB2: pikselidata kuuteen ketjuun samalla kertaa
  • DCLK: siirtorekisterin kellopulssi
  • LE: latch enable (siirtorekisterin strobe)

Koska ohjainpiireissä on haluttu säilyttää jotain käsittämättömiä taaksepäin yhteensopivuuksia, LE ei toimi kuten saattaisi kuvitella. LE ja DCLK muodostavat yhdessä kokonaisen käskyjärjestelmän, joiden avulla voidaan lähettää ohjainpiirille useita erilaisia käskyjä. Näistä strobe on vain yksi joukosta.

Käskyjen lähetys toimii siten, että nostetaan LE ylös, generoidaan N kpl pulsseja DCLK-linjaan ja pudotetaan LE alas. Pulssien määrä kertoo, mistä käskystä oli kyse.

Käskyjä on määritelty kymmenkunta (taulukko datalehden sivulla 13). Meidän toteutuksissa on käytetty N:n arvoja:

1 = siirtorekisterin strobe 2 = VSYNC-käsky 4 = kirjoita Configuration1-rekisteri 10 = reset 14 = pre-active (enabloi Configuration1-kirjoituksen)

Oheisessa kuvassa on esimerkki 6 osavärin (2 pikselin) 16-bittisen kirkkausarvon shiftauksesta. Kuvassa on kaapattu vain 4 datalinjaa, koska halpisanalysaattorin kaistanleveys loppuu muuten.

Kun tämä on toistettu ketjun kaikille 22 piirille, viimeisen piirin viimeisen bitin aikana lähetetään strobe-käsky nostamalla LE ylös viimeisen DCLK-pulssin ajaksi. Käskyn lähetyksen saa siis yhdistää tällä tavalla varsinaisiin shiftauspulsseihin. Tästä kuva ohessa.

Tällä tavalla saatiin siis jokaisen piirin muistiin siirrettyä yhden pikselin datat. Tämä toistetaan 16 kertaa, koska kukin piiri osaa ohjata 16 pikseliä.

Nyt on siirretty yhden scanlinen verran dataa piireille. Kaikki edellä oleva toistetaan 11 kertaa, koska yksi ketju hallitsee 11 scanlinea. Tällöin meillä on siirretty kokonainen kuva ja voidaan tehdä VSYNC heti, kun multipleksaus pääsee sopivaan vaiheeseen. Sen jälkeen voidaan ryhtyä siirtämään seuraavaa kuvaa.

Sama vielä pseudokoodina, syntaksi ad hoc:

FOR scanline in 0...10:
    FOR led in 0...15:
        get data for next 44 pixels
        FOR ic in 0...21:
            FOR bit in 0...15:
                set values for DR1,DG1,DB1,DR2,DG2,DB2
                IF ic == 21 and bit == 15:
                    set LE
                ENDIF
                pulse DCLK
            ENDFOR (bit)
        ENDFOR (ic)
        reset LE
    ENDFOR (led)
ENDFOR (scanline)
request VSYNC from multiplexer


Pikselien järjestys

Mutta missä järjestyksessä pikselien datat pitää shiftata sisään siirtorekisteriketjuihin? Tämän kysymyksen vastaus ei ole ollenkaan itsestään selvä. Vastaus ei todellakaan ole “kauniisti vasemmalta oikealle ja ylhäältä alas”.

Matriisin sisällä olevassa piirilevyssä ohjainpiirien ja ledien väliset kytkennät on ilmeisesti tehty pitkälti piirilevysuunnittelijan ehdoilla, ja syntyneet epäloogisuudet on jätetty softamiesten päänsäryksi. Järjestys ei ole täysin satunnainen, siinä on jonkinlaista systematiikkaa, mutta en edes yritä määritellä sitä tähän, muuten kuin koodina.

Kyse on funktiosta, joka toteuttaa edellä olleessa pseudokoodissa rivin “get data for next 44 pixels”. Tässä haetaan ketjuun syötettävät datat seuraavalle kierrokselle, jossa syötetään yksi pikseli kummakin ketjukolmikon kaikille 22 piirille, eli tarvitaan 44 pikselin datat (yksi pikseli = 3 arvoa: R, G ja B).

Tälle funktiolle annetaan inputiksi nykyinen scanline ja led ja se palauttaa puskurissa 44 pikseliä, 22 ketjulle R1,G1,B1 ja 22 ketjulle R2,G2,B2. Data on bitmap-taulukossa normaalissa järjestyksessä ja tämä poimii niitä sieltä näytön kannalta oikeassa järjestyksessä.


void getChainData(pixel_t bitmap[88][88], uint scanline, uint led, pixel_t data[44]) {
  // Row delta from current led
  uint8_t ledRow = (led / 8) ? 0 : 11;
  // Led delta in columns
  uint8_t ledColumn = led % 8;

  int row = scanline + ledRow;

  if (ledRow == 11) {
    ledColumn = (7 - ledColumn);
  }
 
  int start = 33;

  // Rows r and r+8
  for (int i = 0; i < 11; i++) {
    data[start+i] = bitmap[row][(8 * i) + ledColumn];
  }

  row += 22;
  start = 22;

  for (int i = 0; i < 11; i++) {
    data[start+i] = bitmap[row][(8 * i) + ledColumn];
  }

  row += 22;
  start = 11;

  for (int i = 0; i < 11; i++) {
    data[start+i] = bitmap[row][(8 * i) + ledColumn];
  }

  row += 22;
  start = 0;
  
  for (int i = 0; i < 11; i++) {
    data[start+i] = bitmap[row][(8 * i) + ledColumn];
  }
}

Ohjainpiirin konfigurointi

Ohjainpiiriä voi myös konfiguroida, ja pitää, koska muuten se ei toimi oikein. Konfiguraatiorekisteri on 16-bittinen rekisteri nimeltään Configuration1 ja sen sisältö on kuvattu datalehden sivulla 16. Muutama huomio:

  • scanline-määrä pitää asettaa 11:ksi, muuten ei toimi ollenkaan
  • GCLK-multiplier pitää enabloida, muuten ei edellä kuvattu multipleksaustapa toimi
  • Current gainia voi säätää laajoissa rajoissa (0...63), normaalissa huonevalossa arvo 5 on ihan riittävä, jolloin näytön virrankulutuskin pysyy kohtuullisena. Säätövaraa ylöspäin on runsaasti, jos tarvitsee lisää kirkkautta.

Arvona on käytetty yleensä 0x0A45, joka toteuttaa yllä mainitut.

Konfiguraatorekisterin arvo lähetetään ohjainpiirille seuraavasti:

  1. Lähetä käsky “pre-active”
  2. Lähetä haluttu konfiguraatiorekisterin 16-bittinen sisältö
  3. Lähetä käsky “kirjoita Configuration1”

Kaksi viimeistä voidaan yhdistää nostamalla LE ylös sisällön viimeisten neljän DCLK-pulssin ajaksi.

Rekisterin sisältö pitää lähettää jokaiseen ketjuun ja jokaiselle 22 piirille erikseen. Lisäksi ilmeisesti pitää lähettää myös jokaiselle piirin 16 ledille erikseen, näin ainakin esimerkkikoodi tekee. Ehkä current gain-asetus on ledikohtainen? Eli kohtaa 2 toistetaan 352 kertaa.

Piirissä on myös Configuration2-rekisteri, mutta tätä ei ole muutettu oletusarvosta meidän toteutuksissa.

Reference design

Depili kirjoitti koodin Teensylle, jota lukemalla olen nämä asiat opetellut ja tehnyt omat 8051-toteutukseni. Tätä en ole koskaan Teensyssä ajanut.

Koodi on optimoimatonta, eli asiat tehdään joissakin paikoissa aika lailla nysväten, mutta se on juuri hyvä tällaisessa mallikoodissa, ei huku asia ovelien optimointien keskelle. Koodi löytyy täältä:

https://gist.github.com/JKN0/6cdcf1181f3ea4e7dfcdc235a89fa7df