add several example programs

This commit is contained in:
Zack Buhman 2023-06-15 16:22:22 +00:00
parent 05a68be57b
commit 10cf94edcd
28 changed files with 2292 additions and 40 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
*.bin
*.rom
*.asm
.#*
tools/otb-convert
tools/term

View File

@ -14,11 +14,29 @@ all:
%.prog: %.rom
minipro -p AT28C256 -w $<
%.term: %.bin
./tools/term $<
clean:
rm -f *.bin *.rom
rm -f $(basename $(wildcard *.in))
rm -f $(basename $(wildcard */*.in))
aoc/2020/day1/solution.bin: aoc/2020/day1/solution.asm aoc/mul24.asm aoc/hex.asm aoc/lcd.asm aoc/2020/day1/input.bin
oled.bin: oled.asm face.bin
res/keymap.bin: tools/keymap.py
python tools/keymap.py res/keymap.bin
keyboard.bin: keyboard.asm character-lcd.asm keymap.bin
keyboard2.bin: keyboard2.asm character-lcd.asm keymap.bin
graphic-font.bin: graphic-font.asm graphic-lcd.asm res/font.bin
keyboard3.bin: keyboard3.asm graphic-lcd.asm graphic-font.asm res/font.bin res/keymap.bin
.SUFFIXES:
.INTERMEDIATE:
.PRECIOUS: %.bin %.rom %.asm

View File

@ -11,4 +11,4 @@ loop: LDA # 1
STA a 8000
;; repeat
JMP a :loop
BRA r :loop

21
blink2.asm.in Normal file
View File

@ -0,0 +1,21 @@
include(`common.m4')
LDA # 1
STA a VIA1_DDRA
LDA # 1
STA a VIA2_DDRA
loop: LDA # 1
STA a VIA1_PORTA
LDA # 0
STA a VIA2_PORTA
LDA # 0
STA a VIA1_PORTA
LDA # 1
STA a VIA2_PORTA
BRA r :loop

174
bootloader.asm.in Normal file
View File

@ -0,0 +1,174 @@
; -*-asm-*-
include(`common.m4')
BRA r :reset ; RESB
JMP a 0202 ; IRQB
;; reset stack
reset: SEI i
LDX # ff
TXS i
;; CS high, SCLK low
LDA # hh(M_CS)
STA a VIA2_PORTB
LDA # hh(M_DDR_MASK)
STA a VIA2_DDRB
LDX # hh(M_CFGH)
LDY # hh(M_CFGL_BAUD_115200)
JSR a :spi16
define(SPI_IN_H, 2)dnl
define(SPI_IN_L, 1)dnl
define(SPI_OUT_H, 4)dnl
define(SPI_OUT_L, 3)dnl
define(LDR_OFFSET, fc)dnl
define(LDR_LEN, fd)dnl
define(LDR_ADDR_L, fe)dnl
define(LDR_ADDR_H, ff)dnl
;; read header
;;; begin hdr_len
LDX # hh(M_W_DATAH|M_W_DATAH_TE|M_W_DATAH_RTS)
LDY # 0
BRA r :_read_hdr_spi
read_header: LDX # hh(M_W_DATAH|M_W_DATAH_RTS)
LDY zp SPI_OUT_L
_read_hdr_spi: JSR a :spi16
LDA zp SPI_OUT_H
BMI r :_hdr_len ; BMI = if the leftmost bit is 0
_wait_hdr_len: LDX # hh(M_W_DATAH|M_W_DATAH_TE|M_W_DATAH_RTS)
LDY # 0
JSR a :spi16
LDA zp SPI_OUT_H
BPL r :_wait_hdr_len ; BPL = if the leftmost bit is 0
_hdr_len: LDA zp SPI_OUT_L
STA zp LDR_LEN
;;; end hdr_len
;;; begin hdr_al
LDX # hh(M_W_DATAH|M_W_DATAH_RTS)
LDY # 4c ; L
JSR a :spi16
LDA zp SPI_OUT_H
BMI r :_hdr_al ; BMI = if the leftmost bit is 0
_wait_hdr_al: LDX # hh(M_W_DATAH|M_W_DATAH_TE|M_W_DATAH_RTS)
LDY # 0
JSR a :spi16
LDA zp SPI_OUT_H
BPL r :_wait_hdr_al ; BPL = if the leftmost bit is 0
_hdr_al: LDA zp SPI_OUT_L
STA zp LDR_ADDR_L
;;; end hdr_al
;;; begin hdr_ah
LDX # hh(M_W_DATAH|M_W_DATAH_RTS)
LDY # 44 ; D
JSR a :spi16
LDA zp SPI_OUT_H
BMI r :_hdr_ah ; BMI = if the leftmost bit is 0
_wait_hdr_ah: LDX # hh(M_W_DATAH|M_W_DATAH_TE|M_W_DATAH_RTS)
LDY # 0
JSR a :spi16
LDA zp SPI_OUT_H
BPL r :_wait_hdr_ah ; BPL = if the leftmost bit is 0
_hdr_ah: LDA zp SPI_OUT_L
STA zp LDR_ADDR_H
;;; end hdr_ah
LDA zp LDR_LEN
BEQ r :_ldr_jump ; if (len == zero) goto _ldr_jump;
STZ zp LDR_OFFSET
LDX # hh(M_W_DATAH|M_W_DATAH_RTS)
LDY # 52 ; R
JSR a :spi16
BRA r :_data_cmp
;; transfer data
wait_data: LDX # hh(M_W_DATAH|M_W_DATAH_TE|M_W_DATAH_RTS)
LDY # 0
JSR a :spi16
_data_cmp: LDA zp SPI_OUT_H
BPL r :wait_data ; BPL = if the leftmost bit is 0
copy_fifo: LDY zp LDR_OFFSET
LDA zp SPI_OUT_L
STA (zp),y LDR_ADDR_L
INC zp LDR_OFFSET
DEC zp LDR_LEN
BEQ r :read_header
LDX # hh(M_W_DATAH)
LDY zp SPI_OUT_L
JSR a :spi16
LDA zp SPI_OUT_H
BMI r :copy_fifo ; BMI = if the leftmost bit is 1
BRA r :wait_data
_ldr_jump: JMP (a) LDR_ADDR_L
;; CS low, SCLK low
spi16: LDA # %00000000
STA a VIA2_PORTB
STX zp 2
STY zp 1
;; SPI output
STZ zp 4
STZ zp 3
LDX # 2
_spi_next: LDY # 8
STY zp 0
_spi_8: ASL zp,x 0
LDA # 0 ; preclear MOSI
BCC r :_spi_zout
ORA # hh(M_DIN) ; set MOSI
_spi_zout: STA a VIA2_PORTB
ORA # hh(M_SCLK) ; set SCLK
STA a VIA2_PORTB
LDY a VIA2_PORTB ; DOUT on bit 7
CLC i ; preclear MISO
BPL r :_spi_zin ;
SEC i ; set MISO
_spi_zin: ROL zp,x 2
AND # hh(~M_SCLK & 0xff) ; clear SCLK
STA a VIA2_PORTB
DEC zp 0
BNE r :_spi_8
DEX i
BNE r :_spi_next
;; CS high, SCLK low
LDA # hh(M_CS)
STA a VIA2_PORTB
RTS s

83
character-lcd.asm.in Normal file
View File

@ -0,0 +1,83 @@
include(`common.m4')
;;; begin lcd_init
;; Set Port A to Output
lcd_init: LDA # hh(L_DDR_MASK)
STA a VIA0_DDRA
;; Function Set:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 1 B L F x x
;; (Bits 8/4, Lines 2/1, Font 5x11/5x8)
LDA # %00111000
JSR a :lcd_w_rs0
;; Display ON/OFF:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 0 0 0 D C B
;; (Display, Cursor, Blink)
LDA # %00001110
JSR a :lcd_w_rs0
;; Clear Display:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 0 0 0 0 0 1
LDA # %00000001
JSR a :lcd_w_rs0
;; Entry Mode Set:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 0 0 0 1 I/D S
;; (Increment/Decrement, Shift)
LDA # %00000110
JSR a :lcd_w_rs0
RTS s
;;; end lcd_init
;; write "instruction"
lcd_w_rs0: JSR a :lcd_wait
STA a VIA0_PORTB
LDA # 0
STA a VIA0_PORTA
LDA # hh(C_E)
STA a VIA0_PORTA
LDA # 0
STA a VIA0_PORTA
RTS s
;; write "data" to lcd
lcd_w_rs1: JSR a :lcd_wait
STA a VIA0_PORTB
LDA # hh(C_RS)
STA a VIA0_PORTA
LDA # hh(C_RS|C_E)
STA a VIA0_PORTA
LDA # hh(C_RS)
STA a VIA0_PORTA
RTS s
;; wait BF
lcd_wait: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a VIA0_DDRB
_lcd_wait: LDA # hh(C_RW)
STA a VIA0_PORTA
LDA # hh(C_E|C_RW)
STA a VIA0_PORTA
LDA a VIA0_PORTB
AND # %10000000
BNE r :_lcd_wait
LDA # hh(C_RW)
STA a VIA0_PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output
STA a VIA0_DDRB
PLA s
RTS s

124
common.m4
View File

@ -1,27 +1,109 @@
changecom(`@')dnl
dnl
define(PORTB, 8000)dnl
define(PORTA, 8001)dnl
define(DDRB, 8002)dnl
define(DDRA, 8003)dnl
define(T1CL, 8004)dnl
define(T1CH, 8005)dnl
define(T1LL, 8006)dnl
define(T1LH, 8007)dnl
define(T2CL, 8008)dnl
define(T2CH, 8009)dnl
define(SR, 800a)dnl
define(ACR, 800b)dnl
define(PCR, 800c)dnl
define(IFR, 800d)dnl
define(IER, 800e)dnl
define(VIA0_PORTB, 8000)dnl
define(VIA0_PORTA, 8001)dnl
define(VIA0_DDRB, 8002)dnl
define(VIA0_DDRA, 8003)dnl
define(VIA0_T1CL, 8004)dnl
define(VIA0_T1CH, 8005)dnl
define(VIA0_T1LL, 8006)dnl
define(VIA0_T1LH, 8007)dnl
define(VIA0_T2CL, 8008)dnl
define(VIA0_T2CH, 8009)dnl
define(VIA0_SR, 800a)dnl
define(VIA0_ACR, 800b)dnl
define(VIA0_PCR, 800c)dnl
define(VIA0_IFR, 800d)dnl
define(VIA0_IER, 800e)dnl
dnl
define(`L_CGRAM', `0b01000000')dnl
define(`L_DDRAM', `0b10000000')dnl
define(VIA1_PORTB, 8800)dnl
define(VIA1_PORTA, 8801)dnl
define(VIA1_DDRB, 8802)dnl
define(VIA1_DDRA, 8803)dnl
define(VIA1_T1CL, 8804)dnl
define(VIA1_T1CH, 8805)dnl
define(VIA1_T1LL, 8806)dnl
define(VIA1_T1LH, 8807)dnl
define(VIA1_T2CL, 8808)dnl
define(VIA1_T2CH, 8809)dnl
define(VIA1_SR, 880a)dnl
define(VIA1_ACR, 880b)dnl
define(VIA1_PCR, 880c)dnl
define(VIA1_IFR, 880d)dnl
define(VIA1_IER, 880e)dnl
dnl
define(`L_E', `0b001')dnl
define(`L_RS', `0b010')dnl
define(`L_RW', `0b100')dnl
define(VIA2_PORTB, 9000)dnl
define(VIA2_PORTA, 9001)dnl
define(VIA2_DDRB, 9002)dnl
define(VIA2_DDRA, 9003)dnl
define(VIA2_T1CL, 9004)dnl
define(VIA2_T1CH, 9005)dnl
define(VIA2_T1LL, 9006)dnl
define(VIA2_T1LH, 9007)dnl
define(VIA2_T2CL, 9008)dnl
define(VIA2_T2CH, 9009)dnl
define(VIA2_SR, 900a)dnl
define(VIA2_ACR, 900b)dnl
define(VIA2_PCR, 900c)dnl
define(VIA2_IFR, 900d)dnl
define(VIA2_IER, 900e)dnl
dnl ACR
dnl ACR
define(`ACR_SR_DISABLED', `0b00000000')dnl
define(`ACR_SR_IN_T2', `0b00000100')dnl
define(`ACR_SR_IN_PHI2', `0b00001000')dnl
define(`ACR_SR_IN_CB1', `0b00001100')dnl
define(`ACR_SR_OUT_FREE_T2', `0b00010000')dnl
define(`ACR_SR_OUT_T2', `0b00010100')dnl
define(`ACR_SR_OUT_PHI2', `0b00011000')dnl
define(`ACR_SR_OUT_CB1', `0b00011100')dnl
dnl LCD common
define(`L_DDR_MASK', `0b11111111')dnl
dnl character LCD
define(`C_CGRAM', `0b01000000')dnl
define(`C_DDRAM', `0b10000000')dnl
dnl
define(`C_E', `0b00000001')dnl
define(`C_RS', `0b00010000')dnl
define(`C_RW', `0b00100000')dnl
dnl
define(`hh', `eval($1, 16)')dnl
define(`bh', `eval(0b$1, 16)')dnl
dnl graphic LCD
define(`G_E', `0b00000010')dnl
define(`G_C1', `0b00000100')dnl
define(`G_C2', `0b00001000')dnl
define(`G_RS', `0b00010000')dnl
define(`G_RW', `0b00100000')dnl
dnl MAX3100
define(`M_DDR_MASK', `0b01110000')dnl
define(`M_DOUT', `0b10000000')dnl input
define(`M_DIN', `0b01000000')dnl output
define(`M_SCLK', `0b00100000')dnl output
define(`M_CS', `0b00010000')dnl output
dnl MAX3100 CFG bits
define(`M_CFGH', `0b11000000')dnl
define(`M_CFGH_FENB', `0b00100000')dnl 0=enable FIFO
define(`M_CFGH_SHDN', `0b00010000')dnl 1=shutdown
define(`M_CFGH_TMB', `0b00001000')dnl 1=enable transmit done interrupt
define(`M_CFGH_RMB', `0b00000100')dnl 1=enable data received interrupt
define(`M_CFGH_PMB', `0b00000010')dnl 1=enable parity interrupt
define(`M_CFGH_RAMB', `0b00000001')dnl 1=enable framing error interrupt
define(`M_CFGL_IR', `0b10000000')dnl 1=enable IrDA timing mode
define(`M_CFGL_ST', `0b01000000')dnl 1=two stop bits
define(`M_CFGL_PE', `0b00100000')dnl 1=parity enabled
define(`M_CFGL_L', `0b00010000')dnl 1=7-bits; 0=8-bits
define(`M_CFGL_BAUD_230400', `0b00000000')dnl
define(`M_CFGL_BAUD_115200', `0b00000001')dnl
define(`M_CFGL_BAUD_57600', `0b00000010')dnl
define(`M_CFGL_BAUD_38400', `0b00001001')dnl
define(`M_CFGL_BAUD_19200', `0b00001010')dnl
define(`M_CFGL_BAUD_9600', `0b00001011')dnl
define(`M_CFGL_BAUD_600', `0b00001111')dnl
dnl MAX3100 data bits
define(`M_R_DATA', `0b00000000')dnl
define(`M_W_DATAH', `0b10000000')dnl
define(`M_W_DATAH_TE', `0b00000100')dnl 1=inhibit TX
define(`M_W_DATAH_RTS', `0b00000010')dnl 1=drive RTS low; 0=drive RTS high
define(`M_W_DATAH_PT', `0b00000001')dnl 1=parity1; 0=parity0
dnl bit7 high "data has been received"
dnl bit6 high "transmit buffer empty"

99
graphic-font.asm.in Normal file
View File

@ -0,0 +1,99 @@
; -*-asm-*-
include(`common.m4')
;; BRA r :_gfont_reset ; RESB
;; NOP i ; IRQ
;; _gfont_reset: LDX # ff
;; TXS i
;; JSR a :gfont_init
;; LDA # ^97
;; JSR a :gfont_draw_c2
;; stop: BRA r :stop
;; Set pins 0-4 on Port A to Output
gfont_init: LDA # hh(L_DDR_MASK)
STA a VIA0_DDRA
;; Display ON/OFF:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 1 1 1 1 1 D
;;
LDA # %00111111
JSR a :glcd_w_rs0_c2
LDA # %00111111
JSR a :glcd_w_rs0_c1
STZ zp 0
JSR a :glcd_fill
LDA # %01000000 ; Y address
ORA # ^55
JSR a :glcd_w_rs0_c2
LDA # %10111000 ; X page
ORA # ^7
JSR a :glcd_w_rs0_c2
RTS s
;;; begin gfont_draw_c2 (A)
;; begin A << 3
gfont_draw_c2: STA zp 0
STZ zp 1
ASL zp 0
ROL zp 1
ASL zp 0
ROL zp 1
ASL zp 0
ROL zp 1
;; end A << 3
CLC i
LDA # :_bin_res/font_start_l
ADC zp 0
STA zp 0
LDA # :_bin_res/font_start_h
ADC zp 1
STA zp 1
LDY # 4
_gfont_c2_y_loop: LDA (zp),y 0
JSR a :glcd_w_rs1_c2
DEY i
BPL r :_gfont_c2_y_loop
RTS s
;;; end gfont_draw_c2
;;; begin gfont_draw_c1 (A)
;; begin A << 3
gfont_draw_c1: STA zp 0
STZ zp 1
ASL zp 0
ROL zp 1
ASL zp 0
ROL zp 1
ASL zp 0
ROL zp 1
;; end A << 3
CLC i
LDA # :_bin_res/font_start_l
ADC zp 0
STA zp 0
LDA # :_bin_res/font_start_h
ADC zp 1
STA zp 1
LDY # 4
_gfont_c1_y_loop: LDA (zp),y 0
JSR a :glcd_w_rs1_c1
DEY i
BPL r :_gfont_c1_y_loop
RTS s
;;; end gfont_draw_c1

131
graphic-lcd.asm.in Normal file
View File

@ -0,0 +1,131 @@
include(common.m4)
;;; begin glcd_init
glcd_fill: LDY # 00
LDA # %01000000 ; Y address
JSR a :glcd_w_rs0_c2
LDA # %01000000 ; Y address
JSR a :glcd_w_rs0_c1
_glcd_next_page: TYA i
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c2
TYA i
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c1
LDX # 40
_glcd_fill_page: LDA zp 0
JSR a :glcd_w_rs1_c2
LDA zp 0
JSR a :glcd_w_rs1_c1
DEX i
BNE r :_glcd_fill_page
INY i
CPY # 8
BNE r :_glcd_next_page
RTS s
;;; end glcd_init
;; write "instruction"
glcd_w_rs0_c2: JSR a :glcd_wait_c2
STA a VIA0_PORTB
LDA # hh(G_C2)
STA a VIA0_PORTA
LDA # hh(G_C2|G_E)
STA a VIA0_PORTA
LDA # hh(G_C2)
STA a VIA0_PORTA
RTS s
glcd_w_rs0_c1: JSR a :glcd_wait_c1
STA a VIA0_PORTB
LDA # hh(G_C1)
STA a VIA0_PORTA
LDA # hh(G_C1|G_E)
STA a VIA0_PORTA
LDA # hh(G_C1)
STA a VIA0_PORTA
RTS s
;; write "data" to lcd
glcd_w_rs1_c2: JSR a :glcd_wait_c2
STA a VIA0_PORTB
LDA # hh(G_RS|G_C2)
STA a VIA0_PORTA
LDA # hh(G_RS|G_C2|G_E)
STA a VIA0_PORTA
LDA # hh(G_RS|G_C2)
STA a VIA0_PORTA
RTS s
glcd_w_rs1_c1: JSR a :glcd_wait_c1
STA a VIA0_PORTB
LDA # hh(G_RS|G_C1)
STA a VIA0_PORTA
LDA # hh(G_RS|G_C1|G_E)
STA a VIA0_PORTA
LDA # hh(G_RS|G_C1)
STA a VIA0_PORTA
RTS s
;; wait BF
glcd_wait_c2: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a VIA0_DDRB
_glcd_wait-c2: LDA # hh(G_RW|G_C2)
STA a VIA0_PORTA
LDA # hh(G_RW|G_C2|G_E)
STA a VIA0_PORTA
LDA a VIA0_PORTB
AND # %10000000
BNE r :_glcd_wait-c2
LDA # hh(G_RW|G_C2)
STA a VIA0_PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output
STA a VIA0_DDRB
PLA s
RTS s
;; wait BF
glcd_wait_c1: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a VIA0_DDRB
_glcd_wait-c1: LDA # hh(G_RW|G_C1)
STA a VIA0_PORTA
LDA # hh(G_RW|G_C1|G_E)
STA a VIA0_PORTA
LDA a VIA0_PORTB
AND # %10000000
BNE r :_glcd_wait-c1
LDA # hh(G_RW|G_C1)
STA a VIA0_PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output
STA a VIA0_DDRB
PLA s
RTS s

121
keyboard.asm.in Normal file
View File

@ -0,0 +1,121 @@
include(`common.m4')
define(KBD_STATE, 0x40) ;;; 0x40 - 0x80
BRA r :reset ; RESB
NOP i ; IRQ
reset: LDX # ff
TXS i
JSR a :lcd_init
;; LDA # 61
;; JSR a :lcd_w_rs1
LDA # %11111111
STA a VIA1_PORTA
LDA # %00000000
STA a VIA1_DDRB
LDA # %11111111
STA a VIA1_DDRA
LDX # 80
LDA # f
_state: STA zp,x hh(KBD_STATE)
DEX i
BNE r :_state
forever: LDX # 7 ; state
LDA # %01111111
STA zp 0
loop0: LDA zp 0
STA a VIA1_PORTA
LDY # 4 ; bit
LDA a VIA1_PORTB
loop1: ROR A
PHP s
PHA s
;; (X * 8 + Y) * 2
TYA i
STA zp 1
TXA i
ASL A
ASL A
ASL A
CLC i
ADC zp 1
ASL A
;;
STX zp 1
TAX i
PLP s
BCS r :_kbd_up
LSR A ;
JSR a :lcd_w_rs1 ;
BPL r :_loop1_resume ;
_kbd_down: DEC zp,x hh(KBD_STATE)
BPL r :_loop1_resume
BNE r :_key_not_yet_down
;; if (KBD_STATE[X][0] == 0) {
LSR A
TAX i
LDA a,x :_bin_keymap_start
JSR a :lcd_w_rs1
;; }
_key_not_yet_down: LDA # ff
STA zp,x hh(KBD_STATE)
LDA # f
STA zp,x hh(KBD_STATE + 1)
BRA r :_loop1_resume
;;; Y is the offset of the current key
_kbd_up: DEC zp,x hh(KBD_STATE + 1)
BPL r :_loop1_resume
LDA # ff
STA zp,x hh(KBD_STATE + 1)
LDA # f
STA zp,x hh(KBD_STATE)
_loop1_resume: PLA s
LDX zp 1
DEY i
BPL r :loop1
SEC i
ROR zp 0
DEX i
BPL r :loop0
BRA r :forever
;; LDA # %00000001
;; JSR a :lcd_w_rs0
;; TXA i
;; CLC i
;; ADC # 30
;; STA a VIA1_PORTB
;; JSR a :lcd_w_rs1
;; LDA # 20
;; JSR a :lcd_w_rs1
;; TYA i
;; CLC i
;; ADC # 30
;; STA a VIA1_PORTB
;; JSR a :lcd_w_rs1

116
keyboard2.asm.in Normal file
View File

@ -0,0 +1,116 @@
include(`common.m4')
define(KBD_STATE, 0x40) ;;; 0x40 - 0x7f
define(KBD_STATE2, 0x80) ;;; 0x80 - 0xbf
BRA r :reset ; RESB
NOP i ; IRQ
reset: LDX # ff
TXS i
JSR a :lcd_init
;; LDA # 61
;; JSR a :lcd_w_rs1
LDA # %11111111
STA a VIA1_PORTA
LDA # %00000000
STA a VIA1_DDRB
LDA # %11111111
STA a VIA1_DDRA
LDX # 80
LDA # 0
_state: STA zp,x hh(KBD_STATE)
DEX i
BNE r :_state
loop: LDX # 7 ; state
LDA # %01111111
STA zp 0
loop0: LDA zp 0
STA a VIA1_PORTA
LDY # 4 ; bit
LDA a VIA1_PORTB
loop1: ROR A
PHA s ; [A]
PHP s ; [P,A]
;; (X * 8 + Y) * 2
TXA i
ASL A
ASL A
ASL A
CLC i
STY zp 1
ADC zp 1
;;
PLP s ; [A]
PHX s ; [X,A]
TAX i
BCS r :_kbd_up
;;; down
_kbd_down: LDA zp,x hh(KBD_STATE)
CMP # 4
BNE r :_kbd_state_inc
;; if (kbd_state == 0)
LDA a,x hh(KBD_STATE2)
BNE r :_loop1_resume
INC a,x hh(KBD_STATE2)
LDA a,x :_bin_keymap_start
JSR a :kbd_char
BRA r :_loop1_resume
;; }
_kbd_state_inc: INC zp,x hh(KBD_STATE)
BRA r :_loop1_resume
;;; end down
_kbd_up: LDA zp,x hh(KBD_STATE)
BEQ r :_kbd_up_state2
_kbd_state_dec: DEC zp,x hh(KBD_STATE)
BRA r :_loop1_resume
_kbd_up_state2: STZ a,x hh(KBD_STATE2)
_loop1_resume: PLX s ; [A]
PLA s ; []
DEY i
BPL r :loop1
SEC i
ROR zp 0
DEX i
BPL r :loop0
BRA r :loop
;;; kbd char
kbd_char: CMP # 30
BEQ r :_backspace
JSR a :lcd_w_rs1
RTS s
;; CL
;; 0001SRxx
_backspace: LDA a %00010000
JSR a :lcd_w_rs0
RTS s
;;; end kbd_char

277
keyboard3.asm.in Normal file
View File

@ -0,0 +1,277 @@
include(`common.m4')
define(KBD_STATE, 40) ;;; 0x40 - 0x7f
define(KBD_STATE2, 80) ;;; 0x80 - 0xbf
define(KBD_COM_MASK, 3f)
define(KBD_GLCD_Y, 3e)
define(KBD_GLCD_X, 3d)
define(KBD_GLCD_C, 3c)
define(KBD_LAYER, 3b)
BRA r :reset ; RESB
NOP i ; IRQ
reset: LDX # ff
TXS i
JSR a :gfont_init
;; gfont_init already set Y and X to 55 and 7
LDA # ^55
STA zp KBD_GLCD_Y
JSR a :_kbd_char_c2_cursor
LDA # ^7
STA zp KBD_GLCD_X
STZ zp KBD_GLCD_C
STZ zp KBD_LAYER
LDA # %11111111
STA a VIA1_PORTA
LDA # %00000000
STA a VIA1_DDRB
LDA # %11111111
STA a VIA1_DDRA
;; layer indication
LDA # %00000011
STA a VIA2_DDRA
STZ a VIA2_PORTA
LDX # 80
LDA # 0
_state: STA zp,x KBD_STATE
DEX i
BNE r :_state
loop: LDX # 7 ; state
LDA # %01111111
STA zp KBD_COM_MASK
loop0: LDA zp KBD_COM_MASK
STA a VIA1_PORTA
LDY # 4 ; bit
LDA a VIA1_PORTB
loop1: ROR A
PHA s ; [A]
PHP s ; [P,A]
;; { A = (X * 8 + Y)
TXA i
ASL A
ASL A
ASL A
STY zp 1
ORA zp 1
;; }
PLP s ; [A]
PHX s ; [X,A]
TAX i
BCS r :_kbd_up
;;; begin down
_kbd_down: LDA zp,x KBD_STATE
CMP # 4
BNE r :_kbd_state_inc
;; if (KBD_STATE[X] == 4) {
LDA a,x KBD_STATE2
BNE r :_loop1_resume
;; if (KBD_STATE2[X] == 0) {
INC a,x KBD_STATE2
LDA zp KBD_LAYER
ASL A
ASL A
ASL A
ASL A
ASL A
ASL A ; << 6
STX zp 1
ORA zp 1
TAX i
LDA a,x :_bin_res/keymap_start
PHY s ; [Y,X,A]
JSR a :kbd_char_draw
PLY s ; [X,A]
BRA r :_loop1_resume
;; }
;; }
_kbd_state_inc: INC zp,x KBD_STATE
BRA r :_loop1_resume
;;; end down
;;; begin up
_kbd_up: LDA zp,x KBD_STATE
BEQ r :_kbd_up_state2
_kbd_state_dec: DEC zp,x KBD_STATE
BRA r :_loop1_resume
_kbd_up_state2: STZ a,x KBD_STATE2
;;; end up
_loop1_resume: PLX s ; [A]
PLA s ; []
DEY i
BPL r :loop1
SEC i
ROR zp KBD_COM_MASK
DEX i
BPL r :loop0
BRA r :loop
;;; end main loop
_kbd_char_nonprint: SEC i
SBC # 80
CMP # 4 ; L0 through L3
BCC r :_kbd_set_layer
BEQ r :_kbd_backspace ; BACKSPACE
BCS r :_kbd_enter ; ENTER or ???
_kbd_jump_return: RTS s
_kbd_set_layer: AND # %11
STA zp KBD_LAYER
STA a VIA2_PORTA
RTS s
_kbd_enter: LDA # ^32
LDY zp KBD_GLCD_C
BNE r :_kbd_enter_c1
;; fallthrough to _kbd_backspace_c2
_kbd_enter_c2: JSR a :gfont_draw_c2
JMP a :_kbd_end_of_line ; too long for BRA
_kbd_enter_c1: JSR a :gfont_draw_c1
JMP a :_kbd_end_of_line ; too long for BRA
_kbd_backspace: LDA # ^32
LDY zp KBD_GLCD_C
BNE r :_kbd_backspace_c1
;; fallthrough to _kbd_backspace_c2
_kbd_backspace_c2: JSR a :gfont_draw_c2
LDA zp KBD_GLCD_Y
CLC i
ADC # 5
CMP # ^56
BMI r :_kbd_char_c2_cursor
;; transitioning to c1
LDY # 1
STY zp KBD_GLCD_C
;; beginning of line, increment X page
LDA zp KBD_GLCD_X
INC A
AND # %111
STA zp KBD_GLCD_X
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c2
LDA zp KBD_GLCD_X
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c1
LDA # ^4
BRA r :_kbd_char_c1_cursor
_kbd_backspace_c1: JSR a :gfont_draw_c1
LDA zp KBD_GLCD_Y
CLC i
ADC # 5
CMP # ^60
BMI r :_kbd_char_c1_cursor
;; transitioning to c2
LDY # 0
STY zp KBD_GLCD_C
LDA # ^0
BRA r :_kbd_char_c2_cursor
;;; begin char_draw (A)
kbd_char_draw: CMP # 80
BCS r :_kbd_char_nonprint
LDY zp KBD_GLCD_C
BNE r :_kbd_char_c1
;; fallthrough to _kbd_char_c2
;;; c2: [55,0]
;; if (KBD_GLCD_C == 0) {
_kbd_char_c2: JSR a :gfont_draw_c2
LDA zp KBD_GLCD_Y
SEC i
SBC # 5
BPL r :_kbd_char_c2_cursor
;; transitioning to c1
LDY # 1
STY zp KBD_GLCD_C
LDA # ^59
BRA r :_kbd_char_c1_cursor
_kbd_char_c2_cursor: STA zp KBD_GLCD_Y
ORA # %01000000 ; Y address
JSR a :glcd_w_rs0_c2
LDA # ^95
JSR a :gfont_draw_c2
LDA zp KBD_GLCD_Y
ORA # %01000000 ; Y address
JSR a :glcd_w_rs0_c2
RTS s
;; }
;;; c2: [59,4]
;; if (KBD_GLCD_C == 1) {
_kbd_char_c1: JSR a :gfont_draw_c1
LDA zp KBD_GLCD_Y
SEC i
SBC # 5
CMP # 4
BPL r :_kbd_char_c1_cursor
;; transitioning to c2
_kbd_end_of_line: LDY # 0
STY zp KBD_GLCD_C
;; end of line, decrement X page
LDA zp KBD_GLCD_X
DEC A
AND # %111
STA zp KBD_GLCD_X
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c2
LDA zp KBD_GLCD_X
ORA # %10111000 ; X page
JSR a :glcd_w_rs0_c1
LDA # ^55
BRA r :_kbd_char_c2_cursor
_kbd_char_c1_cursor: STA zp KBD_GLCD_Y
ORA # %01000000 ; Y address
JSR a :glcd_w_rs0_c1
LDA # ^95
JSR a :gfont_draw_c1
LDA zp KBD_GLCD_Y
ORA # %01000000 ; Y address
JSR a :glcd_w_rs0_c1
RTS s
;; }
;;; end char_draw

130
lcd.asm Normal file
View File

@ -0,0 +1,130 @@
;; Set pins 0-7 on Port B to Output
LDA # FF
STA a 8002
;; Set pins 0-2 on Port A to Output
LDA # 7
STA a 8003
;; 00111000 set 8-bit mode, 2-line display, 5x8 font
LDA # 38
STA a 8000
LDA # 0
STA a 8001 ; clear RS|RW|E
LDA # 1
STA a 8001 ; set E
LDA # 0
STA a 8001 ; clear RS|RW|E
;; 00001110 display on; cursor on; blink off
LDA # E
STA a 8000
LDA # 0
STA a 8001 ; clear RS|RW|E
LDA # 1
STA a 8001 ; set E
LDA # 0
STA a 8001 ; clear RS|RW|E
;; 00000001 Clear Display:
LDA # 1
STA a 8000
LDA # 0
STA a 8001 ; clear RS|RW|E
LDA # 1
STA a 8001 ; set E
LDA # 0
STA a 8001 ; clear RS|RW|E
;; 00000110 Entry Mode Set: increment and shift cursor; don't shift display
LDA # 6
STA a 8000
LDA # 0
STA a 8001 ; clear RS|RW|E
LDA # 1
STA a 8001 ; set E
LDA # 0
STA a 8001 ; clear RS|RW|E
;; l
LDA # 6C
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; o
LDA # 6F
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; v
LDA # 76
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; e
LDA # 65
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; ' '
LDA # 20
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; a
LDA # 61
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; n
LDA # 6E
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
;; a
LDA # 61
STA a 8000
LDA # 2
STA a 8001 ; set RS; clear RW|E
LDA # 3
STA a 8001 ; set RS|E
LDA # 2
STA a 8001 ; set RS; clear RW|E
forever: JMP a :forever

5
mul5.asm Normal file
View File

@ -0,0 +1,5 @@
LDA # d15
STA zp 0
ASL A
ASL A
ADC zp 0

198
oled.asm.in Normal file
View File

@ -0,0 +1,198 @@
; -*-asm-*-
include(`common.m4')
BRA r :reset ; RESB
NOP i ; IRQ
;; reset stack
reset: LDX # ff
TXS i
;; Set pins 0-4 on Port A to Output
LDA # %00011111
STA a DDRA
;; Display ON/OFF:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 0 1 1 1 1 1 D
;;
LDA # %00111111
JSR a :lcd-w-rs0-c2
LDA # %00111111
JSR a :lcd-w-rs0-c1
JSR a :reset-oled
LDA # 0 ; face address
STA zp 0
LDX # 1 ; X page
_face_page: LDA # %01000000 ; Y address
JSR a :lcd-w-rs0-c2
TXA i
ORA # %10111000 ; X page
JSR a :lcd-w-rs0-c2
TXA i
ORA # %10111000 ; X page
JSR a :lcd-w-rs0-c1
PHX s
LDY # 17 ; Y address
LDX zp 0
_face_fill: LDA a,x :_bin_face_start
JSR a :lcd-w-rs1-c2
TYA i
CLC i
ADC # 28
ORA # %01000000 ; Y address
JSR a :lcd-w-rs0-c1
LDA a,x :_bin_face_start
JSR a :lcd-w-rs1-c1
INX i
STX zp 0
DEY i
CPY # 0
BPL r :_face_fill ; BGE 0
PLX s
INX i
CPX # 7
BNE r :_face_page
stop: JMP a :stop
reset-oled: LDY # 00
LDA # %01000000 ; Y address
JSR a :lcd-w-rs0-c2
_next_page: TYA i
ORA # %10111000 ; X page
JSR a :lcd-w-rs0-c2
TYA i
ORA # %10111000 ; X page
JSR a :lcd-w-rs0-c1
LDX # 40
_fill_page: LDA # 00
JSR a :lcd-w-rs1-c2
TXA i
SEC i
SBC # 1
ORA # %01000000 ; Y address
JSR a :lcd-w-rs0-c1
LDA # 00
JSR a :lcd-w-rs1-c1
DEX i
BNE r :_fill_page
INY i
CPY # 8
BNE r :_next_page
RTS s
;; write "instruction"
lcd-w-rs0-c2: JSR a :lcd-wait-c2
STA a PORTB
LDA # hh(G_C2)
STA a PORTA
LDA # hh(G_C2|G_E)
STA a PORTA
LDA # hh(G_C2)
STA a PORTA
RTS s
lcd-w-rs0-c1: JSR a :lcd-wait-c1
STA a PORTB
LDA # hh(G_C1)
STA a PORTA
LDA # hh(G_C1|G_E)
STA a PORTA
LDA # hh(G_C1)
STA a PORTA
RTS s
;; write "data" to lcd
lcd-w-rs1-c2: JSR a :lcd-wait-c2
STA a PORTB
LDA # hh(G_RS|G_C2)
STA a PORTA
LDA # hh(G_RS|G_C2|G_E)
STA a PORTA
LDA # hh(G_RS|G_C2)
STA a PORTA
RTS s
lcd-w-rs1-c1: JSR a :lcd-wait-c1
STA a PORTB
LDA # hh(G_RS|G_C1)
STA a PORTA
LDA # hh(G_RS|G_C1|G_E)
STA a PORTA
LDA # hh(G_RS|G_C1)
STA a PORTA
RTS s
;; wait BF
lcd-wait-c2: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a DDRB
_lcd_wait-c2: LDA # hh(G_RW|G_C2)
STA a PORTA
LDA # hh(G_RW|G_C2|G_E)
STA a PORTA
LDA a PORTB
AND # %10000000
BNE r :_lcd_wait-c2
LDA # hh(G_RW|G_C2)
STA a PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output
STA a DDRB
PLA s
RTS s
;; wait BF
lcd-wait-c1: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a DDRB
_lcd_wait-c1: LDA # hh(G_RW|G_C1)
STA a PORTA
LDA # hh(G_RW|G_C1|G_E)
STA a PORTA
LDA a PORTB
AND # %10000000
BNE r :_lcd_wait-c1
LDA # hh(G_RW|G_C1)
STA a PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output
STA a DDRB
PLA s
RTS s

67
res/keymap.txt Normal file
View File

@ -0,0 +1,67 @@
pb0 pb1 pb2 pb3 pb4
pa3 1 2 3 4 5
pa2 q w e r t
pa1 a s d f g
pa0 z x c v b
pa4 6 7 8 9 0
pa5 y u i o p
pa6 h j k l ;
pa7 n m , . _
pa: 0111 1111
10000 b
01000 v
00100 c
00010 x
00001 z
pa: 1011 1111
10000 g
01000 f
00100 d
00010 s
00001 a
pa: 1101 1111
10000 t
01000 r
00100 e
00010 w
00001 q
pa: 1110 1111
10000 5
01000 4
00100 3
00010 2
00001 1
pa: 1111 0111
10000 0
01000 9
00100 8
00010 7
00001 6
pa: 1111 1011
10000 p
01000 o
00100 i
00010 u
00001 y
pa: 1111 1101
10000 ;
01000 l
00100 k
00010 j
00001 h
pa: 1111 1110
10000 _
01000 .
00100 ,
00010 m
00001 n

95
shift.asm.in Normal file
View File

@ -0,0 +1,95 @@
; -*-asm-*-
include(`common.m4')
BRA r :reset ; RESB
BRA r :irq ; IRQB
irq: PHA s
LDA a %10000000
STA a IFR
PLA s
RTI s
;; reset stack
reset: LDX # ff
TXS i
;; xxxSSSxx
LDA # hh(ACR_SR_OUT_PHI2)
STA a ACR
LDA # %10000000
STA a PORTA
LDA # %10000000
STA a DDRA
LDA # %01111111
STA a IER
LDA # %10000100
STA a IER
;; R T FEN SHD TM RM PM RAM
;; 1 1 1 0 0 0 0 0
LDX # %11100000 ; write configuration
;; IR ST PE L B3 B2 B1 B0
;; 0 0 0 0 0 0 0 1 ; 115200
LDY # %00000001
JSR a :spi16
;; R T FEN SHD TM RM PM RAM
;; 1 1 1 0 0 0 0 0
LDX # %11100000 ; write configuration
;; IR ST PE L B3 B2 B1 B0
;; 0 0 0 0 0 0 0 1 ; 115200
LDY # %00000001
JSR a :spi16
;; R T FEN SHD TM RM PM RAM
;; 1 1 1 0 0 0 0 0
LDX # %01000000 ; read configuration
;; IR ST PE L B3 B2 B1 B0
;; 0 0 0 0 0 0 0 1 ; 115200
LDY # %00000000
JSR a :spi16
;; R T FEN SHD TM RM PM RAM
;; 1 1 1 0 0 0 0 0
LDX # %01000000 ; read configuration
;; IR ST PE L B3 B2 B1 B0
;; 0 0 0 0 0 0 0 1 ; 115200
LDY # %00000000
JSR a :spi16
LDX # %00000000 ; read data
LDY # %00000000
JSR a :spi16
LDX # %10000000 ; write data
LDY # ca
JSR a :spi16
LDX # %10000010 ; write data
LDY # ca
JSR a :spi16
forever: BRA r :forever
spi16: CLI i
LDA # %00000000
STA a PORTA
STX a SR
WAI i
STY a SR
WAI i
LDA # %10000000
STA a PORTA
SEI i
RTS s

74
shift2-old.asm.in Normal file
View File

@ -0,0 +1,74 @@
; -*-asm-*-
include(`common.m4')
BRA r :reset ; RESB
BRA r :irq ; IRQB
irq: PHA s
LDA a %10000000
STA a IFR
PLA s
RTI s
;; reset stack
reset: SEI i
LDX # ff
TXS i
;; xxxSSSxx
LDA # hh(ACR_SR_OUT_PHI2)
STA a ACR
LDA # %10000000
STA a PORTA
;; CS SCLK DO x x x x x
LDA # %11100000
STA a DDRA
;; LDA # %01111111
;; STA a IER
;; LDA # %10000100
;; STA a IER
;; low byte
LDX # %11000000 ; write conf
LDY # %00000001
JSR a :spi16
LDX # %10000000 ; write data
LDY # ca
JSR a :spi16
forever: BRA r :forever
;; CS low
spi16: LDA # %00000000
STA a PORTA
STX zp 1
STY zp 2
LDY # 2
_spi_next: LDX # 8
CLC i
ASL zp,y 0
LDA # %00000000 ; clear DO
BCC r :_spi_z
ORA # %00100000 ; set DO
_spi_z: STA a PORTA
NOP i
ORA # %01000000 ; set SCLK
STA a PORTA
AND # %10111111 ; clear SCLK
STA a PORTA
DEX i
BNE r :_spi_next
DEY i
BNE r :_spi_next
;; CS high
LDA # %10000000
STA a PORTA
RTS s

74
shift2.asm Normal file
View File

@ -0,0 +1,74 @@
; -*-asm-*-
BRA r :reset ; RESB
BRA r :irq ; IRQB
irq: PHA s
LDA a %10000000
STA a 800d
PLA s
RTI s
;; reset stack
reset: SEI i
LDX # ff
TXS i
;; xxxSSSxx
LDA # 18
STA a 800b
LDA # %10000000
STA a 8001
;; CS SCLK DO x x x x x
LDA # %11100000
STA a 8003
;; LDA # %01111111
;; STA a 800e
;; LDA # %10000100
;; STA a 800e
;; low byte
LDX # %11000000 ; write conf
LDY # %00000001
JSR a :spi16
LDX # %10000000 ; write data
LDY # 6c
JSR a :spi16
forever: BRA r :forever
;; CS low
spi16: LDA # %00000000
STA a 8001
STX zp 2
STY zp 1
LDX # 2
_spi_next: LDY # 8
_spi_8: CLC i
ASL zp,x 0
LDA # %00000000 ; clear DO
BCC r :_spi_z
ORA # %00100000 ; set DO
_spi_z: STA a 8001
NOP i
ORA # %01000000 ; set SCLK
STA a 8001
AND # %10111111 ; clear SCLK
STA a 8001
DEY i
BNE r :_spi_8
DEX i
BNE r :_spi_next
;; CS high
LDA # %10000000
STA a 8001
RTS s

79
shift3.asm.in Normal file
View File

@ -0,0 +1,79 @@
; -*-asm-*-
include(`common.m4')
BRA r :reset ; RESB
BRA r :irq ; IRQB
irq: RTI s
;; reset stack
reset: SEI i
LDX # ff
TXS i
;; CS high, SCLK low
LDA # hh(M_CS)
STA a PORTA
LDA # hh(M_DDRA_MASK)
STA a DDRA
LDX # hh(M_CFGH|M_CFGH_FENB)
LDY # hh(M_CFGL_BAUD_115200)
JSR a :spi16
;; read data
tryagain: LDX # hh(M_R_DATA)
LDY # hh(M_R_DATA)
JSR a :spi16
LDA zp 4
BPL r :tryagain ; BPL = if the leftmost bit is 0, go here
;; write data
LDX # hh(M_W_DATAH)
LDY zp 3
JSR a :spi16
BRA r :tryagain
;; CS low, SCLK low
spi16: LDA # %00000000
STA a PORTA
STX zp 2
STY zp 1
;; SPI output
STZ zp 4
STZ zp 3
LDX # 2
_spi_next: LDY # 8
STY zp 0
_spi_8: ASL zp,x 0
LDA # 0 ; preclear MOSI
BCC r :_spi_zout
ORA # hh(M_DIN) ; set MOSI
_spi_zout: STA a PORTA
ORA # hh(M_SCLK) ; set SCLK
STA a PORTA
LDY a PORTA ; DOUT on bit 7
CLC i ; preclear MISO
BPL r :_spi_zin ;
SEC i ; set MISO
_spi_zin: ROL zp,x 2
AND # hh(~M_SCLK & 0xff) ; clear SCLK
STA a PORTA
DEC zp 0
BNE r :_spi_8
DEX i
BNE r :_spi_next
;; CS high, SCLK low
LDA # hh(M_CS)
STA a PORTA
RTS s

5
test.asm Normal file
View File

@ -0,0 +1,5 @@
LDX # ff
LDX # 00
LDX # 7f
LDX # 80
LDX # fe

View File

@ -17,11 +17,15 @@ irq: PHA s
;;; end irq
reset: LDX # ff
reset: SEI i
LDX # ff
TXS i
LDA # %10000000 ;; Set pins 0-7 on Port B to Output
STA a DDRA
LDA # %00000001 ;; Set pins 0-7 on Port B to Output
STA a DDRB
LDA # %00000001
STA a PORTB
JSR a :continuous
@ -30,9 +34,9 @@ count: LDA # 25
loop: LDA zp ticks_
BPL r :loop
LDA # %10000000
EOR a PORTA
STA a PORTA
LDA # %00000001
EOR a PORTB
STA a PORTB
BRA r :count

Binary file not shown.

20
tools/Makefile Normal file
View File

@ -0,0 +1,20 @@
CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter -pedantic -ggdb
CFLAGS += $(shell pkg-config --cflags freetype2)
#CFLAGS += $(shell pkg-config --cflags libutf8proc)
LDFLAGS = $(shell pkg-config --libs freetype2)
#LDFLAGS = $(shell pkg-config --libs libutf8proc)
all: otb-convert
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%: %.o
$(CC) $< -o $@
otb-convert: %.o
$(CC) $(LDFLAGS) $< -o $@
.SUFFIXES:

79
tools/keymap.py Normal file
View File

@ -0,0 +1,79 @@
L0 = 128
L1 = 129
L2 = 130
L3 = 131
BKSPC = 132
ENTER = 133
keymap = [
[
[ "q", "w", "f", "p", "b", "j", "l", "u", "y", ";"],
[ "a", "r", "s", "t", "g", "k", "n", "e", "i", "o"],
[ 0, "x", "c", "d", "v", "m", "h", "z", 0, 0],
[ L0, L1, L2, L3, " ",BKSPC, 0, 0, 0,ENTER],
],
[
[ "Q", "W", "F", "P", "B", "J", "L", "U", "Y", ":"],
[ "A", "R", "S", "T", "G", "K", "N", "E", "I", "O"],
[ 0, "X", "C", "D", "V", "M", "H", "Z", 0, 0],
[ L0, L1, L2, L3, " ",BKSPC, 0, 0, 0,ENTER],
],
[
[ "'", "~", "=", "{", "@", "%", "}", "_", "*", "\""],
[ ",", "\\", "+", "(", "<", ">", ")", "-", "/", "."],
[ "`", "?", "#", "[", "|", "&", "]", "$", "!", "^"],
[ L0, L1, L2, L3, " ",BKSPC, 0, 0, 0,ENTER],
],
[
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ L0, L1, L2, L3, " ",BKSPC, 0, 0, 0,ENTER],
],
]
# qwerty_keymap = [
# ["z", "x", "c", "v", "b"],
# ["a", "s", "d", "f", "g"],
# ["q", "w", "e", "r", "t"],
# ["1", "2", "3", "4", "5"],
# ["6", "7", "8", "9", "0"],
# ["y", "u", "i", "o", "p"],
# ["h", "j", "k", "l", ";"],
# ["n", "m", ",", ".", " "],
# ]
def visual_to_scancode(table):
assert len(table) == 4
assert all(len(row) == 10 for row in table)
yield table[3][0:5]
yield table[2][0:5]
yield table[1][0:5]
yield table[0][0:5]
yield table[0][5:10]
yield table[1][5:10]
yield table[2][5:10]
yield table[3][5:10]
def keymap_table():
for layer in keymap:
for state in visual_to_scancode(layer):
for key in reversed(state):
if type(key) is str:
code = ord(key)
assert code < 128
yield code
elif type(key) is int:
yield key
else:
raise TypeError(key)
for _ in range(8 - len(state)):
yield ord('?')
import sys
with open(sys.argv[1], 'wb') as f:
f.write(bytes(keymap_table()))

102
tools/otb-convert.c Normal file
View File

@ -0,0 +1,102 @@
#include <stdio.h>
#include <assert.h>
#include <ft2build.h>
#include FT_FREETYPE_H
int load_char(FT_Face face, FT_ULong char_code, unsigned char * buf)
{
FT_Error error;
FT_UInt glyph_index = FT_Get_Char_Index(face, char_code);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error) {
printf("FT_Load_Glyph %s\n", FT_Error_String(error));
return 0;
}
assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP);
assert(face->glyph->bitmap.num_grays == 2);
assert(face->glyph->bitmap.pitch == 1);
if (face->glyph->bitmap.width != 5)
fprintf(stderr, "%ld\n", char_code);
assert(face->glyph->bitmap.width == 5);
assert(face->glyph->bitmap.rows == 8);
//fprintf(stderr, "%ld %d\n", char_code, face->glyph->bitmap.rows);
for (int x = 0; x < 8; x++) buf[x] = 0;
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
char row = face->glyph->bitmap.buffer[y];
for (int x = 0; x < 5; x++) {
int bit = (row >> (7 - x)) & 1;
buf[x] |= (bit << (7 - y));
}
}
/*
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
char row = face->glyph->bitmap.buffer[y];
unsigned char row_out = 0;
for (int x = 0; x < 8; x++) {
int bit;
if (x < (int)face->glyph->bitmap.width) {
bit = (row >> (7 - x)) & 1;
} else {
bit = 0;
}
//fprintf(stderr, bit ? "█" : " ");
row_out |= (bit << x);
}
//fprintf(stderr, "\n");
buf[y] = row_out;
}
*/
//return face->glyph->bitmap.rows;
return 8;
}
int main(int argc, char *argv[])
{
FT_Library library;
FT_Face face;
FT_Error error;
if (argc < 2) {
fprintf(stderr, "argc");
return -1;
}
error = FT_Init_FreeType(&library);
if (error) {
fprintf(stderr, "FT_Init_FreeType\n");
return -1;
}
error = FT_New_Face(library, argv[1], 0, &face);
if (error) {
fprintf(stderr, "FT_New_Face\n");
return -1;
}
error = FT_Select_Size(face, 0);
if (error) {
fprintf(stderr, "FT_Select_Size: %s %d\n", FT_Error_String(error), error);
return -1;
}
#define CHARS (128)
unsigned char buf[CHARS * face->available_sizes[0].height];
int ret;
unsigned char * bufi = buf;
for (unsigned long c = 0; c < CHARS; c++) {
ret = load_char(face, c, bufi);
if (ret == 0)
return -1;
bufi += ret;
}
fwrite(buf, (sizeof (buf[0])), (sizeof (buf)) / (sizeof (buf[0])), stdout);
}

196
tools/term.c Normal file
View File

@ -0,0 +1,196 @@
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
static int fd = -1;
void int_handler(int dummy) {
write(STDERR_FILENO, "sigint\n", 7);
if (fd != -1)
close(fd);
exit(1);
}
void
set_attrs(int fd)
{
struct termios t;
int attr = tcgetattr(fd, &t);
assert (attr != -1);
cfsetospeed(&t, B115200);
cfsetispeed(&t, B115200);
t.c_cflag = (t.c_cflag & ~CSIZE) | CS8; // 8-bit chars
t.c_lflag = 0; // no signaling chars, no echo, no canonical processing
t.c_oflag = 0; // no remapping, no delays
t.c_cc[VMIN] = 1; // read doesn't block
t.c_cc[VTIME] = 0; // no timeout
// convert break to null byte, no CR to NL translation,
// no NL to CR translation, don't mark parity errors or breaks
// no input parity check, don't strip high bit off,
// no XON/XOFF software flow control
t.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
INLCR | PARMRK | INPCK | ISTRIP | IXOFF | IXON | IXANY);
t.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, enable reading
t.c_cflag &= ~(PARENB | PARODD); // shut off parity
t.c_cflag &= ~CSTOPB; // one stop bit
t.c_cflag |= CRTSCTS; // enable CTS/RTS
int ret = tcsetattr(fd, TCSANOW, &t);
assert (ret != -1);
}
ssize_t
write_block(int fd, char * buf, size_t len)
{
ssize_t wret, rret;
size_t out_len = 0;
char in_buf[len];
memset(in_buf, 0xea, len);
#define BLOCK_SIZE 8
for (unsigned int i = 0; i < (len / BLOCK_SIZE); i++) {
wret = write(fd, &buf[BLOCK_SIZE * i], BLOCK_SIZE);
assert (wret == BLOCK_SIZE);
int tret = tcdrain(fd);
assert (tret != -1);
//printf("%x\n", out_buf[BLOCK_SIZE * i] & 0xff, rret);
size_t block = 0;
while (block != BLOCK_SIZE) {
rret = read(fd, &in_buf[(BLOCK_SIZE * i) + block], BLOCK_SIZE - block);
assert (rret != -1);
block += rret;
}
//printf("%x %x %ld\n", out_buf[BLOCK_SIZE * i] & 0xff, in_buf[BLOCK_SIZE * i] & 0xff, rret);
assert (block == BLOCK_SIZE);
out_len += block;
write(STDERR_FILENO, ".", 1);
fsync(STDERR_FILENO);
}
size_t rem = len % BLOCK_SIZE;
if (rem) {
wret = write(fd, &buf[len - rem], rem);
assert (wret != -1);
assert ((size_t)wret == rem);
int tret = tcdrain(fd);
assert (tret != -1);
size_t block = 0;
while (block != rem) {
rret = read(fd, &in_buf[len - rem + block], rem - block);
assert (rret != -1);
block += rret;
}
//printf("%x %x %ld\n", buf[BLOCK_SIZE * i] & 0xff, in_buf[BLOCK_SIZE * i] & 0xff, rret);
assert (block == rem);
out_len += block;
write(STDERR_FILENO, ".", 1);
fsync(STDERR_FILENO);
}
write(STDERR_FILENO, "\n", 1);
//int cmp = memcmp(buf, in_buf, len);
for (unsigned int bx = 0; bx < len; bx++) {
if (buf[bx] != in_buf[bx]) {
fprintf(stderr, "buf[%d] != in_buf[%d]\n", bx, bx);
fprintf(stderr, "%02x != %02x\n", buf[bx], in_buf[bx]);
}
}
return out_len;
}
void
write_header(int fd, size_t len, size_t addr)
{
assert (addr <= 0xffff);
assert (len <= 255);
fprintf(stderr, "len %ld addr %lx\n", len, addr & 0xffff);
char out_buf[3] = {
len & 0xff,
(addr >> 0) & 0xff,
(addr >> 8) & 0xff,
};
ssize_t wret = write(fd, out_buf, 3);
assert (wret != -1);
size_t hdr_len = len == 0 ? 2 : 3;
char in_buf[3];
size_t offset = 0;
ssize_t rret;
while (offset != hdr_len) {
rret = read(fd, &in_buf[offset], hdr_len - offset);
assert (rret != -1);
offset += rret;
}
assert (offset == hdr_len);
int cmp = memcmp(in_buf, "LDR", hdr_len);
assert (cmp == 0);
}
static char read_buf[0x8000];
int main(int argc, char *argv[])
{
signal(SIGINT, int_handler);
int tfd = open("/dev/ttyUSB0", O_RDWR | O_SYNC | O_NOCTTY);
assert (tfd != -1);
set_attrs(tfd);
int tret = tcflush(tfd, TCIOFLUSH);
assert (tret != -1);
assert (argc > 1);
fprintf(stderr, "%s\n", argv[1]);
int ffd = open(argv[1], O_RDONLY);
ssize_t rret = read(ffd, read_buf, 0x8000);
assert (rret != -1 && rret > 0 && rret <= 0x8000);
size_t offset = 0;
size_t base_address = 0x200;
while (rret - offset > 0) {
size_t block_len = rret - offset >= 255 ? 255 : rret - offset;
write_header(tfd, block_len, base_address + offset);
ssize_t block_ret = write_block(tfd, &read_buf[offset], block_len);
assert (block_ret != -1);
assert ((size_t)block_ret == block_len);
offset += block_ret;
}
fprintf(stderr, "jump %lx\n", base_address & 0xffff);
write_header(tfd, 0, base_address);
close(fd);
}
// stty -F /dev/ttyUSB0 115200 -icrnl -imaxbel -opost -onlcr -isig -echo -icanon -ixon

