Compare commits

...

7 Commits

Author SHA1 Message Date
matthias@rpi
55d0926fe4 add spi 2023-10-30 22:17:19 +01:00
matthias@rpi
5ec8858180 use keypad buffer read 2023-10-30 22:16:49 +01:00
matthias@rpi
44b73b30c3 add debug 2023-10-30 22:15:40 +01:00
matthias@rpi
3fcf8e45c6 add RAM 2023-10-30 22:15:09 +01:00
matthias@rpi
83009b11b4 add read 2023-10-30 22:14:33 +01:00
matthias@rpi
bb88981d80 fix addressing mode 2023-10-30 22:14:08 +01:00
matthias@rpi
f3a51dc764 moved buffer to separate module 2023-10-30 22:11:24 +01:00
8 changed files with 291 additions and 134 deletions

View File

@ -6,7 +6,7 @@ SRC_DIRS = programs system
# VASM = ~/6502/vasm6502 # VASM = ~/6502/vasm6502
ASM = ca65 ASM = ca65
ASMFLAGS = --cpu 65C02 $(foreach srcdir, $(SRC_DIRS), -I $(srcdir)) ASMFLAGS = -g --cpu 65C02 $(foreach srcdir, $(SRC_DIRS), -I $(srcdir))
ASMDEPFLAGS = --create-dep .dependencies ASMDEPFLAGS = --create-dep .dependencies
LD = ld65 LD = ld65

View File

