Post by Mario MalenicaPost by ChupoTrenutno inace radim s atmega8 - covjek koji je narucio uredjaj ga je
imao pa, s obzirom da je overkill a nista nije vremenski kriticno, mogu
bez brige raditi i u C-u ;-)
Atmega8 ima 8KB programske i 1kb data memorije. Dobro, i 512 byte-a
EEPROM-a.
Znam, zato i kazem da je overkill za ovo sta radim i da bez brige mogu
koristiti C (ne moram nista napraviti u assembler-u)
Post by Mario MalenicaStandardni C nema rješenje koje trebaš, zapravo niti jedan C kompajler s
kojim sam radio (pa i ovi za mikrokontrolere) nije imao nešto takvo.
Koliko razumijem, ti planiraš podatke staviti u programsku memoriju, a
vidim nisi naveo kako bi to bilo tijekom rada (SPM instrukcija), nego u
fazi izrade SW-a. Pa bi se tu moglo odraditi s nekoliko opcija.
Prva je za slučaj da imaš puno array-a, a ne da ti se tipkati kod - uzmeš
"glavni" array i zatim napišeš mali program koji offsetira za koliko je
potrebno i zapiše sve te array-e u nekakvu header datoteku, koju zatim
ubaciš u svoj projekt.
Ako nemaš mjesta u flashu, ima tamo u čipu i nekih 512 byte-a EEPROM-a, a i
nije nešto puno sporiji od čitanja iz flash memorije, no trebati će ti
dodatni kod za pristup podacima.
Drugi način je funkcija koja inkrementira vrijednost, a to može odraditi
tako da joj kao parametar daješ člana array-a i offset. Stack ti ne bi
trebao biti problem, prepostavljam da imaš tih 30 i nešto byte-a RAM-a
slobodno.
Ovo za 25 byte-ova koliko imaju 12c508 i 12f508 sam spomenuo kao
nastavak na nedavnu raspravu s Zeljkom na comp.programiranje (da li
ima/nema smisla raditi u assembleru, zasto ima/nema, ...).
Post by Mario MalenicaČini mi se kako se inline poziv ovakve funkcije ne bi isplatio,
jer bi pojeo više prostora u programskoj memoriji od jednostavnog
deklariranja array-a.
Ili ako imaš dovoljno RAM-a, napravi funkciju koja odradi alociranje
prostora za array, pa onda kopiranje i inkrementiranje. Kao rezultat vratiš
pointer na array. :)
Nakon korištenja naravno oslobađaš alociranu memoriju.
No, u ovom slučaju treba i obavezno raditi provjere je li zbog nekog
razloga crklo alociranje memorije.
Sve sam napravio ali bi mi u fazi testiranja dobro doso spomenuti
pseudo-op. Evo jednog nedavnog primjera gdje sam (na Z80) koristio
takvu mogucnost. S obzirom da rutina radi u interrupt-u a generirace
sliku i na border-u (ovo je testna faza), krajnji program ce morati
prilikom prolaska kroz vise grana uvijek trajati tocno isti broj
taktova. Na nekim mjestima mogu uz drukciju organizaciju podataka od
standardne smanjiti broj instrukcija. U ovoj konkretnoj rutini sam bez
offset-a na ASCII kodove mogo isto postici da sam pointer HL na 15616
inicijalizirao na tu adresu umanjenu za 256 ali planiram dodati jos
stvari i to mi ne bi odgovaralo jer mi treba da mi HL pokazuje na 8
praznih byte-ova (definicija space character-a). Izmedju ta dva stanja
bi se mogo prebacivati s INC H i natrag s DEC H ali mi vise odgovara da
su offset-i vec u 'ASCII'-ima. Rutina jos ni izdaleka nije
optimizirana:
;26.06.2012. by Chupo
;IM2 mode
;stari trik za ustediti 256 byte-ova za tabelu interrupt vectora
;character set addr u ROM-u: 15616 (#3D00)
;ako se izbace naredbe oznacene sa strelicama i otkomentira RET,
;onda se umjesto okomite linije ne generira nista nego se samo
;ostavlja jedan prazan stupac
;text je definiran s ASCII kodovima umanjenim za 32 (SPACE = 0)
;legalni kodovi su od 0 do 95
;oznaka za kraj texta je #FF
;definicije karaktera se uzimaju iz ROM-a (addr 15616 = #3D00)
;program je samomodificijajuc (*)
;OUT (#FE),A unutar interrupt-a mijenjaju BORDER tako da se
;moze vidjeti koliko rutina trosi vremena
;snapshot entry point je #52, na toj adresi u ROM-u je #C9 (RET)
device zxspectrum48
org #c000 ;49152
pocetak di ;iskljuci interrupte za vrijeme promjene mode-a
ld a,#39 ;visi byte pokazuje na vise od 256 #FF-ova u
ROM-u
ld i,a ;podesi interrupt vector
im 2 ;interrupt mode 2
ei ;ponovo omoguci interrupt-e
ret ;vrati se (u Basic)
int_addr di
push af ;spremi registre na stack
push hl
push de
push bc
ld a,5
out (254),a
ld hl,16384+6144 ;HL = adresa prvog atributa
push hl
pop de ;DE = adresa prvog atributa
inc hl ;HL = adresa drugog atributa
ld a,8 ;8 redova
scroll_l ld bc,31 ;brojac prebacivanja za LDIR
ldir ;scroll jednog reda atributa ulijevo
push af ;spremi registre
push hl
push de
push bc
call crtaj ;nacrtaj kvadratic
pop bc ;vrati registre
pop de
pop hl
pop af ;vrati A
inc hl ;slijedeci red
inc de
dec a ;brojac redova
jr nz,scroll_l
ld a,7
out (254),a
pop bc ;vrati registre sa stack-a
pop de
pop hl
pop af
jp #38 ;pozovi interrupt rutinu iz ROM-a
;crtanje kvadratica u 32. stupcu
;input: A = 8..1 (broj stupca)
;row = 8 - A
;8 --> 0, 7 --> 1, ..., 1 --> 7
crtaj neg
add a,8 ;A = 8 - A
ld (row),a ;spremi izracunatu vrijednost
ld hl,15616 ;HL = adresa definicije charactera u ROM-u
ld de,msg ;DE = adresa poruke
ld a,(pos) ;procitaj offset
add a,e
ld e,a ;DE pokazuje na trenutni character
jr nc,skip4
inc d
skip4 ld a,(de) ;A = ASCII trenutnog character-a
cp #ff ;da li je oznaka za kraj texta?
jr nz,skip3 ;ako nije onda je ASCII, preskoci
ld a,%00100000 ;PAPER = GREEN
<--------------------------------
ld (atr+1),a ;plava okomita crta (*)
|
ld a,(row) ;procitaj row offset |
cp 7 ;da li je bio zadnji red? |
jr nz,b_line ;ako nije, preskoci resetiranje offset-a
<------
xor a ;kraj text-a i zadnji red, A = 0
ld (pos),a ;resetiraj string offset
;ret ;vrati se na scroll (jedan stupac ce biti prazan)
ld a,(col) ; <---------------------------------------------
dec a ; |
ld (col),a ;korekcija kad se ne crta iz ROM-a |
jr b_line ; <---------------------------------------------
skip3 ld b,#00 ;nije bila oznaka za kraj texta
ld c,a
sla c
rl b
sla c
rl b
sla c
rl b ;BC = 8*ASCII
add hl,bc ;HL pokazuje na prvi byte charactera
ld a,(row) ;procitaj row offset
add a,l
ld l,a
jr nc,skip1
inc h ;HL = HL + A
skip1 ld a,(col) ;procitaj column offset
ld b,a ;B je brojac za rotaciju
ld a,(hl) ;procitaj definiciju reda character-a
rot_row rla ;najvisi bit u carry
djnz rot_row ;nakon petlje je u carry bit koji trazimo
ld a,%00111000 ;PAPER = WHITE
jr nc,skip2 ;ako je pixel 0 preskoci
ld a,%00101000 ;PAPER = CYAN
skip2 ld (atr+1),a ;modificira instrukciju LD A,#00 (*)
b_line ld hl,22528+31 ;HL = adresa zadnjeg atributa u prvom
redu
ld a,(row) ;ponovo procitaj row offset
sla a
sla a
sla a
sla a
sla a ;A = A*32
add a,l
ld l,a ;HL pokazuje na zadnji atribut u row redu
atr=$ ld a,#00 ;parametar se modificira (*)
ld (hl),a ;nacrtaj kvadratic
ld a,(row) ;procitaj row offset
cp 7 ;da li je bio zadnji red?
ret nz ;ako nije bio zadnji, vrati se
ld a,(col) ;bio je zadnji red, procitaj column offset
cp 8 ;da li je bio zadnji stupac u character-u?
jr z,last_row ;ako je bio i zadnji stupac, preskoci
inc a ;povecaj brojac stupaca
ld (col),a ;spremi ga
ret ;vrati se
last_row ld a,1 ;bio je zadnji stupac a nacrtan je i
zadnji red
ld (col),a ;resetiraj brojac za stupce
ld a,(pos) ;procitaj string offset
inc a ;povecaj offset
ld (pos),a ;spremi ga za slijedeci put
ret ;povratak
msg abyte -32 " IM2 ATTRIBUTE SCROLLER by Chupo. MADE IN A FEW
HOURS, CAN STILL BE IMPROVED."
abyte -32 " READS CHAR DEFINITIONS FROM THE ROM AT ADDR 15616
"
abyte -32 #7f ;ASCII za ?
abyte -32 " Chupo 22.06.2012. "
defb #ff ;znak za kraj
pos defb 0 ;string offset
row defb 0 ;row offset
col defb 1 ;column offset (1 - 8)
;interrupt stuff
org #ffff ;tu ce biti interrupt vector bez obzira na podatak na
data BUS-u
defb #18 ;OP code instrukcije JR,e
;kao parametar ce se uzeti byte 0 u ROM-u (#FE -->
DI)
;to ce biti JR,$-13 i program ce se nastaviti na
65524
org 65524 ;#fff4
jp int_addr ;skok na interrupt rutinu
kraj
display " "
display "GRESAKA : ", /d, _ERRORS
display "UPOZORENJA : ", /d, _WARNINGS
display "DUZINA PROGRAMA: ", /a, kraj - pocetak, " bytes"
display " "
savesna "im2_attrText.sna", #52
--
Chupo