Zoals jullie misschien wisten ben ik bezig met een blinkenAVR. Dit is een matrix versie van blinken, dus veel minder draden en minder stroomgebruik. Ook komt er een 255 staps dimfunctie op, handig als je ultrafelle LEDs gebruikt en 's avonds niet blind wilt worden.

Ik ben nu het blinken protocol aan het onderzoeken voor de AVR versie van blinken. Op mijn pc is door het blinkenleds programma van jalcds in 200us alle data van een heel beeld verstuurd. Dat is op 9 lijnen 16 bitjes.

Ik ga ervan uit dat het altijd langer dan 160us duurt om alle data te versturen, mag ik hier van uit gaan? Hier staat de VB source van blinkenleds (jalcds). Per 9 bits worden er 4 commando's naar de poort verstuurd. Dus in totaal 64 (+3 om display te refreshen) commando's.

VRAAG: Hoe lang duurt het schrijven van commando's naar een parallelle poort minimaal?

Ik ben op dit moment namelijk hard bezig met de ASM source. De data staat op PB0-7 en PD0, de data (MSB first) moet in het RAM worden opgeslagen, kan ik de data realtime omzetten naar 18 bytes?

VRAAG: Ik heb ongeveer 10us (80 clock cycles) om 9 bits op 9 adressen in het RAM te krijgen, gaat dit lukken? Ik heb nog nooit RAM in een AVR gebruikt dus ik zou het zelf niet weten.

Het is de bedoeling dat ik de eerste 9 bits in 9 even RAM plaatsen zet, het MSB zet ik dan aan of uit, ligt aan de data natuurlijk. De volgende data (10uS later) moet in dezelfde RAM plaatsen komen, maar op een plek met een lagere significantie. De 8e datareeks komt op het LSB terecht. De 9e reeks op de oneven ramplaatsen, weer op MSB. Als de 16e datareeks op de LSB's is gezet moet er een memcopy gebeuren en het geheugen worden gewist. Maar dat laatste is niet kritiek, dus dat is geen probleem.

Heeft er iemand een goed idee hoe ik dit alles in ASM moet gaan aanpakken?

VRAAG: Hoe lang duurt het schrijven van commando's naar een parallelle poort minimaal?

?? Enkele nsec?

VRAAG: Ik heb ongeveer 10us (80 clock cycles) om 9 bits op 9 adressen in het RAM te krijgen, gaat dit lukken?

10us = 40 ck (10us/250nsec = 40 ck) bij 4MHz xtal. Dus ik neem aan dat je op 2MHz draait (80 ck) ??

Voor 9 bits heb je maar 2 adressen nodig (2 bytes), hm ik weet niet welke AVR jij gebruikt. Ik ken alleen 8bits SRAM.

Ik weet ook niet of die data parallel of serieel gaat.
Stel je inlees progje is 20 instructies, dan maar 20*250ns = 5us. (het kan dus, mits je progje kleiner is dan 40 instructies ongeveer)
Parallel zou maar 1 instructie duren;

in r16, PINx

Dan duurt het maar 250 nsec. (4mhz xtal)

Ik weet niet hoe dat blinken led protocol werkt maar als de data zo binnen komt werkt het wel binnen die tijd
Ik noemen die 9bits de rijen
en de 16bits de kolomen
MSB gebruik ik als Most Significant Byte
Hierbij ga ik er van uit dat de data op deze manier binnen komt ik weet niet of dat zo is.
MSB Rij0
LSB Rij0
MSB Rij1
LSB Rij1
MSB Rij2
LSB Rij2
etc

Als je data dan op zelfde volgorde opslaat werkt het heel makkelijk


in temp,pinb
st X+, temp

Dit moet dan iederekeer dat je de data binnen krijgt aangeroepen worden. en de eerste keer moet x ingesteld worden op beginlocatie.

Als de data opdeze manier binnen komt een andere oplossing.
MSb is Most Signifcant bit.
PB7 ,PB6 ,PB5 ,PB4 ,PB3 ,PB2 ,PB1 ,PB0 ,PD0 de poorten
R8B0,R7B0,R6B0,R5B0,R4B0,R3B0,R2B0,R1B0,R0B0 1e datareeks
R8B1,R7B1,R6B1,R5B1,R4B1,R3B1,R2B1,R1B1,R0B1 2e datareeks
etc

Dan kan je deze het efficents opslaan op deze manier
in een reeks
R8B0-R1B0 eerste byte.
R8B1-R1B1 tweede byte.
etc
worden dus 16 bytes


in temp,pinb
st X+, temp

Dit moet dan iederekeer dat je de data binnen krijgt.
en R1 die van portD afhaald op deze manier
je schijft de inhoud van portd naar rechts zodat de LSb van portd in volgde byte van het ram komt. Hiervoor moet je wel alledata ontvangen voordat het op de goede plek
staat.
R0B15-R0B8 eerste byte
R0B7-R0B0 tweede byte
hiervoor zijn 2 bytes nodig.