@ -1,7 +1,9 @@
MEMORY { MEMORY {
ROM: start = $8000, size = $8000, file = %O, fill = yes; ROM: start = $8000, size = $8000, type = ro, file = %O, fill = yes;
RAM: start = $0000, size = $5fff, type = rw, file = "", fill = yes;
} }
SEGMENTS { SEGMENTS {
RAM: load = RAM, type = bss;
CODE: load = ROM, type = ro; CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro; RODATA: load = ROM, type = ro;
RESET_VECTOR: load = ROM, type = ro, start = $FFFA; RESET_VECTOR: load = ROM, type = ro, start = $FFFA;

148
main.s65
View File

@ -1,6 +1,26 @@
.segment "CODE" .segment "CODE"
.include "system/system.h65" .include "system/system.h65"
.macro DEBUG_LED_OFF nr
lda IO1 + IO_RA
.if nr = 0
and #%11111110
.else
and #%11111101
.endif
sta IO1 + IO_RA
.endmacro
.macro DEBUG_LED_ON nr
lda IO1 + IO_RA
.if nr = 0
ora #%00000001
.else
ora #%00000010
.endif
sta IO1 + IO_RA
.endmacro
;******************************************************************************** ;********************************************************************************
; Modules ; Modules
;******************************************************************************** ;********************************************************************************
@ -9,13 +29,17 @@
LCD_IO = IO1 LCD_IO = IO1
.include "lcd.s65" .include "lcd.s65"
; Keypad Reading ; Keypad Reading
KP_IO = IO1 KP_IO = IO2
.include "keypad.s65" .include "keypad.s65"
; SPI
SPI_IO = IO1
.include "system/spi.s65"
; Printer ; Printer
.include "printer.s65" .include "printer.s65"
; Digital Humidity and Temerature Sensor ; Digital Humidity and Temerature Sensor
; .include "dht.s65" ; .include "dht.s65"
;******************************************************************************** ;********************************************************************************
; Interrupts ; Interrupts
;******************************************************************************** ;********************************************************************************
@ -24,51 +48,52 @@ nmi:
jsr _lcd_char jsr _lcd_char
rti rti
irq: irq:
; lda IFR2 todo: verify that the line below does the same thing ; read IRFs, while bit 7 ist set handle interrupts
; Print str_irq
@irq_io1:
; todo use a reserved address instead of 0
lda IO1+IO_IFR
sta 0
bbr7 0,@irq_io2
bbs2 0,@irq_spi_p ; check SR
@irq_io2:
lda IO2+IO_IFR lda IO2+IO_IFR
sta 0 sta 0
; todo: decide wether to read keypad or dht bbr7 0,@irq_return
ora #%10100000 bbs4 0,@irq_keypad ; check CB1
; jsr lcd_char ;TODO: Remove ; this should never be reached
jsr kp_read Print str_irq_unknown
rti ; force reset interrupt flags
; bbs1 0,irq_keypad lda #$ff
lda #'-' sta IO1 + IO_IFR
jsr _lcd_char sta IO2 + IO_IFR
; bbs4 0,irq_dht bra @irq_return
; bbs6 0,irq_dht @irq_keypad:
rti jsr kp_read_on_irq
irq_keypad: bra irq
jsr kp_read @irq_spi_p:
rti jsr spi_p_read
irq_dht: bra irq
@irq_dht:
lda IO1 + IO_T1CL ;T1L2 ; clear interrupt flag lda IO1 + IO_T1CL ;T1L2 ; clear interrupt flag
; jsr dht_irq bra irq
@irq_return:
rti rti
;******************************************************************************** ;********************************************************************************
; Reset sequence ; Reset sequence
;******************************************************************************** ;********************************************************************************
reset: reset:
lda #%11111111 jsr spi_p_init
sta IO1 + IO_DDRA
.macro SET_DEBUG_LED_OFF
lda #%00000000
sta IO1 + IO_RANH
.endmacro
.macro SET_DEBUG_LED_ON
lda #%11111111
sta IO1 + IO_RANH
.endmacro
; SET_DEBUG_LED_OFF
jsr lcd_init jsr lcd_init
; .repeat 1000
; nop
; .endrepeat
; SET_DEBUG_LED_ON
jsr kp_init jsr kp_init
; SET_DEBUG_LED_OFF
lda #$ff
sta IO1 + IO_DDRA
DEBUG_LED_ON 0
DEBUG_LED_ON 1
; ; INIT DHT ; ; INIT DHT
; lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2 ; lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2
@ -86,21 +111,27 @@ reset:
.proc return_home .proc return_home
Print message_menu Print message_menu
; @return_home:
; lda menu,x
; beq @return_home_done
; sta TO_PRINT,x
; jsr _lcd_char
; inx
; bra @return_home
; @return_home_done:
; jsr lcd_print_clear
.endproc .endproc
.proc home .proc home
; SET_DEBUG_LED_ON .macro wait
jsr kb_read wait:
stz 1
stz 2
.repeat 2
nop
.endrepeat
inc 1
bne wait
inc 2
bne wait
.endmacro
; jsr rb_keypad_read
lda KB_LAST
beq home beq home
stz KB_LAST
; beq home
cmp #'A' cmp #'A'
jeq printer jeq printer
cmp #'B' cmp #'B'
@ -109,20 +140,19 @@ reset:
jeq print_1 jeq print_1
cmp #'D' cmp #'D'
jeq print_2 jeq print_2
cmp '4'
bra debug
cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home) cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home)
beq return_home jeq return_home
; .repeat 500
; nop
; .endrepeat
; SET_DEBUG_LED_OFF
; .repeat 500
; nop
; .endrepeat
jmp home jmp home
debug:
DEBUG_LED_OFF 0
jmp home
.endproc .endproc
print_1: print_1:
@ -135,12 +165,20 @@ print_2:
.segment "RODATA" .segment "RODATA"
message_1: .asciiz " Powered by ......6502...... **** www.quintern.xyz" message_1: .asciiz " Powered by ......6502...... **** www.quintern.xyz"
message_2: .asciiz " Danke fuer eure Aufmerksamkeit ;) " message_2:
.byte " Hallo "
.byte " Clara "
.byte " <3 "
.asciiz "================"
message_menu: message_menu:
.byte "<A> Printer " .byte "<A> Printer "
.byte "<B> Temperatur " .byte "<B> Temperatur "
.byte "<C> Text 1 " .byte "<C> Text 1 "
.asciiz "<D> Text 2 " .asciiz "<D> Text 2 "
str_irq:
.asciiz "IRQ detected! "
str_irq_unknown:
.asciiz "Unknown IRQ src!"
.segment "CODE" .segment "CODE"
;******************************************************************************** ;********************************************************************************

View File

@ -11,7 +11,7 @@ printer:
lda #LCD_CMD_CLEAR lda #LCD_CMD_CLEAR
jsr _lcd_cmd jsr _lcd_cmd
@printer: @printer:
jsr kb_read jsr rb_keypad_read
beq @printer beq @printer
cmp #'*' cmp #'*'
jeq return_home jeq return_home