View File

@ -42,7 +42,7 @@ reset: LDX # ff
;; Set DDRAM Address:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 1 A6 A5 A4 A3 A2 A1 A0
LDA # hh(L_DDRAM|0)
LDA # hh(C_DDRAM|0)
JSR a :lcd-w-rs0
;; Write Data:
@ -60,7 +60,7 @@ reset: LDX # ff
;; Set CGRAM Address:
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0
LDA # hh(L_CGRAM|0)
LDA # hh(C_CGRAM|0)
JSR a :lcd-w-rs0
;; data is at e000
@ -97,7 +97,7 @@ loop: LDA (zp),y 00
;; Set CGRAM Address
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0
loop2: LDA # hh(L_CGRAM|9)
loop2: LDA # hh(C_CGRAM|9)
JSR a :lcd-w-rs0
;; Write Data to CGRAM
@ -109,7 +109,7 @@ loop2: LDA # hh(L_CGRAM|9)
;; Set CGRAM Address
;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0
LDA # hh(L_CGRAM|9)
LDA # hh(C_CGRAM|9)
JSR a :lcd-w-rs0
;; Write Data to CGRAM
@ -129,7 +129,7 @@ lcd-w-rs0: JSR a :lcd-wait
STA a PORTB
LDA # 0
STA a PORTA
LDA # hh(L_E)
LDA # hh(C_E)
STA a PORTA
LDA # 0
STA a PORTA
@ -139,11 +139,11 @@ lcd-w-rs0: JSR a :lcd-wait
lcd-w-rs1: JSR a :lcd-wait
STA a PORTB
LDA # hh(L_RS)
LDA # hh(C_RS)
STA a PORTA
LDA # hh(L_RS|L_E)
LDA # hh(C_RS|C_E)
STA a PORTA
LDA # hh(L_RS)
LDA # hh(C_RS)
STA a PORTA
RTS s
@ -153,15 +153,15 @@ lcd-wait: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a DDRB
_lcd_wait: LDA # hh(L_RW)
_lcd_wait: LDA # hh(C_RW)
STA a PORTA
LDA # hh(L_E|L_RW)
LDA # hh(C_E|C_RW)
STA a PORTA
LDA a PORTB
AND # %10000000
BNE r :_lcd_wait
LDA # hh(L_RW)
LDA # hh(C_RW)
STA a PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output