Files
rc2014-oled/oled.mac
2025-10-27 19:51:57 +00:00

280 lines
6.5 KiB
Plaintext

.Z80
ASEG ; absolute addressing
ORG 100h ; skip CP/M
CR EQU 0Dh ; carriage return
LF EQU 0Ah ; new line
BDOS EQU 0005h ; BDOS entry point
PSTR EQU 09h ; print string
CRED EQU 01h ; read console
FOPE EQU 0Fh ; file open
FRED EQU 14h ; file read next record
FCB EQU 5Ch ; File Control Block
FCBFNAME EQU FCB+01h ; FCB File Name
FCBEX EQU FCB+0Ch ; FCB Excent Number
FCBRC EQU FCB+0Fh ; FCB Record Count
FCBCR EQU FCB+20h ; FCB Current Record
FB EQU 80h ; File Buffer
OLED EQU 50h ; base addr of OLED card
ORST EQU 04h ; reset command (H)
OBUF EQU 02h ; chip select (L), buffer (H)
ODB EQU 01h ; display byte (H)
OCMD EQU 00h ; command (L)
; 4 rows of display
OROWA EQU 0B0h ; select top row
OROWB EQU 0B1h ; select second row
OROWC EQU 0B2h ; select third row
OROWD EQU 0B3h ; select bottom row
OCOL0 EQU 04h ; left most column
OSELC EQU 10h ; select column command
OCOL EQU 80h ; column count: 128 columns
; 128 columns from 4 to 131
; 1Xh, 0Yh - XY = 04h to 83h
; MAIN
CALL OINIT ; init OLED
CALL OCLS ; clear screen
CALL OCSTART ; go to start
LD A,(FCBFNAME) ; load first char of file name
CP ' ' ; check file name provided
JP NZ,MAIN1
CALL PROMPTREAD ; read from prompt
RET ; exit to CP/M
MAIN1:
CALL FILEREAD ; read from file
RET ; exit to CP/M
PROMPTREAD:
LD DE,MSGPROMPT
CALL PRINT ; print prompt
CALL READLINE ; read row A
CALL READLINE ; read row B
CALL READLINE ; read row C
CALL READLINE ; read row D
RET
FILEREAD:
LD DE,MSGFILEREAD
CALL PRINT ; print reading from file
XOR A
LD (FCBEX),A ; select 0'th extent
LD (FCBRC),A ; clear
LD (FCBCR),A ; select 0'th record
LD C,FOPE ; open file
LD DE,FCB ; use default FCB
CALL BDOS
CP 0FFh ; is error
JP Z,FILEREAD1
XOR A
LD (FCBCR),A ; start from beginning
CALL READRECORD ; read 128 byte record
CALL READRECORD
CALL READRECORD
CALL READRECORD
RET
FILEREAD1:
LD DE,MSGOPENERR
CALL PRINT
LD A,0FFh
RET
READLINE:
LD D,OCOL ; number of columns
READLINE1:
PUSH DE
CALL READHEX ; read hex input from console
CALL ODATA ; write to OLED
POP DE
DEC D ; count down columns
JP NZ,READLINE1 ; next column
RET
; reads block using default FCB
; A=0 - OK
; A=FFh - error
READRECORD:
LD C,FRED ; read file
LD DE,FCB ; use default FCB
CALL BDOS
CP 0 ; check status code
JP NZ,READRECORD1
LD D,OCOL ; bytes to read
LD HL,FB ; start of file buffer
READRECORD0:
LD A,(HL) ; load byte
PUSH DE
PUSH HL
CALL ODATA ; send to oled
POP HL
POP DE
INC HL ; next byte
DEC D ; count columns down
JP NZ,READRECORD0
RET
READRECORD1:
LD DE,MSGREADERR
CALL PRINT
LD A,0FFh ; error
RET
OINIT:
CALL ORESET ; reset OLED
LD HL,OINITSEQ ; commands to send
OINITLOOP:
LD A,(HL) ; load command byte to A
CP 0FFh ; check if we are done
RET Z ; marker reached
CALL OCOMMAND ; send command from A
INC HL ; next command
JR OINITLOOP ; do next command
ORESET:
LD C,OLED ; base I/O address
LD B,ORST OR OBUF ; RST H, /CS H, DB L
OUT (C),A ; write any A, to (C) + B
REPT 4
NOP ; delay
ENDM
LD B,OBUF ; clear RST
OUT (C),A ; send
REPT 20
NOP ; long delay
ENDM
RET
OCLS:
CALL OCSTART ; set start
CALL OCLSROW ; clear row A
CALL OCLSROW ; clear row B
CALL OCLSROW ; clear row C
CALL OCLSROW ; clear row D
RET
; set cursor to start
OCSTART:
LD A,OSELC ; select column
CALL OCOMMAND
LD A,OCOL0 ; column 0
CALL OCOMMAND
LD A,OROWA ; select first row
CALL OCOMMAND
RET
OCLSROW:
;XOR A ; display byte to write (0)
LD A,0FFh ; turn on all pixels
LD D,OCOL ; count columns in D
OCLSROW1:
CALL ODATA ; write A to displey
DEC D ; next column
JR NZ,OCLSROW1
RET
; A = command to send to OLED
OCOMMAND:
LD C,OLED ; base I/O
LD B,OCMD ; send command
OUT (C),A ; send
REPT 4
NOP
ENDM
LD B,OCMD OR OBUF
OUT (C),A ; send
REPT 10
NOP
ENDM
RET
; Write to OLED memory
; A = graphic byte to dispaly memory
ODATA:
LD C,OLED ; base I/O
LD B,ODB ; select Data Byte mode
OUT (C),A ; output byte
REPT 4
NOP
ENDM
LD B,OBUF OR ODB
OUT (C),A ; output byte
NOP
NOP
RET
; Read byte from console
READ:
LD C,CRED ; read from console
CALL BDOS ; call CP/M
RET ; A=char
; Reads 4 bit value (0-F)
READNIB:
CALL READ
LD B,41h ; compare with 'A' (10)
CP B
JP NC,RNB1 ; A>=B
SUB 30h ; sub '0'
RET
RNB1:
SUB 41h-10 ; sub 'A'-10
AND 0Fh ; clear to 4 bits so 'a-f' also work
RET
; Reads two bytes (0-F) from console
; A = byte read
READHEX:
CALL READNIB ; read MSD nibble
SLA A ; shift 4 bits
SLA A
SLA A
SLA A
LD B,A ; B=A
PUSH BC ; save B
CALL READNIB ; read LSD nibble
POP BC ; restore B
OR B ; OR B to A
RET
; DE - address to $ terminated string
PRINT:
LD C,PSTR ; load function number
CALL BDOS ; call CP/M
RET
MSGPROMPT:
DB 'OLED:>', CR, LF,'$' ; string terminated with $
MSGFILEREAD:
DB 'Reading from file', CR, LF, '$'
MSGOPENERR:
DB 'Error opening file', CR, LF, '$'
MSGREADERR:
DB 'Error reading file', CR, LF, '$'
; Initialization sequence
; 081h,080h - set contrast (080h full)
; 020h,000h - set horizontal window wrapping
; 021h,004h,083h - window full width
; 022h,000h,003h - window full height
OINITSEQ:
DB 0AEh,0D5h,0A0h,0A8h
DB 01Fh,0D3h,000h,0ADh
DB 08Eh,0D8h,005h,0A1h
DB 0C8h,0DAh,012h,091h
DB 03Fh,03Fh,03Fh,03Fh
DB 081h,070h,0D9h,0D2h
DB 0DBh,034h,0A6h,0A4h
DB 0AFh,020h,000h,021h
DB 004h,083h,000h,003h
DB 0FFh ; end marker
END