97
system/buffer.s65 Normal file
View File

@ -0,0 +1,97 @@
;********************************************************************************
; @module ringbuffer
; @type utility
; @details
; Size of the ringbuffer is RBUF_MEM_END - RBUF_MEM_START - 2, since two bytes
; are used by the read and write pointer
; The RBUF_NAME variable must be defined, the functions will then be exported
; as rb_<RBUF_NAME>_<function> where <function> = init, read or write
; @requires
; RBUF_MEM_START: Start address of ringbuffer memory space
; RBUF_MEM_END: End address of ringbuffer memory space
; RBUF_NAME: Name of the ringbuffer
;********************************************************************************
.ifndef RBUF_MEM_START
.fatal "RBUF_MEM_START not defined"
.endif
.ifndef RBUF_MEM_END
.fatal "RBUF_MEM_END not defined"
.endif
; can not detect if RBUF_NAME is defined, if it is not you will get
; "String constant expected" Error on the line below
.define _RBUF_NAME .concat("rb_", RBUF_NAME)
RB_WRITE = RBUF_MEM_START ; write pointer, relative to RB_WRITE
RB_READ = RBUF_MEM_START + 1 ; read ponter, relative to RB_START
RB_START = RBUF_MEM_START + 2
RB_LENGTH = RBUF_MEM_END - RBUF_MEM_START - 2
.if RB_LENGTH < 1
.fatal "buffer size too small, must be at least 1"
.endif
.if RB_LENGTH > $ff
.fatal "buffer size too large, must be <= $ff"
.endif
;********************************************************************************
; @function Initialize the buffer
;********************************************************************************
.ident(.concat(_RBUF_NAME, "_init")):
.scope
stz RB_WRITE
stz RB_READ
rts
.endscope
;********************************************************************************
; @function Read a value from the buffer
; @details
; If there is no value to be read, the Pz will be set
; @returns A: value
; @modifies: A, X
;********************************************************************************
.ident(.concat(_RBUF_NAME, "_read")):
.scope
ldx RB_READ
cpx RB_WRITE
beq @rb_read_rts ; if buffer empty
lda RB_START,x
inx ; increment RB_READ pointer
cpx #RB_LENGTH
beq @rb_read_jump
stx RB_READ
@rb_read_rts:
rts
@rb_read_jump:
stz RB_READ
; make sure Pz is not set
ldx #$01
rts
.endscope
;********************************************************************************
; @function Write a value to the buffer
; @param A: value to store
; @modifies: X
;********************************************************************************
.ident(.concat(_RBUF_NAME, "_write")):
.scope
; lda kp_VALUES, x ; load the char in a
ldx RB_WRITE
sta RB_START,x
inx ; increment write pointer
cpx #RB_LENGTH
beq @rb_jump_write
stx RB_WRITE
rts
@rb_jump_write: ; when the end of the buffer is reached, the next keys go to the start again
stz RB_WRITE
rts
.endscope
.undefine _RBUF_NAME
.undefine RBUF_NAME

View File