in temp,portd
lds r0, byte0
lds r1, byte1
lsr temp
rol r0
rol r1
sts byte0,r0
sts byte1,r1

opeen van deze manieren red je het makkelijk binnen de tijd.
voor manier1 zijn er 3 cycles nodig en 2 voor de init van x.
voor manier2 zijn er 14 cycles nodig en 2 voor de init van x
mijn langste reply ooit :).

darksteel83: Hmm, wel een idee inderdaad, gewoon opslaan en later goed zetten! Maar dat kan altijd nog, liever gelijk goed. Ik denk dat het protocol wat jij in gedachte hebt anders is...

RES: Enkele nsec kan nooit! Dan zou het zelfs veel sneller dan USB 2.0 zijn! Ik bedoel eigenlijk de tijd tussen twee commando's als je dat niet had begrepen.

En 80 cycles / 10us is natuurlijk 8Mhz en geen 2.

Ik heb geen 9 bits RAM nodig, maar gewoon 8 bits, de data komt op 9 poorten binnen, 16 bits per poort, dat wil ik in 18 8 bits RAM plekjes opslaan! 9 * 16 = 18 * 8 :)

Misschien heb ik het protocol niet goed uitgelegd, poging 2:

Blinken heeft 18 kolommen, 8 rijen.

De data hiervoor wordt over 9 lijntjes gestuurd.

Op datalijn 1: kolom 1 en 2.
Op datalijn 2: kolom 3 en 4 enz...

De data zou normaal in twee CMOS schuifregisters geklokt worden, dus op datalijn 1 komt het volgende binnen:

Eerst: MSB(bit8) van rij 2
bit7,2
6,2
.
.
.
1,2 (LSB)
8,1 (MSB)
.
.
.
1,1 (LSB)

Alle data van kolom 1 wil ik in de goede volgorde op één geheugenplek hebben in het RAM. En zo ook voor de overige kolommen.

Kan ik in 160us op 8Mhz dit redden? Ik moet dus per 10us 9 bits setten op een 9 tal geheugenplekken (80 cycles)

ok dan heb ik inderdaad het protocol niet goed begrepen.
weinig efficent dit protocool voor een uC


MSBeven:
in  temp,pinb       ;laat de stand van pinb in temp      
lds temp2,MSBrij2   ;laat de MSBrij2 in temp2
ror temp            ;schuif het lsb van temp in de carry
rol temp2           ;schijf de carry in lsb  en de rest door
sts MSBrij2,temp2   ;sla temp2 op in MSBrij2
lds temp2,MSBrij4
ror temp
rol temp2
sts MSBrij4,temp2
etc                 ;de rest gaat zo verder
in  temp,pind       ;speciaal voor portd opnieuw inladen.
lds temp2,MSBrij18
ror temp
rol temp2
sts MSBrij2,temp2
rjmp terug

Als je deze code 4 keer maakt dus de eerst voor MSBeven(het voorbeeld)dan LSBeven,MSBoneven en LSBoneven. werkt het.
counter wordt bij de eerste bit op 64 gezet.


lds temp, counter   ;laat de bit counter in temp
dec counter         ;verlaag counter
sts counter,temp    ;sla de counter op
sbrc temp,5         ;als counter minder dan 32 is naar oneven.
rjmp oneven
sbrc temp,4
rjmp evenMSB       ;als counter tussen 64 en 48 is naar MSBeven
rjmp evenLSB       ;als counter tussen 47 en 32 is naar LSBeven
oneven:
sbrc temp,4
rjmp onevenMSB     ;als counter tussen 31 en 16 is naar MSBoneven
rjmp onevenLSB     ;als counter tussen 64 en 48 is naar LSBoneven.
terug:

dit is de snelste methode die ik zo snel weet. Hetbovenste stuk duurt 6 cycles per bit plus 2* inladen van de poort in temp is 2 cycles. En de rjmp naar terug duurt 2 cycles.
Dat wordt (9*6)+2+2+2=60 cycles
dat onderste stuk dat bepaalt welke code aan de beurt is duurt maximaal 12 cycles

Dus 60 + 12 cycles = 72 cycles.
Dit is redelijk krap maar het kan wel. Je hebt dan 8 cycles over omtebepalen of de nieuwe data al binnen is.
Als je een paar nops bij de methodes zet die het snelst aangeroepen worden en 8 extra nops heb je een wachtlus van precies 80 cycles.
Als de code sneller wil maken kan je counter in een vast register stoppen bijv r0 dit maakt het 4 cycles korter.

Als ik iets snellers of iets kleiners en net zo snel weet post ik het wel.
EDIT:de counter werdt niet opgeslagen dit is nu gewijzigd.

