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 *.bin
*.rom *.rom
*.asm .#*
tools/otb-convert
tools/term

View File

@ -14,11 +14,29 @@ all:
%.prog: %.rom %.prog: %.rom
minipro -p AT28C256 -w $< minipro -p AT28C256 -w $<
%.term: %.bin
./tools/term $<
clean: clean:
rm -f *.bin *.rom 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 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: .SUFFIXES:
.INTERMEDIATE: .INTERMEDIATE:
.PRECIOUS: %.bin %.rom %.asm .PRECIOUS: %.bin %.rom %.asm

View File

@ -11,4 +11,4 @@ loop: LDA # 1
STA a 8000 STA a 8000
;; repeat ;; 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 changecom(`@')dnl
dnl dnl
define(PORTB, 8000)dnl define(VIA0_PORTB, 8000)dnl
define(PORTA, 8001)dnl define(VIA0_PORTA, 8001)dnl
define(DDRB, 8002)dnl define(VIA0_DDRB, 8002)dnl
define(DDRA, 8003)dnl define(VIA0_DDRA, 8003)dnl
define(T1CL, 8004)dnl define(VIA0_T1CL, 8004)dnl
define(T1CH, 8005)dnl define(VIA0_T1CH, 8005)dnl
define(T1LL, 8006)dnl define(VIA0_T1LL, 8006)dnl
define(T1LH, 8007)dnl define(VIA0_T1LH, 8007)dnl
define(T2CL, 8008)dnl define(VIA0_T2CL, 8008)dnl
define(T2CH, 8009)dnl define(VIA0_T2CH, 8009)dnl
define(SR, 800a)dnl define(VIA0_SR, 800a)dnl
define(ACR, 800b)dnl define(VIA0_ACR, 800b)dnl
define(PCR, 800c)dnl define(VIA0_PCR, 800c)dnl
define(IFR, 800d)dnl define(VIA0_IFR, 800d)dnl
define(IER, 800e)dnl define(VIA0_IER, 800e)dnl
dnl dnl
define(`L_CGRAM', `0b01000000')dnl define(VIA1_PORTB, 8800)dnl
define(`L_DDRAM', `0b10000000')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 dnl
define(`L_E', `0b001')dnl define(VIA2_PORTB, 9000)dnl
define(`L_RS', `0b010')dnl define(VIA2_PORTA, 9001)dnl
define(`L_RW', `0b100')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 dnl
define(`hh', `eval($1, 16)')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 ;;; end irq
reset: LDX # ff reset: SEI i
LDX # ff
TXS i TXS i
LDA # %10000000 ;; Set pins 0-7 on Port B to Output LDA # %00000001 ;; Set pins 0-7 on Port B to Output
STA a DDRA STA a DDRB
LDA # %00000001
STA a PORTB
JSR a :continuous JSR a :continuous
@ -30,9 +34,9 @@ count: LDA # 25
loop: LDA zp ticks_ loop: LDA zp ticks_
BPL r :loop BPL r :loop
LDA # %10000000 LDA # %00000001
EOR a PORTA EOR a PORTB
STA a PORTA STA a PORTB
BRA r :count 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: ;; Set DDRAM Address:
;; D7 D6 D5 D4 D3 D2 D1 D0 ;; D7 D6 D5 D4 D3 D2 D1 D0
;; 1 A6 A5 A4 A3 A2 A1 A0 ;; 1 A6 A5 A4 A3 A2 A1 A0
LDA # hh(L_DDRAM|0) LDA # hh(C_DDRAM|0)
JSR a :lcd-w-rs0 JSR a :lcd-w-rs0
;; Write Data: ;; Write Data:
@ -60,7 +60,7 @@ reset: LDX # ff
;; Set CGRAM Address: ;; Set CGRAM Address:
;; D7 D6 D5 D4 D3 D2 D1 D0 ;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0 ;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0
LDA # hh(L_CGRAM|0) LDA # hh(C_CGRAM|0)
JSR a :lcd-w-rs0 JSR a :lcd-w-rs0
;; data is at e000 ;; data is at e000
@ -97,7 +97,7 @@ loop: LDA (zp),y 00
;; Set CGRAM Address ;; Set CGRAM Address
;; D7 D6 D5 D4 D3 D2 D1 D0 ;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0 ;; 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 JSR a :lcd-w-rs0
;; Write Data to CGRAM ;; Write Data to CGRAM
@ -109,7 +109,7 @@ loop2: LDA # hh(L_CGRAM|9)
;; Set CGRAM Address ;; Set CGRAM Address
;; D7 D6 D5 D4 D3 D2 D1 D0 ;; D7 D6 D5 D4 D3 D2 D1 D0
;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0 ;; 0 1 AC5 AC4 AC3 AC2 AC1 AC0
LDA # hh(L_CGRAM|9) LDA # hh(C_CGRAM|9)
JSR a :lcd-w-rs0 JSR a :lcd-w-rs0
;; Write Data to CGRAM ;; Write Data to CGRAM
@ -129,7 +129,7 @@ lcd-w-rs0: JSR a :lcd-wait
STA a PORTB STA a PORTB
LDA # 0 LDA # 0
STA a PORTA STA a PORTA
LDA # hh(L_E) LDA # hh(C_E)
STA a PORTA STA a PORTA
LDA # 0 LDA # 0
STA a PORTA STA a PORTA
@ -139,11 +139,11 @@ lcd-w-rs0: JSR a :lcd-wait
lcd-w-rs1: JSR a :lcd-wait lcd-w-rs1: JSR a :lcd-wait
STA a PORTB STA a PORTB
LDA # hh(L_RS) LDA # hh(C_RS)
STA a PORTA STA a PORTA
LDA # hh(L_RS|L_E) LDA # hh(C_RS|C_E)
STA a PORTA STA a PORTA
LDA # hh(L_RS) LDA # hh(C_RS)
STA a PORTA STA a PORTA
RTS s RTS s
@ -153,15 +153,15 @@ lcd-wait: PHA s
LDA # %00000000 ;; Set pins 0-7 on Port B to Input LDA # %00000000 ;; Set pins 0-7 on Port B to Input
STA a DDRB STA a DDRB
_lcd_wait: LDA # hh(L_RW) _lcd_wait: LDA # hh(C_RW)
STA a PORTA STA a PORTA
LDA # hh(L_E|L_RW) LDA # hh(C_E|C_RW)
STA a PORTA STA a PORTA
LDA a PORTB LDA a PORTB
AND # %10000000 AND # %10000000
BNE r :_lcd_wait BNE r :_lcd_wait
LDA # hh(L_RW) LDA # hh(C_RW)
STA a PORTA STA a PORTA
LDA # %11111111 ;; Set pins 0-7 on Port B to Output LDA # %11111111 ;; Set pins 0-7 on Port B to Output