Files
rc2014-oled/oled.mac
2025-10-20 20:13:44 +01:00

199 lines
4.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
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
OCOLL 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 PROMPT ; print prompt
CALL OCSTART ; go to start
CALL READLINE ; read row A
CALL READLINE ; read row B
CALL READLINE ; read row C
CALL READLINE ; read row D
RET ; exit to CP/M
READLINE:
LD D,OCOLL ; number of columns
READLINE1:
PUSH DE
CALL READHEX ; read hex input from console
CALL ODATA ; write to OLED
POP DE
DEC D ; count donw columns
JP NZ,READLINE1 ; next column
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 ; send 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,OCOLL ; 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
PROMPT:
LD C,PSTR ; load function number
LD DE,PROMPTMSG ; load string addr
CALL BDOS ; call CP/M
RET
PROMPTMSG:
DB 'OLED:>', CR, LF,'$' ; string terminated with $
; 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