.org 0
; protocol.asm
; Stefano Salvi - 11 Novembre 2001
;
; Protocollo di comunicazione tra PC e scheda GPC2 con display LCD
;
; Il piedino P1.2 e' connesso al led giallo ed al cicalino
; il piedino P1.5 e' connesso al led rosso
;
; La scheda GPC2 possiede 32K di EPROM da 0 a 7FFF e 32 K di RAM da 8000 a f7FF.
;
; L'I/O aggiuntivo di GPC2 e' mappato come segue in memoria XDATA:
;
; 0FA00h .. 0FA3Fh PPI 8255
; 0FA40h .. 0FA7Fh TIMER 82C54 (primo)
; 0FA80h .. 0FABFh TIMER 82C54 (secondo)
; 0FAC0h .. 0FAFFh RTC 6242b
;
; 0FB00h .. 0FFFFh BUS esterno (ABACO Bus)
;
; In particolare, per il PPI 8255 avremo:
; 0FA00h -> PDA = Registro dati del port A
; 0FA01h -> PDB = Registro dati del port B
; 0FA02h -> PDB = Registro dati del port C
; 0FA03h -> CNT = registro di controllo
;
; L'8255 ha tre modi di funzionamento (Mode 0 = Basic Input Output, Mode 1 = Strobed
; Input Output, Mode 3 = Bi-Directional Bus), che possono essere selezionati indipendentemente
; per il gruppo Port B, Port C 0..3 e Port A,Port C 4..7.
; Avendo connesso alla scheda il tastierino (TIO 16), il solo modo che ci interessa e' lo 0,
; nel quale ogni port puo' essere programmato come ingresso o uscita, per entrambi i gruppi.
; Vediamo ora come programmare il PPI, tramite il port di controllo:
;
; Bit 0 -> Port C 0..3 : 1 = Input, 0 = Output
; Bit 1 -> Port B : 1 = Input, 0 = Output
; Bit 2 -> Modo Port B -> 0 = Mode 0, 1 = Mode 1
;
; Bit 3 -> Port C 4..7 : 1 = Input, 0 = Output
; Bit 4 -> Port A : 1 = Input, 0 = Output
; Bit 5 -+
; Bit 6 -+> Modo port A: 00 -> Mode 0, 01 -> Mode 1, 10-11 Mode 3
;
; Bit 7 -> Programmazione Interrupt : 0 -> Interrupt, 1 -> Modo
;
; Non mi preoccupo della programmazione dll'interrupt, quindi dovremo sempre programmare il
; bit 7 a 1.
;
; Il Port A e' collegato ai piedini 1..8 del connettore CN2 (Tasti rossi)
; Il Port B e' collegato ai DIP Switch
; Il Port C e' collegato ai piedini 9..16 del connettore CN2 (0..3 Tasti gialli, 4..7 Tasti verdi)
;
; Scrivo un programma che:
; - Programmi il Port A in uscita, il Port B in ingresso, i bit 0..3 del Port C in uscita e i
: bit 4..7 in ingresso.
;
; Il display ha:
; - Bus dati (8 bit - connesso al port A)
; - Un segnale di Enable 'E' connesso a Port C, bit 3, attivo sul fronte di discesa
; - Cinque abilitazioni di 'colonna', attive alte (connesse ad un latch)
; - Un segnale 'D/I' che deve essere alto per scrivere dati, basso per inviare cdomandi
; (connesso ad un latch)
;
; Le attivazioni delle colonne e D/I sono collegati ad un buffer:
; - Port C bit 1 e' l'enable del buffer (attivo alto/ latchato basso)
; - I bit da 0 a 4 del buffer sono le cinque clolnne (attive alte)
; - Il bit 5 del buffer e' il piedino D/I
; - Ai bit 4..7 di Port C sono connessi quattro pulsanti, Zero se premuti
;
.org 8050h
;
;
; ExLxB -> E -> Al display; L -> Al LATCH
.equ E, 1000B ;0000B
.equ NONE, 0000B ;1000B
.equ LATCH, 0010B ;1010B
.equ NONLATCH, 0000B ;1000B
;
; *****************************************************************************
; Definizione Indirizzi Assoluti Registri 'Timer' (registri di RB2)
.equ BlinkTout, 17H ; R7B2 Divisore Lampeggio Led
.equ RxTout, 16H ; R6B2 Registro timeout Ricezione Caratteri
.equ TransmitTout, 15H ; R5B2 Registro timeout Ritrasmissioni trasmettitore
.equ DeBounceTout, 14H ; R4B2 Registro timeout debounce
.equ RetryCount, 13H ; R3B2 Retry ancora da inviare
;
; *****************************************************************************
; Definizione Indirizzi assoluti e Costanti Interrupt Seriale
; USA RB1
.equ RxPtrLo, 0Fh ; R7B1 PTR RX Buffer Lo
.equ RxCommand, 0Eh ; R6B1 Comando ricevuto
.equ RxSt, 0Dh ; R5B1 Stato RX
.equ RxCks, 0Ch ; R4B1 CKS RX
.equ TxCnt, 0Bh ; R3B1 Conteggio Caratteri TX
.equ TxSt, 0Ah ; R2B1 Stato TX
.equ TxCks, 09h ; R1B1 CKS TX
.equ TxPtr, 08h ; R0B1 PRT TX Buffer
;
; Codifica Stati Ricevitore
.equ StIdle, 0 ; Tra un 'flag' e l'altro
.equ StFirst, 1 ; Primo carattere ricevuto (solo RX, gestione doppio FLAG)
.equ StStd, 2 ; Carattere normale
.equ StMask, 3 ; Carattere mascherato
.equ StCks, 4 ; Checksum (solo trasmissione)
.equ StCFlg, 5 ; Flag di chiusura (solo trasmissione)
.equ StBufOvfl, 6 ; Buffer overflow - attende fine pacchetto e termina
.equ StCksMask, 7 ; Invia il checksum mascherato (solo trasmissione)
.equ StEnding, 8 ; Fine Trasmissione (trasmesso anche Flag Chiusura - Solo Trasmissione)
;
.equ FLAGc, 7Eh ; Carattere 'Flag'
.equ ESCAPE, 7Dh ; Carattere di Trasparenza
.equ MASK, 20h ; Carattere con cui mascherare
;
.equ CONFIRM, 0FFh ; Conferma (comando ricevuto)
;
.equ SENDTO, 132 ; 660 mS / 5 mS -> numero di tick timeout di trasmissione
;
; *****************************************************************************
; Definizione Variabili BIT
.equ CmdRecvd, 0 ; Flag Comando Ricevuto
.equ CommandPending, 1 ; Flag spedizione Comando in corso (con ritrasmissioni)
.equ CommandSending, 2 ; Flag spedizione Comando in corso
.equ RispSending, 3 ; Flag Risposta da spedire
.equ RispOrCommand, 4 ; Flag: sto inviando Comando o Risposta?
.equ DeBouncheTO, 5 ; Flag: debounche in corso
;
; *****************************************************************************
; Definizione Variabili DATA
;
.equ CURCOL, 30h ; Variabile: colonna corrente
.equ CURBAND, 31h ; Variabile: Banda corrente (gruppo di 50 colonne)
.equ CURROW, 32h ; Variabile: Riga corrente (gia' shiftata nei bit 6 e 7)
.equ RxBufLen, 33h ; Variabile: Lunghezza dei dati ricevuti
.equ TxRispLen, 34h ; Variabile: Lunghezza della risposta da inviare
.equ TxRispBuff, 35h ; Buffer: Risposta (38 byte max - 26 hex)
.equ TxRispDato, 36h ; Secondo carattere del buffer: parametro
.equ TxCommLen, 5Bh ; Lunghezza Comando da inviare
.equ TxCommBuf, 5Ch ; Comando da inviare (stato pulsanti - 2 caratteri)
.equ TxCommTStat, 5Dh ; posto per lo stato dei bottoni nel buffer Tx
.equ CurButtons, 5Eh ; Stato attuale bottoni
.equ StackStart, 5Fh ; Inizio Area di stack
;
; *****************************************************************************
; Definizione Variabili XDATA
;
.equ RxBuff, 0F700h ; Buffer di ricezione. Ho 256 byte a disposizione
.equ RxComm, 0F700h ; Comando Ricevuto
.equ RxCol, 0F701h ; Se il comando e' 'scrivi ...', colonna iniziale
.equ RxRow, 0F702h ; Se il comando e' 'scrivi ...', riga
.equ RxData, 0F703h ; Inizio dell'area dati
.equ RxBufPage, 0F7h ; Parte alta dell'indirizzo
;
.equ DREG, 0FA00h ; Registro Port A (dato display)
.equ CREG, 0fa03h ; Registro di controllo PPI
;
; *****************************************************************************
;
sjmp START ; Salto a START, perche' adesso devo metter i vettori di TI0 e SI
;
.org 8053h ; External Interrupt 0
;
.org 805Bh ; Timer 0 Interrupt
ajmp TIMINT
;
.org 8063h ; External Interrupt 1
;
.org 806bh ; Timer 1 Interrupt
;
.org 8073h ; Serial Interrupt
sjmp SERINT
;
START:
mov SP,#StackStart
acall ClrScr ; Inizializza il display e lo cancella
;
mov PSW,#0 ; Seleziona RB0 per main
;
; Inizializzazione Variabili
mov RxSt,#StIdle ; RxSeriale inizialmente 'idle'
mov TxSt,#StIdle ; TxSeriale inizialmente 'idle'
mov BlinkTout,#200 ; Conteggio iniziale Lampeggiatore
mov RxTout,#0 ; Rx Timeout fermo
mov TransmitTout,#0 ; ReTransmit Timeout fermo
mov DeBounceTout,#0 ; Debounch Timeout fermo
mov CurButtons,#0 ; Tasti inizialmente rilasciati
clr CmdRecvd ; Nessun comando ancora ricevuto
clr CommandPending ; Nessun comando in corso di invio
clr CommandSending ; Flag spedizione Comando in corso
clr RispSending ; Flag Risposta da spedire
clr DeBouncheTO ; Flag: debounche in corso
;
; Impostazione Seriale
;
mov IE,#0 ; nessun interrupt
mov IP,#0 ; tutti a priorita' bassa
mov SCON,#52H ; Modo 2, REN, TI
mov TMOD,#21H ; No Gate, Timer, Modo 2;No Gate, Timer, Modo 1
mov TCON,#50H ; T1 running, T0 Running
mov TH1,#0FDH ; 9600 baud
;
; Impostazione Timer 0: divisore 4608 -> impostare a 60928 = EE00
;
mov TH0,#0EEH ; Parte alta divisore
mov TL0,#00H ; Parte bassa divisore
mov BlinkTout,#200 ; Conteggio iniziale
mov IE,#92H ; EA, ES, ET0
;
cpl P1.5 ; Fa lampeggiare il led
;
ajmp main
;
;*****************************************************************************
;
; Rotuine Interrupt Seriale
; USA RB1
; R7 PTR RX Buffer Lo (la parte alta e' fissa, funge anche da contatore)
; R6 Comando ricevuto
; R5 Stato RX
; R4 CKS RX
; R3 Conteggio Caratteri TX
; R2 Stato TX
; R1 CKS TX
; R0 PRT TX Buffer
; ----------------------------------------------------------------------------
;
SERINT:
push acc
push PSW
mov PSW,#08H ; Seleziona RB1
;
; +++++++++++++++++++++++++++++++++++++++++++++
; Rx
; +++++++++++++++++++++++++++++++++++++++++++++
;
jnb RI,norx
mov a,sbuf
clr RI
;
cjne R5,#StIdle,StFirstQ
;
; +++++++++++ Stato 'Idle'
;
cjne a,#FLAGc,norx ; Scarta tutto, eccetto al 'flag'
FLAGREC: ; Ha ricevuto un 'flag', inizia ricezione
mov R5,#StFirst ; Cambia stato
mov R7,#0 ; Inizializza conteggio/puntatore
mov R4,#0 ; Inizializza checksum
mov RxTout,#22 ; Timeout di 110mS (22 * 5)
;
sjmp norx
;
; +++++++++++ Stato 'First'
;
StFirstQ:
cpl P1.5 ; Fa lampeggiare il led
cjne R5,#StFirst,StStdQ
;
cjne a,#FLAGc,NORMCHAR ; Se non e' un secondo 'FLAG', gestione normale
sjmp FLAGREC ; Se e' un 'FLAG', gestisce come fosse il primo
NORMCHAR:
mov R6,a ; Ripone il comando per poi
mov R5,#StStd ; Se non e' un 'FLAG', passa a carattere normale
;
; +++++++++++ Stato 'Std'
;
StStdQ:
cjne R5,#StStd,StMaskQ
;
cjne a,#FLAGc,ESCAPEQ ; Se non e' un 'FLAG' di chiusura, controlla con MASK
;
; Ha ricevuto un FLAG: chiusura pacchetto
;
mov R5,#StIdle ; Ritorna Idle
mov RxTout,#0 ; Ferma il timer
cjne R4,#0,norx ; Il checksum deve essere 0, altrimenti pacchetto errato
;
; Pacchetto corretto
;
cjne R6,#CONFIRM,COMMAND ; Se e' un comando ricevuto, lo gestisce
;
; Conferma
;
clr CommandPending ; Indica che non c'e' piu' alcun comando pendente
mov TransmitTout,#0 ; Ferma il timer dei ritentativi
cpl P1.2 ; Lampeggia Led Giallo
sjmp norx
COMMAND:
mov a,R7 ; Recupera il conteggio
dec a ; elimina il checksum
mov RxBufLen,a ; inserisce lunghezza nella variabile opportuna
setb CmdRecvd
sjmp norx
;
ESCAPEQ:
cjne a,#ESCAPE,NORMC ; Se non e' un 'ESCAPE' e' un carattere normale
;
mov R5,#StMask ; Cambia banalmente lo stato
sjmp norx
;
NORMC:
acall AddChar
sjmp norx
;
; +++++++++++ Stato 'Mask'
;
StMaskQ:
cjne R5,#StMask,StBufOvflQ
;
cjne a,#FLAGc,NORMEXC ; Se non e' un 'FLAG' allora OK
; sjmp NORMEXC
; Ha ricevuto un FLAG: errore !!!
RXERROR:
mov R5,#StIdle ; Ritorna Idle
mov RxTout,#0 ; Ferma il timer
sjmp norx
;
NORMEXC:
mov R5,#StStd ; Ritorna a stato normale
xrl a,#MASK ; Ripristina il carattere
acall AddChar ; e lo 'sistema'
sjmp norx
;
; +++++++++++ Stato 'Idle'
;
StBufOvflQ:
cjne R5,#StBufOvfl,RXERROR
;
cjne a,#FLAGc,norx ; Se non e' un 'FLAG' allora OK
; Ha ricevuto un FLAG: Fine pacchetto - sbagliato
sjmp RXERROR
;
norx:
; +++++++++++++++++++++++++++++++++++++++++++++
; Tx
; +++++++++++++++++++++++++++++++++++++++++++++
;
jnb TI,notx
clr TI
;
; +++++++++++ Stato 'Std'
;
cjne R2,#StStd,TxEscQ
;
mov a,@R0 ; Legge il carattere corrente
add a,R1 ; Aggiunge a Checksum
mov R1,a ; Rimette a posto il checksum
mov a,@R0 ; Legge il carattere corrente di nuovo
cjne a,#FLAGc,TxEscTs ; Se e' 7e (flag) o 7d (esc)
sjmp TxMaskCh
TxEscTs:
cjne a,#ESCAPE,TxStCh
TxMaskCh:
mov sbuf,#ESCAPE ; Spedisce il carattere
mov R2,#StMask ; Cambia stato
sjmp notx
;
TxStCh:
mov sbuf,a ; Spedisce il carattere
inc R0
;
djnz R3,notx ; Non ha finito i caratteri, OK
;
mov R2,#StCks ; Caratteri finiti: Cambia stato
;
sjmp notx
;
; +++++++++++ Stato 'Esc'
;
TxEscQ:
cjne R2,#StMask,StCksQ
;
mov a,@R0 ; Legge il carattere corrente
xrl a,#MASK ; Lo maschera
mov R2,#StStd ; Cambia stato - ritorna a carattere normale
sjmp TxStCh ; Continua come con carattere normale
;
; +++++++++++ Stato 'Cks'
;
StCksQ:
cjne R2,#StCks,StCksMaskQ
;
mov a,R1 ; Recupera il checksum
cpl a
inc a ; Calcola -Checksum
cjne a,#FLAGc,TxEscCk ; Se e' 7e (flag) o 7d (esc)
sjmp TxMaskTsCk
TxEscCk:
cjne a,#ESCAPE,TxStChk
TxMaskTsCk:
mov R1,a ; Ripone il checksum calcolato
mov sbuf,#ESCAPE ; Spedisce il carattere
mov R2,#StCksMask ; Cambia stato
sjmp notx
;
TxStChk:
mov sbuf,A ; Spedisce il carattere
mov R2,#StCFlg ; Cambia stato -> Invio Flag chiusura
;
sjmp notx
;
; +++++++++++ Stato 'CksMask'
;
StCksMaskQ:
cjne R2,#StCksMask,StCFlgQ
;
mov a,R1 ; Recupera il checksum calcolato (gia' invertito)
xrl a,#MASK ; Lo maschera
mov sbuf,A ; Spedisce il carattere mascherato
mov R2,#StCFlg ; Cambia stato -> Invio Flag chiusura
;
sjmp notx
;
; +++++++++++ Stato 'CFlg'
;
StCFlgQ:
cjne R2,#StCFlg,StEndingQ
;
mov sbuf,#FLAGc ; Spedisce il flag di chiusura
mov R2,#StEnding ; Cambia stato -> Attendo fine
;
sjmp notx
;
; +++++++++++ Stato 'Ending' (default)
;
StEndingQ:
mov R2,#StIdle ; Cambia stato -> Fine
;
jnb RispOrCommand,EndingCommand
;
clr RispSending ; Fine invio
jnb CommandSending,notx ; Se non deve inviare un comando
;
mov a,TxCommLen ; Recupera dimensione buffer
acall ReSendCommand ; Avvia la spedizione
;
sjmp notx ; Fine
;
EndingCommand:
;
clr CommandSending ; Indica che ha finito la trasmissione
jnb RispSending,notx ; Se non deve inviare un comando
;
mov a,TxRispLen ; Recupera dimensione buffer
acall SendPktReal ; Avvia la spedizione
;
notx:
;
pop psw
pop acc
reti ; Fine Interrupt Handler
;
; Routine di appoggio: agginge un carattere al buffer, calcolandone il checksum
;
AddChar:
push DPH
push DPL
mov DPL,R7 ; Parte bassa indirizzo
mov DPH,#RxBufPage ; Parte alta, costante
movx @dptr,a ; mette via il dato
pop DPL
pop DPH
inc R7 ; incrementa il puntatore
cjne R7,#253,NOOVFL ; Se non ha fatto overflov, niente
mov R5,#StBufOvfl ; Va in 'buffer overflow
NOOVFL:
add a,R4 ; calcola il checksum
mov R4,a ; e rimette via il risultato
ret
;
;*****************************************************************************
;
; Routine Interrupt Timer 0
;
; Usa RB2
; R7 17H Divisore Lampeggio Led
; R6 16H Timeout RxSeriale
; R5 15H Timeout Trasmettitore
; R4 14H Timeout Debounce
; R3 13H Retry ancora da inviare
;
TIMINT:
push acc
push PSW
mov PSW,#10H ; Seleziona RB2
;
clr TR0 ; 1 Ferma timer 0
mov acc,TL0 ; 1 - preleva la parte bassa
add a,#07H ; 1 - 00h + 7 cicli di adesso
mov TL0,acc ; 1 - rimette a posto
mov a,TH0 ; 1 - preleva la parte alta
addc a,#0EEh ; 1 - somma con riporto (a 16 bit)
mov TH0,a ; 1 - risistema
setb TR0 ; 1 Riavvia Timer 0
;
djnz R7,NOBLINK
mov R7,#200 ; 200 * 5 mS
cpl P1.5 ; Fa lampeggiare il led
NOBLINK:
;
; Timeout Rx Seriale
;
mov A,R6 ; R6 = timeout Tx Seriale
jz NORXTO ; se e' gia' scaduto, sta fermo
djnz R6,NORXTO ; conta i ticks
;
; Timeout Rx Seriale scaduto
mov RxSt,#StIdle ; Riporta lo stato a 'idle' senza indicare la ricezione
;
NORXTO:
;
; Timeout Trasmettitore
;
mov A,R5 ; R5 = timeout Trasmettitore
jz NOTRASMTO ; se e' gia' scaduto, sta fermo
djnz R5,NOTRASMTO ; conta i ticks
;
; Timeout Trasmettitore scaduto
;
djnz R3,Retry ; Conta le riprove effettuate
clr CommandPending ; Fine riprove
sjmp NOTRASMTO ; termina
;
Retry:
;
mov a,TxCommLen ; Recuper dimensione buffer
acall ReSendCommand ; Ripete la spedizione
sjmp NOTRASMTO ; termina
;
NOTRASMTO:
;
; Timeout Debounch
;
mov A,R4 ; R5 = timeout Debounch
jz NODEBNCHTO ; se e' gia' scaduto, sta fermo
djnz R4,NODEBNCHTO ; conta i ticks
;
; Timeout Debounch scaduto
;
clr DeBouncheTO ; timeout scaduto
;
NODEBNCHTO:
;
pop psw
pop acc
reti ; Fine Interrupt Handler
;
;*****************************************************************************
;
; ---- Funzioni di gestione del pacchetto da inviare ----
SendConf:
mov TxRispBuff,#0FFh ; Mette nel buffer 'conferma'
mov a,#1 ; Lunghezza Conferma - poi continua con SendPkt
;
; Funzione che invia un pacchetto di risposta
; Il pacchetto da ritornare deve gia' essere nel buffer
; a contiene la dimensione del buffer
;
SendPkt:
mov TxRispLen,a ; Immagazzina la lunghezza
setb RispSending ; Indica risposta pendente
jb CommandSending,SendPktEnd ; Se sta gia' trasmettendo, non avvia
;
; Avvia trasmissione, inviando kickoff
;
SendPktReal:
setb RispOrCommand ; Indica che sta trasmettendo una risposta
mov sbuf,#FLAGc ; Invia il flag
mov TxCnt,a ; Inizializza il conteggio
mov TxCks,#0 ; Inizializza il checksum
mov TxPtr,#TxRispBuff ; Punta al buffer da trasmettere
mov TxSt,#StStd ; Stato carattere normale
;
SendPktEnd:
ret
;
SendCommand:
cpl P1.2
jb CommandPending,SendCommandEnd ; Se sta facendo ancora i ritentativi, non manda
;
mov TxCommLen,a ; Imposta la lunghezza del pacchetto
setb CommandPending ; Pacchetto in invio (ritrasmissioni)
mov RetryCount,#5 ; Imposta il numero di riprove
ReSendCommand:
setb CommandSending ; Pacchetto in invio (pacchetto)
;
jb RispSending,SendCommandEnd ; Se sta gia' trasmettendo, non avvia
;
mov TransmitTout,#SENDTO ; Imposta il timeout di trasmissione
clr RispOrCommand ; Indica che sta trasmettendo un comando
mov sbuf,#FLAGc ; Invia il flag
mov TxCnt,a ; Inizializza il conteggio
mov TxCks,#0 ; Inizializza il checksum
mov TxPtr,#TxCommBuf ; Punta al buffer da trasmettere
mov TxSt,#StStd ; Stato carattere normale
;
SendCommandEnd:
ret
;
;*****************************************************************************
;
; ---- Funzioni di gestione del display ----
;
;-----------------------------------------------------------------
; Cancella il display - Inizializza il PPI, inizializza il display
ClrScr:
mov CURCOL,#0 ; Variabile: colonna corrente
mov CURBAND,#1 ; Variabile: Banda corrente (gruppo di 50 colonne)
mov CURROW,#0 ; Variabile: Riga corrente (gia' shiftata nei bit 6 e 7)
mov DPTR,#CREG ; Port CNT di PPI
mov A,#10001010b ; Mode 0 per A e B, A in OUT,
; Chi in IN, B in in, Clo in OUT
movx @dptr,a ; Setta il PPI
mov DPL,#0 ; Sempre puntato sul port dati
;
mov r7,#3bh ; Up Mode
acall outControl
mov r7,#03eh ; Start Page 0
acall outControl
;
mov R6,#0
;
CSlp0:
mov A,R6
swap a
rl a
rl a
mov R7,A
acall outControl ; Seleziono il banco (gotoXY)
acall setAllData ; Seleziona tutti i banchi insieme
mov r5,#50 ; 50 colonne
CSlp1:
mov a,#0
acall outByte
djnz r5,CSlp1
;
inc R6
cjne R6,#4,CSlp0 ; Loop per i quattro banchi
;
mov r7,#39h ; Display on
acall outControl
ret
;
;-----------------------------------------------------------------
; Si posiziona alla colonna (assoluta) ed alla riga indicata
; INPUT:
; A -> Colonna (0..249)
; R7-> Riga (0..2)
; Utilizza:
; A, R7
gotoXY:
mov CURCOL,A
mov A,R7 ; R7 = Riga
swap A
rl A
rl A ; A = R7 * 64
mov CURROW,A ; Riga corrente (bit 6 e 7)
mov R7,#1 ; Inizializza conteggio bande
bandlp:
mov A,CURCOL
add A,#-50 ; toglie una banda
jnc endband ; NC -> CURCOL < 50 -> Esce
mov CURCOL,A ; Mette il resto in CURCOL
mov A,R7
clr c
rlc A ; Passa alla banda successiva
mov R7,A
sjmp bandlp ; Loop per tutte le bande
endband: ; Fine loop bande
mov CURBAND,R7 ; E mette nella variabile
realgoto:
mov A,CURROW ; Prende la riga
anl a,#11000000B; Tiene solo riga (toglie eventuale sporco)
orl A,CURCOL ; Aggiunge la colonna
mov R7,A
acall outControl ; invia il comando (gotoXY)
mov a,#00100000B; Setta bit B/I (Dato)
orl A,CURBAND ; Banda selezionata
acall outSel ; Seleziona la banda
ret
;
;-----------------------------------------------------------------
; Invia un carattere al display
; Input:
; A -> carattere (troncato a 7 bit)
; Utilizza:
; A, R7, R6, R5, R4
;
outChar:
mov DPTR,#chargen ; Punta alla tabella
noremap:
;
anl A,#7fh ; scarta l'eccesso' dell'indice
mov B,#8
mul AB ; moltiplica il codice per 8
add A,DPL ; Somma la base della tabella
mov R6,A ; Parte bassa indirizzo in R6
mov A,B ; Recupera parte alta del prodotto
addc A,DPH ; Somma la base (con riporto)
mov R5,A ; Parte alta indirizzo in R5
mov R4,#0 ; Colonna
outClp:
mov DPL,R6
mov DPH,R5
mov A,R4 ; Colonna
movc A,@A+DPTR ; Codice
mov DPTR,#0FA00h ;DREG ; 0FA00H ; Punta al registro dati
acall outDato ; Spara fuori il dato
inc R4
cjne R4,#6,outClp
ret
;
;-----------------------------------------------------------------
; Invia un byte di dato al display, in maniera sequenziale,
; passando da una 'banda' alla successiva
; Input:
; A -> Dato
; DPTR -> Port A
; Utilizza:
; R7, A, DPTR
;
outDato:
acall outByte ; Invia il dato corrente
;
inc CURCOL ; conta il dato
mov A,CURCOL ; guarda dove e' arrivato
cjne A,#50,outDnorm ; Non e' arrivato a 50
; CURCOL = 50 (cambia banda)
mov CURCOL,#0 ; Ricomincia da 0
mov A,CURBAND ; Banda selezionata
rl A ; passa alla banda successiva
mov CURBAND,A ; Rimette a posto la nuova abanda
acall realgoto ; va alla posizione scelta
outDnorm:
ret;
;
;-----------------------------------------------------------------
; Invia la parola di selezione al latch esterno
; B0 .. B4 -> Colonna (Attiva alta)
; B5 -> D/I Alto = Dato, basso = Comando
; Input:
; A -> Parola di selezione
; DPTR -> Port A
; Sporca A
outSel:
movx @DPTR,A ; Manda fuori la selezione
mov DPL,#2 ; Port C
mov A,#LATCH
movx @DPTR,A ; Alza l'enable (fa passare)
mov A,#NONLATCH
movx @DPTR,A ; Riabbassa l'enable (latcha)
mov DPL,#0 ; Ripristina DPTR
ret
;
;-----------------------------------------------------------------
; Invia un byte al display, sulla porta dati (gestisce il segnale 'E')
; Input: A = Dato
; DPTR -> Port A
; Sporca: A
outByte:
movx @DPTR,A
mov DPL,#2 ; Si posiziona sul Port C
mov A,#E ; Alza 'E'
movx @DPTR,A
mov A,#NONE ; Riabbassa 'E'
movx @DPTR,A
mov DPL,#0 ; Si riposiziona sul Port A
ret
;
;-----------------------------------------------------------------
; Invia un comando al display
; Input: R7 = comando
; DPTR -> Port A
; Sporca: A
outControl:
mov A,#011111B
acall outSel
mov A,R7
acall outByte
ret
;
;-----------------------------------------------------------------
setAllData:
mov A,#111111B
acall outSel
ret
;
;
; ---- Funzioni applicative ----
;
main:
;
mainlp:
;
jnb CmdRecvd,nomess1 ; Se non e' arrivato alcun comando, salta
clr CmdRecvd ; Cancella il flag: esguo comando
mov a,RxCommand ; Recupera il comando
;
cjne a,#10h,RstQ ; Riciesta Tasti
;
mov a,#90h ; Codice risposta
mov TxRispBuff,a ; Deposita nel buffer della risposta
mov a,CurButtons ; Stato corrente bottoni (non letto, ma gestito)
mov TxRispDato,a ; Deposita nel buffer
mov a,#2 ; lunghezza risposta
acall SendPkt ; invia la risposta
;
nomess1:
ajmp nomess
;
RstQ:
cjne a,#52h,WrCQ ; Reset Display
;
acall ClrScr ; Inizializza il display e lo cancella
acall SendConf ; Conferma il comando
;
ajmp nomess
;
WrCQ:
cjne a,#21h,WrGQ ; Scrivi Caratteri
;
; Posso usare R3, R2, R1 ed R0 (outChar)
;
mov DPTR,#RxCol
movx a,@DPTR
mov B,#6 ; Dimensione carattere
mul ab ; moltiplica la colonna per 6
mov r0,a ; ripone il dato
add a,#6 ; sottrae 250
jc EndWr ; supera 250, errore
mov a,b ; parte alta moltiplicazione
jnz EndWr ; non e' 0 : eccede
inc dptr ; passa a riga
movx a,@DPTR ; legge riga
mov r7,a ; Riga in R7
mov a,r0 ; colonna in A
mov DPTR,#DREG
acall GotoXY ; si posiziona
;
mov r0,#3 ; offset primo carattere
mov a,RxBufLen ; recupera dimensione buffer
add a,#-3 ; toglie 'comando', 'colonna' e 'riga'
mov r1,a ; r1 funge da contatore
;
; Loop scrittura caratteri
;
WrCLp:
mov DPH,#RxBufPage ; Prepara parte alta puntatore
mov DPL,R0 ; parte bassa
inc R0 ; incrementa puntatore
movx a,@DPTR ; recupera carattere
mov DPTR,#DREG ; ripunta DPTR per operazioni con caratteri
acall outChar ; invia il carattere letto
djnz r1,WrCLp ; loop fino a che non ha finito
;
EndWr:
mov DPTR,#DREG
acall SendConf ; Conferma il comando
;
sjmp nomess
;
WrGQ:
cjne a,#22h,RqIdQ ; Scrivi Grafica
;
; Posso usare R3, R2, R1 ed R0 (outChar)
;
mov DPTR,#RxCol
movx a,@DPTR
mov r0,a ; ripone il dato
add a,#6 ; sottrae 250
jc EndWrG ; supera 250, errore
inc dptr ; passa a riga
movx a,@DPTR ; legge riga
mov r7,a ; Riga in R7
mov a,r0 ; colonna in A
mov DPTR,#DREG
acall GotoXY ; si posiziona
;
mov r0,#3 ; offset primo carattere
mov a,RxBufLen ; recupera dimensione buffer
add a,#-3 ; toglie 'comando', 'colonna' e 'riga'
mov r1,a ; r1 funge da contatore
;
; Loop scrittura caratteri
;
WrGLp:
mov DPH,#RxBufPage ; Prepara parte alta puntatore
mov DPL,R0 ; parte bassa
inc R0 ; incrementa puntatore
movx a,@DPTR ; recupera carattere
mov DPTR,#DREG ; ripunta DPTR per operazioni con caratteri
acall outDato ; invia il carattere letto
djnz r1,WrGLp ; loop fino a che non ha finito
;
EndWrG:
mov DPTR,#DREG
acall SendConf ; Conferma il comando
;
sjmp nomess
;
RqIdQ:
cjne a,#44h,nomess ; Ritorna Identificazione
;
; Risponde con stringa di versione
;
mov r0,#TxRispBuff ; Punta al buffer destinazione
mov DPTR,#IdStr ; Punta alla stringa da copiare
mov R1,#0 ; Inizializza contatore
RqIdLp:
mov a,R1 ; Contatore = offset nella stringa
movc a,@DPTR+a ; Legge il carattere
mov @r0,a ; lo copia nel buffer
inc R0 ; incrementa il puntatore
inc R1 ; incrementa l'indice
jnz RqIdLp ; Continua fino a che non ha copiato lo 0
mov DPTR,#DREG ; Riposiziona il registro dati
mov a,R1 ; mette in a la lunghezza del buffer
acall SendPkt ; Invia il pacchetto di risposta
;
nomess:
jb DeBouncheTO,nobutton ; Se il timeout non e' scaduto, non ricontrolla
;
mov DPL,#2
movx A,@DPTR ; Legge i tasti
mov DPL,#0 ; Ripunta ai dati
swap a ; Mette i tasti nella parte bassa
cpl a ; inverte il dato (1 = tasto premuto)
anl a,#0fh ; Scara i dati 'non tastiera'
;
mov r1,a ; salva il dato della tastiera
xrl a,CurButtons ; controlla se il contenuto e' cambiato
jz nobutton ; no, nessuna azione
;
; Evento bottoni !!!
;
setb DeBouncheTO ; Indica che il timeout e' in corso
mov DeBounceTout,#20 ; imposta timeout di 100 mS (20 * 5)
mov TxCommBuf,#16h ; comando 'evento tastiera'
mov a,R1 ; recupera stato tasti
mov CurButtons,a ; aggiorna stato
mov TxCommTStat,a ; prepara il dato dei tasti
mov a,#2 ; lunghezza dato
acall SendCommand ; Invia il comando
;
nobutton:
;
ajmp mainlp
;
; Identificazione: preceduto dal codice della risposta, 38 Caratteri con il 'null' ed il comando
IdStr:
.db 0c4h, "Display~31 - {Stefano Salvi} :v.1,0",0
;
; Generatore di caratteri: set ASCII completo - 128 codici - matrice 5*7 (5*8 con le discendenti)
; i caratteri sono ruotati (sono orizzontali, con l'alto a destra).
; MSB e' la 'discendente'
;
chargen:
; 00 NU
.db 0001111b
.db 0111010b
.db 1001111b
.db 1000000b
.db 0111000b
.db 0, 0, 0
; 01 SH
.db 0010010b
.db 0010101b
.db 1111101b
.db 0010000b
.db 1111100b
.db 0, 0, 0
; 02 SX
.db 0010010b
.db 0010101b
.db 1001001b
.db 0110000b
.db 1001000b
.db 0, 0, 0
; 03 EX
.db 0011111b
.db 0010101b
.db 1011101b
.db 0110000b
.db 1001000b
.db 0, 0, 0
; 04 ET
.db 0011111b
.db 0010101b
.db 0011101b
.db 1111000b
.db 0001000b
.db 0, 0, 0
; 05 EQ
.db 0011111b
.db 0010101b
.db 0110101b
.db 1101000b
.db 0110000b
.db 0, 0, 0
; 06 AK
.db 0011110b
.db 0000101b
.db 1111110b
.db 0100000b
.db 1010000b
.db 0, 0, 0
; 07 BL
.db 0011111b
.db 0010101b
.db 1111010b
.db 1000000b
.db 1000000b
.db 0, 0, 0
; 08 BS
.db 0011111b
.db 0010101b
.db 1011010b
.db 1010100b
.db 0100100b
.db 0, 0, 0
; 09 HT
.db 0011111b
.db 0000100b
.db 0011111b
.db 1111000b
.db 0001000b
.db 0, 0, 0
; 0A LF
.db 0011111b
.db 0010000b
.db 1111100b
.db 0010100b
.db 0000100b
.db 0, 0, 0
; 0B VT
.db 0001111b
.db 0010000b
.db 0001111b
.db 1111100b
.db 0000100b
.db 0, 0, 0
; 0C FF
.db 0011111b
.db 0000101b
.db 1111101b
.db 0010100b
.db 0000100b
.db 0, 0, 0
; 0D CR
.db 0001110b
.db 0010001b
.db 1111101b
.db 0010100b
.db 1101000b
.db 0, 0, 0
; 0E SO
.db 0010010b
.db 0010101b
.db 0111101b
.db 1000100b
.db 0111000b
.db 0, 0, 0
; 0F SI
.db 0010010b
.db 0010101b
.db 1001101b
.db 1111100b
.db 1000100b
.db 0, 0, 0
; 10 DL
.db 0011111b
.db 0010001b
.db 1111110b
.db 1000000b
.db 1000000b
.db 0, 0, 0
; 11 D1
.db 0011111b
.db 0010001b
.db 1001110b
.db 1111100b
.db 1001000b
.db 0, 0, 0
; 12 D2
.db 0011111b
.db 0010001b
.db 1001110b
.db 1100100b
.db 1011000b
.db 0, 0, 0
; 13 D3
.db 0011111b
.db 0010001b
.db 1001110b
.db 1010100b
.db 0101000b
.db 0, 0, 0
; 14 D4
.db 0011111b
.db 0010001b
.db 0101110b
.db 1111100b
.db 0110000b
.db 0, 0, 0
; 15 NK
.db 0001111b
.db 0000010b
.db 1111111b
.db 0100000b
.db 1010000b
.db 0, 0, 0
; 16 SY
.db 0010010b
.db 0010101b
.db 0001001b
.db 1110000b
.db 0001000b
.db 0, 0, 0
; 17 EB
.db 0011111b
.db 0010101b
.db 1111101b
.db 1010100b
.db 0101000b
.db 0, 0, 0
; 18 CN
.db 0001110b
.db 0010001b
.db 1111001b
.db 0010000b
.db 1111000b
.db 0, 0, 0
; 19 EM
.db 0011111b
.db 0010101b
.db 1111101b
.db 0011000b
.db 1111100b
.db 0, 0, 0
; 1A SB
.db 0010010b
.db 0010101b
.db 1111101b
.db 1010100b
.db 0101000b
.db 0, 0, 0
; 1B EC
.db 0011111b
.db 0010101b
.db 0111001b
.db 1000100b
.db 1000100b
.db 0, 0, 0
; 1C FS
.db 0011111b
.db 0000101b
.db 1011001b
.db 1010100b
.db 0100100b
.db 0, 0, 0
; 1D GS
.db 0001110b
.db 0010001b
.db 1011101b
.db 1010100b
.db 0100100b
.db 0, 0, 0
; 1E RS
.db 0011111b
.db 0000101b
.db 1011010b
.db 1010100b
.db 0100100b
.db 0, 0, 0
; 1F US
.db 0000111b
.db 0001000b
.db 1001111b
.db 1010100b
.db 0100100b
.db 0, 0, 0
;
; 20
.db 0000000b
.db 0000000b
.db 0000000b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 21 !
.db 0000000b
.db 0000000b
.db 1011111b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 22 "
.db 0000000b
.db 0000111b
.db 0000000b
.db 0000111b
.db 0000000b
.db 0, 0, 0
; 23 #
.db 0010100b
.db 1111111b
.db 0010100b
.db 1111111b
.db 0010100b
.db 0, 0, 0
; 24 $
.db 0100100b
.db 0101010b
.db 1101011b
.db 0101010b
.db 001001b
.db 0, 0, 0
; 25 %
.db 1100011b
.db 0010011b
.db 0001000b
.db 1100100b
.db 1100011b
.db 0, 0, 0
; 26 &
.db 0110110b
.db 1001001b
.db 1010110b
.db 0100000b
.db 1010000b
.db 0, 0, 0
; 27 '
.db 0000000b
.db 0000000b
.db 0000111b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 28 (
.db 0000000b
.db 0011100b
.db 0100010b
.db 1000001b
.db 0000000b
.db 0, 0, 0
; 29 )
.db 0000000b
.db 1000001b
.db 0100010b
.db 0011100b
.db 0000000b
.db 0, 0, 0
; 2A *
.db 0101010b
.db 0011100b
.db 0111110b
.db 0011100b
.db 0101010b
.db 0, 0, 0
; 2B +
.db 0001000b
.db 0001000b
.db 0111110b
.db 0001000b
.db 0001000b
.db 0, 0, 0
; 2C ,
.db 0000000b
.db 1011000b
.db 0111000b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 2D -
.db 0001000b
.db 0001000b
.db 0001000b
.db 0001000b
.db 0001000b
.db 0, 0, 0
; 2E .
.db 0000000b
.db 1100000b
.db 1100000b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 2F /
.db 1100000b
.db 0010000b
.db 0001000b
.db 0000100b
.db 0000011b
.db 0, 0, 0
; 30 0
.db 0111110b
.db 1010001b
.db 1001001b
.db 1000101b
.db 0111110b
.db 0, 0, 0
; 31 1
.db 0000000b
.db 1000010b
.db 1111111b
.db 1000000b
.db 0000000b
.db 0, 0, 0
; 32 2
.db 1110010b
.db 1001001b
.db 1001001b
.db 1001001b
.db 1000110b
.db 0, 0, 0
; 33 3
.db 0100010b
.db 1000001b
.db 1001001b
.db 1001001b
.db 0110110b
.db 0, 0, 0
; 34 4
.db 0011000b
.db 0010100b
.db 0010010b
.db 1111111b
.db 0010000b
.db 0, 0, 0
; 35 5
.db 0100111b
.db 1000101b
.db 1000101b
.db 1000101b
.db 0111001b
.db 0, 0, 0
; 36 6
.db 0111100b
.db 1001010b
.db 1001001b
.db 1001001b
.db 0110000b
.db 0, 0, 0
; 37 7
.db 1100001b
.db 0010001b
.db 0001001b
.db 0000101b
.db 0000011b
.db 0, 0, 0
; 38 8
.db 0110110b
.db 1001001b
.db 1001001b
.db 1001001b
.db 0110110b
.db 0, 0, 0
; 39 9
.db 0000110b
.db 1001001b
.db 1001001b
.db 0101001b
.db 0011110b
.db 0, 0, 0
; 3A :
.db 0000000b
.db 0110110b
.db 0110110b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 3B ;
.db 0000000b
.db 1011011b
.db 0111011b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 3C <
.db 0001000b
.db 0010100b
.db 0100010b
.db 1000001b
.db 0000000b
.db 0, 0, 0
; 3D =
.db 0010100b
.db 0010100b
.db 0010100b
.db 0010100b
.db 0010100b
.db 0, 0, 0
; 3E >
.db 1000001b
.db 0100010b
.db 0010100b
.db 0001000b
.db 0000000b
.db 0, 0, 0
; 3F ?
.db 0000010b
.db 0000001b
.db 1011001b
.db 0000111b
.db 0000000b
.db 0, 0, 0
; 40 @
.db 0011100b
.db 0101010b
.db 1010101b
.db 1010101b
.db 1001110b
.db 0, 0, 0
; 41 A
.db 1111100b
.db 0010010b
.db 0010001b
.db 0010010b
.db 1111100b
.db 0, 0, 0
; 42 B
.db 1000001b
.db 1111111b
.db 1001001b
.db 1001001b
.db 0110110b
.db 0, 0, 0
; 43 C
.db 0111110b
.db 1000001b
.db 1000001b
.db 1000001b
.db 0100010b
.db 0, 0, 0
; 44 D
.db 1000001b
.db 1111111b
.db 1000001b
.db 1000001b
.db 0111110b
.db 0, 0, 0
; 45 E
.db 1111111b
.db 1001001b
.db 1001001b
.db 1001001b
.db 1000001b
.db 0, 0, 0
; 46 F
.db 1111111b
.db 0001001b
.db 0001001b
.db 0001001b
.db 0000001b
.db 0, 0, 0
; 47 G
.db 0111110b
.db 1000001b
.db 1000001b
.db 1001001b
.db 0111010b
.db 0, 0, 0
; 48 H
.db 1111111b
.db 0001000b
.db 0001000b
.db 0001000b
.db 1111111b
.db 0, 0, 0
; 49 I
.db 0000000b
.db 1000001b
.db 1111111b
.db 1000001b
.db 0000000b
.db 0, 0, 0
; 4A J
.db 0100000b
.db 1000000b
.db 1000000b
.db 1000000b
.db 0111111b
.db 0, 0, 0
; 4B K
.db 1111111b
.db 0001000b
.db 0010100b
.db 0100010b
.db 1000001b
.db 0, 0, 0
; 4C L
.db 1111111b
.db 1000000b
.db 1000000b
.db 1000000b
.db 1000000b
.db 0, 0, 0
; 4D M
.db 1111111b
.db 0000010b
.db 0001100b
.db 0000010b
.db 1111111b
.db 0, 0, 0
; 4E N
.db 1111111b
.db 0000010b
.db 0000100b
.db 0001000b
.db 1111111b
.db 0, 0, 0
; 4F O
.db 0111110b
.db 1000001b
.db 1000001b
.db 1000001b
.db 0111110b
.db 0, 0, 0
; 50 P
.db 1111111b
.db 0001001b
.db 0001001b
.db 0001001b
.db 0000110b
.db 0, 0, 0
; 51 Q
.db 0111110b
.db 1000001b
.db 1010001b
.db 0100001b
.db 1011110b
.db 0, 0, 0
; 52 R
.db 1111111b
.db 0001001b
.db 0011001b
.db 0101001b
.db 1000110b
.db 0, 0, 0
; 53 S
.db 0100010b
.db 1000101b
.db 1001001b
.db 1010001b
.db 0100010b
.db 0, 0, 0
; 54 T
.db 0000001b
.db 0000001b
.db 1111111b
.db 0000001b
.db 0000001b
.db 0, 0, 0
; 55 U
.db 0111111b
.db 1000000b
.db 1000000b
.db 1000000b
.db 0111111b
.db 0, 0, 0
; 56 V
.db 0000111b
.db 0011000b
.db 1100000b
.db 0011000b
.db 0000111b
.db 0, 0, 0
; 57 W
.db 1111111b
.db 0100000b
.db 0010000b
.db 0100000b
.db 1111111b
.db 0, 0, 0
; 58 X
.db 1100011b
.db 0010100b
.db 0001000b
.db 0010100b
.db 1100011b
.db 0, 0, 0
; 59 Y
.db 0000011b
.db 0000100b
.db 1111000b
.db 0000100b
.db 0000011b
.db 0, 0, 0
; 5A Z
.db 1100001b
.db 1010001b
.db 1001001b
.db 1000101b
.db 1000011b
.db 0, 0, 0
; 5B [
.db 0000000b
.db 1111111b
.db 1000001b
.db 1000001b
.db 0000000b
.db 0, 0, 0
; 5C \
.db 0000011b
.db 0000100b
.db 0001000b
.db 0010000b
.db 1100000b
.db 0, 0, 0
; 5D ]
.db 0000000b
.db 1000001b
.db 1000001b
.db 1111111b
.db 0000000b
.db 0, 0, 0
; 5E ^
.db 0000000b
.db 0000010b
.db 0000001b
.db 0000010b
.db 0000000b
.db 0, 0, 0
; 5F _
.db 1000000b
.db 1000000b
.db 1000000b
.db 1000000b
.db 1000000b
.db 0, 0, 0
; 60 @
.db 0000000b
.db 0000001b
.db 0000010b
.db 0000100b
.db 0000000b
.db 0, 0, 0
; 61 a
.db 0100000b
.db 1010100b
.db 1010100b
.db 1010100b
.db 1111000b
.db 0, 0, 0
; 62 b
.db 1111111b
.db 1000100b
.db 1000100b
.db 1000100b
.db 0111000b
.db 0, 0, 0
; 63 c
.db 0111000b
.db 1000100b
.db 1000100b
.db 1000100b
.db 1000100b
.db 0, 0, 0
; 64 d
.db 0111000b
.db 1000100b
.db 1000100b
.db 1000100b
.db 1111111b
.db 0, 0, 0
; 65 e
.db 0111000b
.db 1010100b
.db 1010100b
.db 1010100b
.db 0011000b
.db 0, 0, 0
; 66 f
.db 0000000b
.db 0001000b
.db 1111110b
.db 0001001b
.db 0000000b
.db 0, 0, 0
; 67 g
.db 0011000b
.db 0100100b
.db 10100100b
.db 10100100b
.db 1111100b
.db 0, 0, 0
; 68 h
.db 1111111b
.db 0001000b
.db 0001000b
.db 0001000b
.db 1110000b
.db 0, 0, 0
; 69 i
.db 0000000b
.db 1000100b
.db 1111101b
.db 1000000b
.db 0000000b
.db 0, 0, 0
; 6A j
.db 1000000b
.db 10000000b
.db 10000000b
.db 1110100b
.db 0000000b
.db 0, 0, 0
; 6B k
.db 0000000b
.db 1111111b
.db 0010000b
.db 0101000b
.db 1000100b
.db 0, 0, 0
; 6C l
.db 0000000b
.db 1000001b
.db 1111111b
.db 1000000b
.db 0000000b
.db 0, 0, 0
; 6D m
.db 1111100b
.db 0000100b
.db 0001000b
.db 0000100b
.db 1111000b
.db 0, 0, 0
; 6E n
.db 1111100b
.db 0000100b
.db 0000100b
.db 0000100b
.db 1111000b
.db 0, 0, 0
; 6F o
.db 0111000b
.db 1000100b
.db 1000100b
.db 1000100b
.db 0111000b
.db 0, 0, 0
; 70 p
.db 11111100b
.db 0100100b
.db 0100100b
.db 0100100b
.db 0011000b
.db 0, 0, 0
; 71 q
.db 0011000b
.db 0100100b
.db 0100100b
.db 0100100b
.db 11111100b
.db 0, 0, 0
; 72 r
.db 0000000b
.db 1111100b
.db 0001000b
.db 0000100b
.db 0000100b
.db 0, 0, 0
; 73 s
.db 1001000b
.db 1010100b
.db 1010100b
.db 1010100b
.db 0100100b
.db 0, 0, 0
; 74 t
.db 0000000b
.db 0000100b
.db 0111110b
.db 1000100b
.db 0000000b
.db 0, 0, 0
; 75 u
.db 0111100b
.db 1000000b
.db 1000000b
.db 1000000b
.db 0111100b
.db 0, 0, 0
; 76 v
.db 0011100b
.db 0100000b
.db 1000000b
.db 0100000b
.db 0011100b
.db 0, 0, 0
; 77 w
.db 0111100b
.db 1000000b
.db 0110000b
.db 100000b
.db 0111100b
.db 0, 0, 0
; 78 x
.db 1000100b
.db 0101000b
.db 0010000b
.db 0101000b
.db 1000100b
.db 0, 0, 0
; 79 y
.db 0011100b
.db 0100000b
.db 10100000b
.db 10100000b
.db 1111100b
.db 0, 0, 0
; 7A z
.db 1000100b
.db 1100100b
.db 1010100b
.db 1001100b
.db 1000100b
.db 0, 0, 0
; 7B {
.db 0000000b
.db 0001000b
.db 0110110b
.db 1000001b
.db 0000000b
.db 0, 0, 0
; 7C |
.db 0000000b
.db 0000000b
.db 1110111b
.db 0000000b
.db 0000000b
.db 0, 0, 0
; 7D }
.db 0000000b
.db 1000001b
.db 0110110b
.db 0001000b
.db 0000000b
.db 0, 0, 0
; 7E ~
.db 0000100b
.db 0000010b
.db 0000010b
.db 0000010b
.db 0000001b
.db 0, 0, 0
; 7F //
.db 0101010b
.db 1010101b
.db 0101010b
.db 1010101b
.db 0101010b
.db 0, 0, 0
;
|