@ -6,112 +6,95 @@
; The LCD must be connected to a W65C22N Interface Chip: ; The LCD must be connected to a W65C22N Interface Chip:
; - IO.RB0-7 -> ; - IO.RB0-7 ->
; @requires KP_IO: Base Address of IO Chip ; @requires KP_IO: Base Address of IO Chip
; @depends IO-W65C22N ; @depends IO-W65C22N
;******************************************************************************** ;********************************************************************************
.ifndef INCLUDE_KEYPAD .ifndef INCLUDE_KEYPAD
INCLUDE_KEYPAD = 1 INCLUDE_KEYPAD = 1
.ifndef KP_IO .ifndef KP_IO
.fatal "KP_IO is not defined: set it to the base address of the IO chip of the Keypad" .fatal "KP_IO is not defined: set it to the base address of the IO chip of the Keypad"
.endif .endif
;********************************************************************************
; Keypad Buffer from $202 to $2ff
;********************************************************************************
KB_VAR = $00
KB_WRITE = $200 ; write pointer, relative to KB_WRITE
KB_READ = $201 ; read ponter, relative to KB_START
KB_START = $202
KB_LENGTH = $fd
kb_init: RBUF_MEM_START = $200
stz KB_WRITE RBUF_MEM_END = $2ff
stz KB_READ .define RBUF_NAME "keypad"
; write null to entire buffer .include "buffer.s65"
ldx #$00
@kb_init_loop:
stz KB_START,x
inx
cpx #KB_LENGTH
bne @kb_init_loop
rts
; read from keybuffer, if empty null will be read KB_VAR = $05
kb_read: KB_LAST = $06
ldx KB_READ
lda KB_START,x
beq @kb_read_rts ; if a buffer is null, dont increment KB_READ
stz KB_START,x ; set buffer location to null
inx ; increment KB_READ pointer
cpx #KB_LENGTH
beq @kb_read_jump
stx KB_READ
@kb_read_rts:
rts
@kb_read_jump:
stz KB_READ
rts
; write to keybuffer .proc kp_init
_kb_write: ; todo remove
lda kp_VALUES, x ; load the char in a stz KB_LAST
ldx KB_WRITE ; todo remove later
sta KB_START,x lda #$ff
inx ; increment KB_WRITE pointer sta KP_IO+IO_DDRB
cpx #KB_LENGTH stz KP_IO+IO_RB
beq @kb_jump_write
stx KB_WRITE
rts
@kb_jump_write: ; when the end of the buffer is reached, the next keys go to the start again
stz KB_WRITE
rts
kp_init:
; INIT KEYPAD ; INIT KEYPAD
lda #%00001111; KP_IO+IO_RB 0-3 output lda #%00001111; KP_IO+IO_RB 0-3 output
sta KP_IO+IO_DDRB sta KP_IO+IO_DDRB
stz KP_IO+IO_RB ; KP_IO+IO_RB 4-7 1 so keypad press can be detected stz KP_IO+IO_RB ; KP_IO+IO_RB 4-7 1 so keypad press can be detected
stz KP_IO+IO_ACR stz KP_IO+IO_ACR
lda #%10010000 ; enable interrupt for CB1 on KP_IO+IO_IO ; lda #%00010000 ; set CB1 to interrupt on pos. edge
sta KP_IO+IO_IER lda #IO_PCR_CB1_IP_AE
lda #%00010000 ; set CB1 to interrupt on pos. edge
sta KP_IO+IO_PCR sta KP_IO+IO_PCR
jsr kb_init ; init keybuffer jsr rb_keypad_init ; init keybuffer
lda #%10010000 ; enable interrupt for CB1 on KP_IO
sta KP_IO+IO_IER
rts rts
.endproc
;******************************************************************************** ;********************************************************************************
; Reading the Keypad ; @function Read which key is pressed on the keypad
; @details
; Checks which key is pressed and stores it in the keybuffer
; The value stored in the keybuffer is the offset which must be added to
; kp_VALUES to retrieve the key that was pressed
;******************************************************************************** ;********************************************************************************
kp_read: ; test each "row" and check which column is 1 .proc kp_read_on_irq
; test each "row" and check which column is 1
lda #%00001110 lda #%00001110
ldx #$00 ldx #$00
jsr @kp_read_branch jsr @kp_read_column
lda #%00001101 lda #%00001101
ldx #$04 ldx #$04
jsr @kp_read_branch jsr @kp_read_column
lda #%00001011 lda #%00001011
ldx #$08 ldx #$08
jsr @kp_read_branch jsr @kp_read_column
lda #%00000111 lda #%00000111
ldx #$0c ldx #$0c
jsr @kp_read_branch jsr @kp_read_column
@kp_read_rts: bra @kp_read_rts
stz KP_IO+IO_RB @kp_read_column:
lda KP_IO+IO_RB ; read to definetly clear the interrupt flag
rts
@kp_read_branch:
sta KP_IO+IO_RB sta KP_IO+IO_RB
lda KP_IO+IO_RB lda KP_IO+IO_RB
sta KB_VAR ; store result in zeropage so that bbr can be used sta KB_VAR ; store result in zeropage so that bbr can be used
bbr4 KB_VAR,_kb_write bbr4 KB_VAR,@kp_write
inx inx
bbr5 KB_VAR,_kb_write bbr5 KB_VAR,@kp_write
inx inx
bbr6 KB_VAR,_kb_write bbr6 KB_VAR,@kp_write
inx inx
bbr7 KB_VAR,_kb_write bbr7 KB_VAR,@kp_write
rts rts
@kp_write:
; temporary: store last keypress in KB_LAST, TODO: remove
lda kp_VALUES,x
sta KB_LAST
txa
jsr rb_keypad_write
@kp_read_rts:
stz KP_IO+IO_RB
; lda KP_IO+IO_RB ; read to definetly clear the interrupt flag
rts
.endproc
.segment "RODATA"
kp_VALUES: kp_VALUES:
; TODO change to literal ; TODO change to literal
.byte "123A", "456B", "789C", "*0#D" .byte "123A", "456B", "789C", "*0#D"

