initial commit
This commit is contained in:
18
README.md
Normal file
18
README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# RC2014 - Quazar OLED board
|
||||
|
||||
This project provides MACRO-80 assembler code for `oled` program to drive OLED display for RC2014 by Quazar. It provides a Rust "script" to convert 128x32 black and white image to hex output suitable for the `oled` program.
|
||||
|
||||
## Compiling
|
||||
|
||||
```
|
||||
m80 =oled.mac/z
|
||||
l80 oled,oled/n/e
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```
|
||||
oled
|
||||
```
|
||||
|
||||
Now paste your image hex data as generated by `oled-to-hex`.
|
||||
58
oled-to-hex
Executable file
58
oled-to-hex
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env -S denim
|
||||
/* Cargo.toml
|
||||
[package]
|
||||
name = "oled-to-hex"
|
||||
version = "0.1.0"
|
||||
authors = ["Anonymous"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
image = { version = "0.25.8", default-features = false, features = ["png"] }
|
||||
*/
|
||||
|
||||
use image::GenericImageView;
|
||||
use image::ImageReader;
|
||||
use image::Pixel;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
|
||||
/// Example script description
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let file = env::args().skip(1).next().ok_or(IoError::new(
|
||||
ErrorKind::NotFound,
|
||||
"expected PNG 128x32 file path",
|
||||
))?;
|
||||
println!("Loading {}", file);
|
||||
|
||||
let img = ImageReader::open(file)?.decode()?;
|
||||
let (w, h) = img.dimensions();
|
||||
println!("Loaded file {}x{}", w, h);
|
||||
if w != 128 && h != 32 {
|
||||
return Err(Into::into(IoError::new(
|
||||
ErrorKind::InvalidData,
|
||||
"bad immage dimensions",
|
||||
)));
|
||||
}
|
||||
|
||||
for row in 0..4 {
|
||||
for column in 0..128 {
|
||||
let mut byte = 0u8;
|
||||
for bit in 0..8 {
|
||||
byte = byte >> 1;
|
||||
let x = column;
|
||||
let y = row * 8 + bit;
|
||||
let pixel = img.get_pixel(x, y);
|
||||
let luma = pixel.to_luma()[0];
|
||||
if luma > 128 {
|
||||
byte = byte | 128;
|
||||
}
|
||||
}
|
||||
print!("{:02X}", byte);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// vim: ft=rust
|
||||
198
oled.mac
Normal file
198
oled.mac
Normal file
@@ -0,0 +1,198 @@
|
||||
.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
|
||||
BIN
oled_compute.png
Normal file
BIN
oled_compute.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
oled_cpm.png
Normal file
BIN
oled_cpm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 983 B |
BIN
oled_tog_hxd.png
Normal file
BIN
oled_tog_hxd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 616 B |
BIN
oled_tog_hxd_grad.png
Normal file
BIN
oled_tog_hxd_grad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
oled_zilog.png
Normal file
BIN
oled_zilog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 858 B |
Reference in New Issue
Block a user