je kunt krachtige instructies gebruiken met de X,Y of Z pointers die ineens je pointer verhogen/verlagen etc bij een bewerking.

Spaart een hoop cycles. Weet niet precies hoe het zit had het eens nodig om "snel" een 16 tal bytes te shadowen van de eeprom naar het sram.

asm instructie

ST X+,Rd als instructie geeft een post increment van de X pointer na de 'store' opdracht van register Rd in het sram. locatie in het sram is dan waarnaar de x pointer wijst als ik het goed herinner. en X pointer is een 16 bit pointer die aan R26:R27 hangt.

de helpfile van avr studio is altijd handig ;)

zo als de data nu opgeslagen wordt zou je de x,y of z pointer 2 moeten verhogen iedere keer dat je opslaat. hierdoor heb je 2 cycles per bit meer nodig dus het wordt alleen maar langzamer.


MSBeven:
clr r0              ;maak r0 leeg
in  temp,pinb       ;laat de stand van pinb in temp
lds temp2,X        ;laat data in temp2 en verhoog pointer
ror temp            ;schuif het lsb van temp in de carry
rol temp2           ;schijf de carry in lsb  en de rest 
door
sts X+,temp2
inc r26             ;tel een op bij x 
adc r27,r0

alleen als je de geheugen indeling wijzigt van
MSBR1
LSBR1
MSBR2
LSBR2
MSBR3
LSBR3
naar
MSBR2
MSBR4
MSBR6
....
LSBR2
LSBR4
LSBR6
.....
MSBR1
MSBR3
MSBR5
.....
LSBR1
LSBR3
LSBR5
met deze geheugen indeling kan het met deze code waarbij wel eerst x moet worden ingeladen. Het voordeel hiervan is dat code size kleiner wordt. Maar het is net zo snel per bit en x moet eerst worden ingeladen. Het is dus langzamer.


MSBeven:
ldi xh,eersteplekh
ldi xl,eersteplekl
in  temp,pinb       ;laat de stand van pinb in temp
lds temp2,X        ;laat data in temp2 en verhoog pointer
ror temp            ;schuif het lsb van temp in de carry
rol temp2           ;schijf de carry in lsb  en de rest 
door
sts X+,temp2

Je zou ook gewoon de resultaten in de registers kunnen laten staan kost je wel 18 van 32 regs maar zo erg is dat niet.


MSBeven:
in  temp,pinb       ;laat de stand van pinb in temp
ror temp            ;schuif het lsb van temp in de carry
rol r2              ;schijf de carry in rij2
ror temp            ;schuif het lsb van temp in de carry
rol r4              ;schijf de carry in rij4

dus kost maar 2 cycles per bit
dat wordt dus (9*2)+1+1+12=32 cycles

Bedankt voor alle reacties, hier kan ik zeker wat mee! :)

Dat van de registers is best een goed plan, maar ik weet niet of ik er genoeg over heb... Als dit zo is doe ik dat wel.

Voor de geinteresseerden: Het schema (OrCAD) en de source tot nu toe.

Als het allemaal af is stel ik de source gewoon beschikbaar, tevens komt er dan een heel bouwplan en PCB ontwerp bij.

De source is nu bijna af, hier staat ie! Alles staat in 223 regels code!

Wat is er nog niet gebeurt?

- Het testen van de source in AVR studio
- Real life testen
- Documentatie van alle source (meeste staat er wel)

Het door mij gemaakte BlinkenAVR schema staat hieronder! Als het goed is ben ik niets vergeten (behalve de LEDs zelf). Willen jullie het ook ff checken als je zin hebt?

Klik op het schema voor de grote versie
http://home.planet.nl/~benadski/Tweakers/blinkenAVR.gif

En misschien is nu de source ook wat makkelijker te begrijpen, dus kijk daar ook ff naar. :)

Bedankt!

Ik zou U3 compleet van fet's voorzien, dan kun je deze module's van 8x8 ook gebruiken.
http://www.futurlec.com/Pictures/Blue_Red_8X8_Matrix_Sm.jpg

Deze waren (zijn ?) in november 2003 voor $1.90 per module bij futurlec te koop.

http://www.futurlec.com/Specials.shtml

Die kan je zowieso al gebruiken toch? Er zitten 18 rijen op (en deze heeft er 16 nodig). Die U3 + FET kun je dus zelfs weglaten.

Ik heb die modules trouwens ook besteld. Op de site stond trouwens eerst rood-blauw, maar helaas was het rood-groen. Maarja, ook erg leuk voor die prijs! :)

De reden dat die modules zo goedkoop zijn is denk ik de kleine luchtbelletjes die in de modules te vinden zijn. Dat verslechtert de warmteafvoer van de LEDchips, dus stuur ze niet met een te grote stroom aan!