View File

@ -103,7 +103,7 @@ LCD_CLEAR = %00000000
.proc lcd_print .proc lcd_print
ldy #$00 ldy #$00
@lcd_print_loop: @lcd_print_loop:
lda ARG0,y lda (ARG0),y
beq @lcd_print_end beq @lcd_print_end
jsr _lcd_char jsr _lcd_char
iny iny
@ -112,6 +112,10 @@ LCD_CLEAR = %00000000
rts rts
.endproc .endproc
;********************************************************************************
; @macro Print a null-terminated string
; @param message: Address of the message
;********************************************************************************
.macro Print message .macro Print message
jsr lcd_clear jsr lcd_clear
lda #.LOBYTE(message) lda #.LOBYTE(message)

View File

@ -5,19 +5,19 @@
; @depends IO-W65C22N ; @depends IO-W65C22N
;******************************************************************************** ;********************************************************************************
.include "system/system.h65" .include "system/system.h65"
.ifndef INCLUDE_SPI .ifndef INCLUDE_SPI
INCLUDE_SPI = 1 INCLUDE_SPI = 1
.segment "CODE" .segment "CODE"
.struct SPI_Pins
.struct SPI_P_Pins
; VIA addresses ; VIA addresses
DDR_a .word ; address of the data direction register DDR_a .word ; address of the data direction register
R_a .word ; address of the register R_a .word ; address of the register
; pin mask ; pin mask
SLK_p .byte ; Serial Clock SCLK_p .byte ; Serial Clock
POCI_p .byte ; Peripheral Out / Controller In POCI_p .byte ; Peripheral Out / Controller In
PICO_p .byte ; Peripheral In / Controller Out PICO_p .byte ; Peripheral In / Controller Out
CSB_p .byte ; Chip Select CSB_p .byte ; Chip Select
@ -25,14 +25,47 @@ INCLUDE_SPI = 1
CPOL .byte ; Clock Polarity CPOL .byte ; Clock Polarity
CPHA .byte ; Clock Phase CPHA .byte ; Clock Phase
.endstruct .endstruct
;********************************************************************************
; @function Initialize the IO Adapter for SPI
; @param ARG0-1 Address of the SPI_Pins struct
;********************************************************************************
.proc spi_p_init
; todo USE MASKS
; set Shift register to shift in under external clock on CB1
lda #%00001100
sta SPI_IO + IO_ACR
; enable SR interrupts
lda #%10000100
sta SPI_IO + IO_IER
rts
.endproc
.proc spi_p_read
; print received byte
lda SPI_IO + IO_SR
jsr _lcd_char
rts
.endproc
;********************************************************************************
; @function Read bytes
; @param X Number of bytes to send
; @param ARG0-1 Address of the SPI_Pins struct
; @param ARG2-3 Address of the first byte
;********************************************************************************
.proc recv_data
.endproc
;******************************************************************************** ;********************************************************************************
; @function Send bytes ; @function Send bytes
; @param X Number of bytes to send ; @param X Number of bytes to send
; @param ARG0-1 Address of the first byte ; @param ARG0-1 Address of the SPI_Pins struct
; @param ARG2-3 Address of the SPI_Pins struct ; @param ARG2-3 Address of the first byte
;******************************************************************************** ;********************************************************************************
send_data: .proc send_data
.endproc