Compare commits
7 Commits
4dbdbaf55d
...
55d0926fe4
Author | SHA1 | Date | |
---|---|---|---|
|
55d0926fe4 | ||
|
5ec8858180 | ||
|
44b73b30c3 | ||
|
3fcf8e45c6 | ||
|
83009b11b4 | ||
|
bb88981d80 | ||
|
f3a51dc764 |
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ SRC_DIRS = programs system
|
||||
|
||||
# VASM = ~/6502/vasm6502
|
||||
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
|
||||
|
||||
LD = ld65
|
||||
|
@ -1,7 +1,9 @@
|
||||
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 {
|
||||
RAM: load = RAM, type = bss;
|
||||
CODE: load = ROM, type = ro;
|
||||
RODATA: load = ROM, type = ro;
|
||||
RESET_VECTOR: load = ROM, type = ro, start = $FFFA;
|
||||
|
148
main.s65
148
main.s65
@ -1,6 +1,26 @@
|
||||
.segment "CODE"
|
||||
.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
|
||||
;********************************************************************************
|
||||
@ -9,13 +29,17 @@
|
||||
LCD_IO = IO1
|
||||
.include "lcd.s65"
|
||||
; Keypad Reading
|
||||
KP_IO = IO1
|
||||
KP_IO = IO2
|
||||
.include "keypad.s65"
|
||||
; SPI
|
||||
SPI_IO = IO1
|
||||
.include "system/spi.s65"
|
||||
; Printer
|
||||
.include "printer.s65"
|
||||
; Digital Humidity and Temerature Sensor
|
||||
; .include "dht.s65"
|
||||
|
||||
|
||||
;********************************************************************************
|
||||
; Interrupts
|
||||
;********************************************************************************
|
||||
@ -24,51 +48,52 @@ nmi:
|
||||
jsr _lcd_char
|
||||
rti
|
||||
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
|
||||
sta 0
|
||||
; todo: decide wether to read keypad or dht
|
||||
ora #%10100000
|
||||
; jsr lcd_char ;TODO: Remove
|
||||
jsr kp_read
|
||||
rti
|
||||
; bbs1 0,irq_keypad
|
||||
lda #'-'
|
||||
jsr _lcd_char
|
||||
; bbs4 0,irq_dht
|
||||
; bbs6 0,irq_dht
|
||||
rti
|
||||
irq_keypad:
|
||||
jsr kp_read
|
||||
rti
|
||||
irq_dht:
|
||||
bbr7 0,@irq_return
|
||||
bbs4 0,@irq_keypad ; check CB1
|
||||
; this should never be reached
|
||||
Print str_irq_unknown
|
||||
; force reset interrupt flags
|
||||
lda #$ff
|
||||
sta IO1 + IO_IFR
|
||||
sta IO2 + IO_IFR
|
||||
bra @irq_return
|
||||
@irq_keypad:
|
||||
jsr kp_read_on_irq
|
||||
bra irq
|
||||
@irq_spi_p:
|
||||
jsr spi_p_read
|
||||
bra irq
|
||||
@irq_dht:
|
||||
lda IO1 + IO_T1CL ;T1L2 ; clear interrupt flag
|
||||
; jsr dht_irq
|
||||
bra irq
|
||||
@irq_return:
|
||||
rti
|
||||
|
||||
;********************************************************************************
|
||||
; Reset sequence
|
||||
;********************************************************************************
|
||||
reset:
|
||||
lda #%11111111
|
||||
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 spi_p_init
|
||||
|
||||
jsr lcd_init
|
||||
|
||||
; .repeat 1000
|
||||
; nop
|
||||
; .endrepeat
|
||||
; SET_DEBUG_LED_ON
|
||||
jsr kp_init
|
||||
; SET_DEBUG_LED_OFF
|
||||
|
||||
lda #$ff
|
||||
sta IO1 + IO_DDRA
|
||||
DEBUG_LED_ON 0
|
||||
DEBUG_LED_ON 1
|
||||
|
||||
; ; INIT DHT
|
||||
; lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2
|
||||
@ -86,21 +111,27 @@ reset:
|
||||
|
||||
.proc return_home
|
||||
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
|
||||
|
||||
.proc home
|
||||
; SET_DEBUG_LED_ON
|
||||
jsr kb_read
|
||||
.macro wait
|
||||
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
|
||||
stz KB_LAST
|
||||
; beq home
|
||||
cmp #'A'
|
||||
jeq printer
|
||||
cmp #'B'
|
||||
@ -109,20 +140,19 @@ reset:
|
||||
jeq print_1
|
||||
cmp #'D'
|
||||
jeq print_2
|
||||
cmp '4'
|
||||
bra debug
|
||||
|
||||
cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home)
|
||||
beq return_home
|
||||
|
||||
; .repeat 500
|
||||
; nop
|
||||
; .endrepeat
|
||||
; SET_DEBUG_LED_OFF
|
||||
; .repeat 500
|
||||
; nop
|
||||
; .endrepeat
|
||||
jeq return_home
|
||||
|
||||
jmp home
|
||||
|
||||
debug:
|
||||
DEBUG_LED_OFF 0
|
||||
jmp home
|
||||
|
||||
|
||||
.endproc
|
||||
|
||||
print_1:
|
||||
@ -135,12 +165,20 @@ print_2:
|
||||
|
||||
.segment "RODATA"
|
||||
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:
|
||||
.byte "<A> Printer "
|
||||
.byte "<B> Temperatur "
|
||||
.byte "<C> Text 1 "
|
||||
.asciiz "<D> Text 2 "
|
||||
str_irq:
|
||||
.asciiz "IRQ detected! "
|
||||
str_irq_unknown:
|
||||
.asciiz "Unknown IRQ src!"
|
||||
|
||||
.segment "CODE"
|
||||
;********************************************************************************
|
||||
|
@ -11,7 +11,7 @@ printer:
|
||||
lda #LCD_CMD_CLEAR
|
||||
jsr _lcd_cmd
|
||||
@printer:
|
||||
jsr kb_read
|
||||
jsr rb_keypad_read
|
||||
beq @printer
|
||||
cmp #'*'
|
||||
jeq return_home
|
||||
|
97
system/buffer.s65
Normal file
97
system/buffer.s65
Normal 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
|
||||
|
||||
|
@ -6,112 +6,95 @@
|
||||
; The LCD must be connected to a W65C22N Interface Chip:
|
||||
; - IO.RB0-7 ->
|
||||
; @requires KP_IO: Base Address of IO Chip
|
||||
; @depends IO-W65C22N
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
|
||||
|
||||
.ifndef INCLUDE_KEYPAD
|
||||
INCLUDE_KEYPAD = 1
|
||||
.ifndef KP_IO
|
||||
.fatal "KP_IO is not defined: set it to the base address of the IO chip of the Keypad"
|
||||
.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:
|
||||
stz KB_WRITE
|
||||
stz KB_READ
|
||||
; write null to entire buffer
|
||||
ldx #$00
|
||||
@kb_init_loop:
|
||||
stz KB_START,x
|
||||
inx
|
||||
cpx #KB_LENGTH
|
||||
bne @kb_init_loop
|
||||
rts
|
||||
RBUF_MEM_START = $200
|
||||
RBUF_MEM_END = $2ff
|
||||
.define RBUF_NAME "keypad"
|
||||
.include "buffer.s65"
|
||||
|
||||
; read from keybuffer, if empty null will be read
|
||||
kb_read:
|
||||
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
|
||||
KB_VAR = $05
|
||||
KB_LAST = $06
|
||||
|
||||
; write to keybuffer
|
||||
_kb_write:
|
||||
lda kp_VALUES, x ; load the char in a
|
||||
ldx KB_WRITE
|
||||
sta KB_START,x
|
||||
inx ; increment KB_WRITE pointer
|
||||
cpx #KB_LENGTH
|
||||
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
|
||||
.proc kp_init
|
||||
; todo remove
|
||||
stz KB_LAST
|
||||
; todo remove later
|
||||
lda #$ff
|
||||
sta KP_IO+IO_DDRB
|
||||
stz KP_IO+IO_RB
|
||||
|
||||
kp_init:
|
||||
; INIT KEYPAD
|
||||
lda #%00001111; KP_IO+IO_RB 0-3 output
|
||||
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_ACR
|
||||
|
||||
lda #%10010000 ; enable interrupt for CB1 on KP_IO+IO_IO
|
||||
sta KP_IO+IO_IER
|
||||
lda #%00010000 ; set CB1 to interrupt on pos. edge
|
||||
; lda #%00010000 ; set CB1 to interrupt on pos. edge
|
||||
lda #IO_PCR_CB1_IP_AE
|
||||
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
|
||||
.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
|
||||
ldx #$00
|
||||
jsr @kp_read_branch
|
||||
jsr @kp_read_column
|
||||
lda #%00001101
|
||||
ldx #$04
|
||||
jsr @kp_read_branch
|
||||
jsr @kp_read_column
|
||||
lda #%00001011
|
||||
ldx #$08
|
||||
jsr @kp_read_branch
|
||||
jsr @kp_read_column
|
||||
lda #%00000111
|
||||
ldx #$0c
|
||||
jsr @kp_read_branch
|
||||
@kp_read_rts:
|
||||
stz KP_IO+IO_RB
|
||||
lda KP_IO+IO_RB ; read to definetly clear the interrupt flag
|
||||
rts
|
||||
@kp_read_branch:
|
||||
jsr @kp_read_column
|
||||
bra @kp_read_rts
|
||||
@kp_read_column:
|
||||
sta KP_IO+IO_RB
|
||||
lda KP_IO+IO_RB
|
||||
sta KB_VAR ; store result in zeropage so that bbr can be used
|
||||
bbr4 KB_VAR,_kb_write
|
||||
bbr4 KB_VAR,@kp_write
|
||||
inx
|
||||
bbr5 KB_VAR,_kb_write
|
||||
bbr5 KB_VAR,@kp_write
|
||||
inx
|
||||
bbr6 KB_VAR,_kb_write
|
||||
bbr6 KB_VAR,@kp_write
|
||||
inx
|
||||
bbr7 KB_VAR,_kb_write
|
||||
bbr7 KB_VAR,@kp_write
|
||||
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:
|
||||
; TODO change to literal
|
||||
.byte "123A", "456B", "789C", "*0#D"
|
||||
|
@ -103,7 +103,7 @@ LCD_CLEAR = %00000000
|
||||
.proc lcd_print
|
||||
ldy #$00
|
||||
@lcd_print_loop:
|
||||
lda ARG0,y
|
||||
lda (ARG0),y
|
||||
beq @lcd_print_end
|
||||
jsr _lcd_char
|
||||
iny
|
||||
@ -112,6 +112,10 @@ LCD_CLEAR = %00000000
|
||||
rts
|
||||
.endproc
|
||||
|
||||
;********************************************************************************
|
||||
; @macro Print a null-terminated string
|
||||
; @param message: Address of the message
|
||||
;********************************************************************************
|
||||
.macro Print message
|
||||
jsr lcd_clear
|
||||
lda #.LOBYTE(message)
|
||||
|
@ -5,19 +5,19 @@
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
|
||||
.include "system/system.h65"
|
||||
.include "system/system.h65"
|
||||
|
||||
.ifndef INCLUDE_SPI
|
||||
INCLUDE_SPI = 1
|
||||
|
||||
.segment "CODE"
|
||||
|
||||
.struct SPI_Pins
|
||||
|
||||
.struct SPI_P_Pins
|
||||
; VIA addresses
|
||||
DDR_a .word ; address of the data direction register
|
||||
R_a .word ; address of the register
|
||||
; pin mask
|
||||
SLK_p .byte ; Serial Clock
|
||||
SCLK_p .byte ; Serial Clock
|
||||
POCI_p .byte ; Peripheral Out / Controller In
|
||||
PICO_p .byte ; Peripheral In / Controller Out
|
||||
CSB_p .byte ; Chip Select
|
||||
@ -25,14 +25,47 @@ INCLUDE_SPI = 1
|
||||
CPOL .byte ; Clock Polarity
|
||||
CPHA .byte ; Clock Phase
|
||||
.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
|
||||
; @param X Number of bytes to send
|
||||
; @param ARG0-1 Address of the first byte
|
||||
; @param ARG2-3 Address of the SPI_Pins struct
|
||||
; @param ARG0-1 Address of the SPI_Pins struct
|
||||
; @param ARG2-3 Address of the first byte
|
||||
;********************************************************************************
|
||||
send_data:
|
||||
.proc send_data
|
||||
.endproc
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user