initial commit
This commit is contained in:
commit
7214f1fe6f
4
.dependencies
Normal file
4
.dependencies
Normal file
@ -0,0 +1,4 @@
|
||||
../rom.bin: main.asm6502 system/system.asm6502 system/io_W65C22.asm6502 utility.asm6502 /usr/share/cc65/asminc/longbranch.mac system/lcd.asm6502 utility.asm6502 system/keypad.asm6502 programs/printer.asm6502 programs/dht.asm6502
|
||||
|
||||
main.asm6502 system/system.asm6502 system/io_W65C22.asm6502 utility.asm6502 /usr/share/cc65/asminc/longbranch.mac system/lcd.asm6502 utility.asm6502 system/keypad.asm6502 programs/printer.asm6502 programs/dht.asm6502:
|
||||
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**.bin
|
||||
**.o
|
28
Makefile
Normal file
28
Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
ROM = ../rom.bin
|
||||
MAIN = main.asm6502
|
||||
|
||||
BUILD_DIR = .build
|
||||
|
||||
SRC_DIRS = programs system
|
||||
|
||||
# VASM = ~/6502/vasm6502
|
||||
ASM = ca65
|
||||
ASMFLAGS = --cpu 65C02 $(foreach srcdir, $(SRC_DIRS), -I $(srcdir))
|
||||
ASMDEPFLAGS = --create-dep .dependencies
|
||||
|
||||
LD = ld65
|
||||
LDFLAGS = -C linker.conf
|
||||
|
||||
# DEPENDS = $(shell $(VASM) -depend=make $(MAIN))
|
||||
|
||||
-include .dependencies
|
||||
|
||||
default: $(ROM)
|
||||
$(ROM):
|
||||
$(ASM) $(ASMFLAGS) $(ASMDEPFLAGS) $(MAIN) -o $@
|
||||
|
||||
.PHONY = test
|
||||
test:
|
||||
# $(VASM) -dotdir -opt-branch -wdc02 -chklabels test.asm6502
|
||||
$(ASM) $(ASMFLAGS) test.asm6502 -o test.o
|
||||
$(LD) $(LDFLAGS) test.o -o test.bin
|
16
details.md
Normal file
16
details.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Project details
|
||||
## Address Space
|
||||
### RAM: $0-$7fff
|
||||
### (EEP)ROM: $8000-$ffff
|
||||
|
||||
## Naming conventions
|
||||
leading underscors `_` indicate a "private" label/variable, that is meant for internal use within the module only.
|
||||
### Labels
|
||||
- `namespace_fname` for exported subroutines
|
||||
- `_namespace_fname` or `_namespace_fname_sub` for internal labels
|
||||
- `(_)namespace_LABELNAME` for labels to data sections
|
||||
|
||||
### Symbols/Macros
|
||||
- `(_)NAMESPACE_SYMBOLNAME` for symbols
|
||||
- `(_)NAMESPACE_macroname
|
||||
|
155
dht.s65
Normal file
155
dht.s65
Normal file
@ -0,0 +1,155 @@
|
||||
;********************************************************************************
|
||||
; @module SPI
|
||||
; @type driver
|
||||
; @details
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
|
||||
;TODO EVERYTHING
|
||||
DHT_REQUEST_L = $00
|
||||
DHT_REQUEST_H = %01010000 ; = 20480 PHI2 pulses = 20,5 ms at 1 MHz
|
||||
|
||||
DHT_RECV_H = %10011100
|
||||
DHT_RECV_L = %01000000 ; = 40000 PHI2 = 40ms
|
||||
|
||||
; Status Variables, Used to determine what is sent by temp module
|
||||
DHT_STATUS = $400
|
||||
DHT_NONE = 0
|
||||
DHT_WAIT_REQ = 1
|
||||
DHT_WAIT_RESP = 2
|
||||
DHT_RECV = 3
|
||||
DHT_DONE = 4
|
||||
|
||||
DHT_BIT = $401
|
||||
DHT_BIT_ROT = $402
|
||||
|
||||
|
||||
DHT_VALUES = $405 ;
|
||||
DHT_OFFSET = $403
|
||||
DHT_OFF_RH_HIGH = 0 ; offsets to DHT_VALUES
|
||||
DHT_OFF_RH_LOW = 1
|
||||
DHT_OFF_T_HIGH = 2
|
||||
DHT_OFF_T_LOW = 3
|
||||
DHT_OFF_CHECKSUM = 4
|
||||
DHT_OFF_DONE = 5
|
||||
|
||||
|
||||
message_dht: .asciiz "DHT-Request gesendet."
|
||||
dht_wait:
|
||||
ldx #$00
|
||||
dht_wait_:
|
||||
lda message_dht,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
bne dht_wait_
|
||||
jsr lcd_print_clear
|
||||
dht_wait_loop: ; check after every interrpt if dht program is done and then return home
|
||||
lda #'.'
|
||||
jsr _lcd_char
|
||||
wai
|
||||
lda DHT_STATUS
|
||||
cmp #DHT_DONE
|
||||
bne dht_wait_loop
|
||||
|
||||
dht_exit:
|
||||
jsr kb_read
|
||||
cmp #'*'
|
||||
jeq home
|
||||
bra dht_exit
|
||||
jmp return_home
|
||||
|
||||
dht_request: ; send request to sensor
|
||||
sei
|
||||
|
||||
lda #%00000001 ; set PA1-0 to output 0
|
||||
ora DDRA1
|
||||
sta DDRA1
|
||||
lda #(LCD_CLEAR | $00)
|
||||
sta PA1
|
||||
|
||||
; start timer
|
||||
lda #DHT_REQUEST_L
|
||||
sta T1L1
|
||||
lda #DHT_REQUEST_H
|
||||
sta T1H1
|
||||
|
||||
lda #DHT_WAIT_REQ
|
||||
sta DHT_STATUS
|
||||
|
||||
cli
|
||||
jmp dht_wait
|
||||
|
||||
|
||||
dht_request_end:
|
||||
lda #%10000010
|
||||
sta IER2 ; enable Interrupt for CA1
|
||||
lda #%11111110
|
||||
and DDRA1
|
||||
sta DDRA1 ; set PA1-0 to input
|
||||
|
||||
lda #DHT_WAIT_RESP
|
||||
|
||||
|
||||
|
||||
dht_response: ; receive response from sensor
|
||||
lda #DHT_RECV
|
||||
sta DHT_STATUS
|
||||
stz DHT_OFFSET
|
||||
lda #7
|
||||
sta DHT_BIT
|
||||
|
||||
dht_recv:
|
||||
; start timer
|
||||
lda #DHT_RECV_L
|
||||
sta T1L1
|
||||
lda #DHT_RECV_H
|
||||
sta T1H1
|
||||
rts
|
||||
|
||||
dht_recv_read:
|
||||
; read PA2
|
||||
lda PA2
|
||||
and #%00000001
|
||||
ldx DHT_BIT
|
||||
beq dht_recv_end
|
||||
dht_recv_rot:
|
||||
rol
|
||||
dex
|
||||
bne dht_recv_rot
|
||||
dht_recv_end:
|
||||
ldy DHT_OFFSET
|
||||
ora DHT_VALUES,y
|
||||
sta DHT_VALUES,y
|
||||
; determine if 8 bits are done
|
||||
ldx DHT_BIT
|
||||
beq dht_recv_next
|
||||
rts
|
||||
dht_recv_next:
|
||||
lda #7
|
||||
sta DHT_BIT
|
||||
inc DHT_OFFSET
|
||||
cmp DHT_OFF_DONE
|
||||
beq dht_display
|
||||
rts
|
||||
|
||||
dht_display:
|
||||
ldx #0
|
||||
dht_display_:
|
||||
lda DHT_VALUES,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
cpx #5
|
||||
bne dht_display_
|
||||
jsr lcd_print_clear
|
||||
rts
|
||||
|
||||
dht_irq:
|
||||
lda DHT_STATUS
|
||||
cmp #DHT_WAIT_REQ
|
||||
beq dht_request_end
|
||||
cmp #DHT_WAIT_RESP
|
||||
beq dht_response
|
||||
cmp #DHT_RECV
|
||||
beq dht_recv
|
||||
rts
|
||||
|
7
linker.conf
Normal file
7
linker.conf
Normal file
@ -0,0 +1,7 @@
|
||||
MEMORY {
|
||||
ROM: start = $8000, size = $8000, file = %O, fill = yes;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load = ROM, type = ro;
|
||||
RESET_VECTOR: load = ROM, type = ro, start = $FFFA;
|
||||
}
|
148
main.s65
Normal file
148
main.s65
Normal file
@ -0,0 +1,148 @@
|
||||
.include "system/system.h65"
|
||||
.org $8000 ; EEPROM Start Address
|
||||
|
||||
;********************************************************************************
|
||||
; Interrupts
|
||||
;********************************************************************************
|
||||
nmi:
|
||||
rti
|
||||
irq:
|
||||
; lda IFR2 todo: verify that the line below does the same thing
|
||||
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:
|
||||
lda T1L2 ; clear interrupt flag
|
||||
jsr dht_irq
|
||||
rti
|
||||
|
||||
;********************************************************************************
|
||||
; Reset sequence
|
||||
;********************************************************************************
|
||||
reset:
|
||||
lda #%11111111
|
||||
sta IO2 + IO_DDRA
|
||||
.macro SET_DEBUG_LED_OFF
|
||||
lda #%00000000
|
||||
sta IO2 + IO_RANH
|
||||
.endmacro
|
||||
.macro SET_DEBUG_LED_ON
|
||||
lda #%11111111
|
||||
sta IO2 + IO_RANH
|
||||
.endmacro
|
||||
SET_DEBUG_LED_OFF
|
||||
jsr lcd_init
|
||||
|
||||
SET_DEBUG_LED_ON
|
||||
; jsr kp_init
|
||||
|
||||
; INIT DHT
|
||||
lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2
|
||||
sta IER2
|
||||
lda #%00111111 ; set Timer 1 to interrupt when loaded
|
||||
and ACR2
|
||||
sta ACR2
|
||||
lda #%00000001 ; set PCR2 bit 0 CA1 pos edge interrupt
|
||||
ora PCR2
|
||||
sta PCR2
|
||||
stz DHT_STATUS
|
||||
|
||||
; enable interrupts
|
||||
cli
|
||||
|
||||
.proc return_home
|
||||
ldx #$00
|
||||
@return_home:
|
||||
lda menu,x
|
||||
beq @return_home_done
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
bra @return_home
|
||||
@return_home_done:
|
||||
jsr lcd_print_clear
|
||||
.endproc
|
||||
|
||||
.proc home
|
||||
jsr kb_read
|
||||
beq home
|
||||
cmp #'A'
|
||||
jeq printer
|
||||
cmp #'B'
|
||||
jeq dht_request
|
||||
cmp #'C'
|
||||
beq print_1
|
||||
cmp #'D'
|
||||
beq print_2
|
||||
|
||||
cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home)
|
||||
beq return_home
|
||||
|
||||
bra home
|
||||
.endproc
|
||||
|
||||
print_1:
|
||||
ldx #$00
|
||||
@print_1:
|
||||
lda message_1,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
bne @print_1
|
||||
jsr lcd_print_clear
|
||||
jmp home
|
||||
|
||||
print_2:
|
||||
ldx #$00
|
||||
@print_2:
|
||||
lda message_2,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
bne @print_2
|
||||
jsr lcd_print_clear
|
||||
jmp home
|
||||
|
||||
.rodata
|
||||
message_1: .asciiz " Powered by ......6502...... **** www.quintern.xyz"
|
||||
message_2: .asciiz " Danke fuer eure Aufmerksamkeit ;) "
|
||||
menu:
|
||||
.byte "<A> Printer "
|
||||
.byte "<B> Temperatur "
|
||||
.byte "<C> Text 1 "
|
||||
.asciiz "<D> Text 2 "
|
||||
|
||||
.code
|
||||
;********************************************************************************
|
||||
; Modules
|
||||
;********************************************************************************
|
||||
; LCD
|
||||
; .include "utility.asm6502"
|
||||
LCD_IO = IO1
|
||||
.include "lcd.asm6502"
|
||||
; Keypad Reading
|
||||
KP_IO = IO1
|
||||
.include "keypad.asm6502"
|
||||
; Printer
|
||||
.include "printer.asm6502"
|
||||
; Digital Humidity and Temerature Sensor
|
||||
.include "dht.asm6502"
|
||||
;********************************************************************************
|
||||
; reset vector
|
||||
;********************************************************************************
|
||||
|
||||
.rodata
|
||||
.org $fffa
|
||||
.word nmi
|
||||
.word reset
|
||||
.word irq
|
147
programs/dht.s65
Normal file
147
programs/dht.s65
Normal file
@ -0,0 +1,147 @@
|
||||
DHT_REQUEST_L = $00
|
||||
DHT_REQUEST_H = %01010000 ; = 20480 PHI2 pulses = 20,5 ms at 1 MHz
|
||||
|
||||
DHT_RECV_H = %10011100
|
||||
DHT_RECV_L = %01000000 ; = 40000 PHI2 = 40ms
|
||||
|
||||
; Status Variables, Used to determine what is sent by temp module
|
||||
DHT_STATUS = $400
|
||||
DHT_NONE = 0
|
||||
DHT_WAIT_REQ = 1
|
||||
DHT_WAIT_RESP = 2
|
||||
DHT_RECV = 3
|
||||
DHT_DONE = 4
|
||||
|
||||
DHT_BIT = $401
|
||||
DHT_BIT_ROT = $402
|
||||
|
||||
|
||||
DHT_VALUES = $405 ;
|
||||
DHT_OFFSET = $403
|
||||
DHT_OFF_RH_HIGH = 0 ; offsets to DHT_VALUES
|
||||
DHT_OFF_RH_LOW = 1
|
||||
DHT_OFF_T_HIGH = 2
|
||||
DHT_OFF_T_LOW = 3
|
||||
DHT_OFF_CHECKSUM = 4
|
||||
DHT_OFF_DONE = 5
|
||||
|
||||
|
||||
message_dht: .asciiz "DHT-Request gesendet."
|
||||
dht_wait:
|
||||
ldx #$00
|
||||
dht_wait_:
|
||||
lda message_dht,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
bne dht_wait_
|
||||
jsr lcd_print_clear
|
||||
dht_wait_loop: ; check after every interrpt if dht program is done and then return home
|
||||
lda #'.'
|
||||
jsr _lcd_char
|
||||
wai
|
||||
lda DHT_STATUS
|
||||
cmp #DHT_DONE
|
||||
bne dht_wait_loop
|
||||
|
||||
dht_exit:
|
||||
jsr kb_read
|
||||
cmp #'*'
|
||||
jeq home
|
||||
bra dht_exit
|
||||
jmp return_home
|
||||
|
||||
dht_request: ; send request to sensor
|
||||
sei
|
||||
|
||||
lda #%00000001 ; set PA1-0 to output 0
|
||||
ora DDRA1
|
||||
sta DDRA1
|
||||
lda #(LCD_CLEAR | $00)
|
||||
sta PA1
|
||||
|
||||
; start timer
|
||||
lda #DHT_REQUEST_L
|
||||
sta T1L1
|
||||
lda #DHT_REQUEST_H
|
||||
sta T1H1
|
||||
|
||||
lda #DHT_WAIT_REQ
|
||||
sta DHT_STATUS
|
||||
|
||||
cli
|
||||
jmp dht_wait
|
||||
|
||||
|
||||
dht_request_end:
|
||||
lda #%10000010
|
||||
sta IER2 ; enable Interrupt for CA1
|
||||
lda #%11111110
|
||||
and DDRA1
|
||||
sta DDRA1 ; set PA1-0 to input
|
||||
|
||||
lda #DHT_WAIT_RESP
|
||||
|
||||
|
||||
|
||||
dht_response: ; receive response from sensor
|
||||
lda #DHT_RECV
|
||||
sta DHT_STATUS
|
||||
stz DHT_OFFSET
|
||||
lda #7
|
||||
sta DHT_BIT
|
||||
|
||||
dht_recv:
|
||||
; start timer
|
||||
lda #DHT_RECV_L
|
||||
sta T1L1
|
||||
lda #DHT_RECV_H
|
||||
sta T1H1
|
||||
rts
|
||||
|
||||
dht_recv_read:
|
||||
; read PA2
|
||||
lda PA2
|
||||
and #%00000001
|
||||
ldx DHT_BIT
|
||||
beq dht_recv_end
|
||||
dht_recv_rot:
|
||||
rol
|
||||
dex
|
||||
bne dht_recv_rot
|
||||
dht_recv_end:
|
||||
ldy DHT_OFFSET
|
||||
ora DHT_VALUES,y
|
||||
sta DHT_VALUES,y
|
||||
; determine if 8 bits are done
|
||||
ldx DHT_BIT
|
||||
beq dht_recv_next
|
||||
rts
|
||||
dht_recv_next:
|
||||
lda #7
|
||||
sta DHT_BIT
|
||||
inc DHT_OFFSET
|
||||
cmp DHT_OFF_DONE
|
||||
beq dht_display
|
||||
rts
|
||||
|
||||
dht_display:
|
||||
ldx #0
|
||||
dht_display_:
|
||||
lda DHT_VALUES,x
|
||||
sta TO_PRINT,x
|
||||
inx
|
||||
cpx #5
|
||||
bne dht_display_
|
||||
jsr lcd_print_clear
|
||||
rts
|
||||
|
||||
dht_irq:
|
||||
lda DHT_STATUS
|
||||
cmp #DHT_WAIT_REQ
|
||||
beq dht_request_end
|
||||
cmp #DHT_WAIT_RESP
|
||||
beq dht_response
|
||||
cmp #DHT_RECV
|
||||
beq dht_recv
|
||||
rts
|
||||
|
20
programs/printer.s65
Normal file
20
programs/printer.s65
Normal file
@ -0,0 +1,20 @@
|
||||
;********************************************************************************
|
||||
; Printing Program
|
||||
;********************************************************************************
|
||||
.ifndef INCLUDE_PRINTER
|
||||
INCLUDE_PRINTER = 1
|
||||
|
||||
printer:
|
||||
stz LCD_CHARCOUNT
|
||||
lda #%10000000
|
||||
jsr _lcd_cmd
|
||||
lda #LCD_CMD_CLEAR
|
||||
jsr _lcd_cmd
|
||||
@printer:
|
||||
jsr kb_read
|
||||
beq @printer
|
||||
cmp #'*'
|
||||
jeq return_home
|
||||
jsr _lcd_char
|
||||
bra @printer
|
||||
.endif
|
19
readme.md
Normal file
19
readme.md
Normal file
@ -0,0 +1,19 @@
|
||||
# 8-bit Breadboard Computer with W65C02S Processor
|
||||
This repo contains the assembly code for my [6502-project](https://quintern.xyz/de/6502.html).
|
||||
|
||||
The assembler used for this project is [vasm](http://www.compilers.de/vasm.html).
|
||||
After assembling it, the binary is loaded onto the EEPROM using [my *eeprom.py* script](https://git.quintern.xyz/MatthiasQuintern/AT28C256-rpi-util) on a Raspberry Pi 4B.
|
||||
|
||||
## Operating System
|
||||
... is probably a far stretch, since it is just the programs I wrote pieced together. My "os" consists of these functionalities:
|
||||
- Main Menu:
|
||||
- Printer: Prints the characters you press on the keypad to the lcd.
|
||||
- Temperature: Shows the temperature using a dht sensor. *Work in progress, this does not work yet*
|
||||
- Text 1: Show a 4x16 character text (defined at compile time)
|
||||
- Text 2: Show a 4x16 character text (defined at compile time)
|
||||
- Ringbuffer for pressed keys.
|
||||
|
||||
> It's not much, but it's honest work.
|
||||
|
||||
## Debug-Utility (with Raspberry Pi 4)
|
||||
`monitor.py` is a python program to monitor the address-bus, data-bus and the read-write pin of the computer. It prints the current address and data in binary and hexadecimal on each clock cycle.
|
49
system/io_W65C22.h65
Normal file
49
system/io_W65C22.h65
Normal file
@ -0,0 +1,49 @@
|
||||
;********************************************************************************
|
||||
; @module IO-W65C22
|
||||
; @type utility
|
||||
; @device Western Design - W65C22N Versatile Interface Adapter
|
||||
; @details
|
||||
;********************************************************************************
|
||||
|
||||
.ifndef INCLUDE_IOW65C22
|
||||
INCLUDE_IOW65C22 = 1
|
||||
|
||||
; IO-CHIPS OFFSETS FOR PINS FROM BASE ADDRESS
|
||||
IO_RB = $0
|
||||
IO_RA = $1
|
||||
IO_DDRB = $2
|
||||
IO_DDRA = $3
|
||||
IO_T1CL = $4
|
||||
IO_T1CH = $5
|
||||
IO_T1LL = $6
|
||||
IO_T1LH = $7
|
||||
IO_T2CL = $8
|
||||
IO_T2CH = $9
|
||||
IO_SR = $a
|
||||
IO_ACR = $b
|
||||
IO_PCR = $c
|
||||
IO_IFR = $d
|
||||
IO_IER = $e
|
||||
IO_RANH = $f ; no handshake
|
||||
|
||||
; TODO: leave?
|
||||
.struct VIA_Pins
|
||||
RB .byte ; $0
|
||||
RA .byte ; $1
|
||||
DDRB .byte ; $2
|
||||
DDRA .byte ; $3
|
||||
T1CL .byte ; $4
|
||||
T1CH .byte ; $5
|
||||
T1LL .byte ; $6
|
||||
T1LH .byte ; $7
|
||||
T2CL .byte ; $8
|
||||
T2CH .byte ; $9
|
||||
SR .byte ; $a
|
||||
ACR .byte ; $b
|
||||
PCR .byte ; $c
|
||||
IFR .byte ; $d
|
||||
IER .byte ; $e
|
||||
RANH .byte ; $f ; no handshake
|
||||
.endstruct
|
||||
.endif
|
||||
|
117
system/keypad.s65
Normal file
117
system/keypad.s65
Normal file
@ -0,0 +1,117 @@
|
||||
;********************************************************************************
|
||||
; @module 4x4 Keypad
|
||||
; @type driver
|
||||
; @device 4x4 Matrix Keypad
|
||||
; @details
|
||||
; Keypad must be connected to a VIA
|
||||
; @requires KP_IO: Base Address of IO Chip
|
||||
; @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
|
||||
KB_READ = $201
|
||||
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
|
||||
|
||||
; 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
|
||||
|
||||
; 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
|
||||
|
||||
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
|
||||
sta KP_IO+IO_PCR
|
||||
jsr kb_init ; init keybuffer
|
||||
rts
|
||||
|
||||
;********************************************************************************
|
||||
; Reading the Keypad
|
||||
;********************************************************************************
|
||||
kp_read: ; test each "row" and check which column is 1
|
||||
lda #%00001110
|
||||
ldx #$00
|
||||
jsr @kp_read_branch
|
||||
lda #%00001101
|
||||
ldx #$04
|
||||
jsr @kp_read_branch
|
||||
lda #%00001011
|
||||
ldx #$08
|
||||
jsr @kp_read_branch
|
||||
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:
|
||||
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
|
||||
inx
|
||||
bbr5 KB_VAR,_kb_write
|
||||
inx
|
||||
bbr6 KB_VAR,_kb_write
|
||||
inx
|
||||
bbr7 KB_VAR,_kb_write
|
||||
rts
|
||||
kp_VALUES:
|
||||
; TODO change to literal
|
||||
.byte "123A", "456B", "789C", "*0#D"
|
||||
.endif
|
211
system/lcd.s65
Normal file
211
system/lcd.s65
Normal file
@ -0,0 +1,211 @@
|
||||
;********************************************************************************
|
||||
; @module LCD-W164B
|
||||
; @type driver
|
||||
; @device ELECTRONIC ASSEMBLY - W164B-NLW
|
||||
; @details
|
||||
; Assumes it is connected to a W65C22N Interface Chip:
|
||||
; - IO.RB0-7 -> LCD.D0-7 data lines
|
||||
; - IO.RA5 -> LCD.RS register select
|
||||
; - IO.RA6 -> LCD.R/W read/write
|
||||
; - IO.RA7 -> LCD.E enable
|
||||
;
|
||||
; @requires LCD_IO: Base Address of IO Chip
|
||||
; @optparam LCD_MEM: Address to a block of memory 1B. Default = $300
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
|
||||
.ifndef LCD_IO
|
||||
.fatal "LCD_IO is not defined: set it to the base address of the IO chip of the LCD"
|
||||
.endif
|
||||
|
||||
.ifndef INCLUDE_IOW65C22
|
||||
.error "IO-W65C22 module is not included"
|
||||
.endif
|
||||
|
||||
.include "utility.asm6502"
|
||||
|
||||
|
||||
; RAM VARIABLES
|
||||
.ifndef LCD_MEM
|
||||
LCD_MEM = $300
|
||||
.endif
|
||||
LCD_CHARCOUNT = LCD_MEM
|
||||
|
||||
; PIN MASKS
|
||||
LCD_E = %10000000
|
||||
LCD_RW = %01000000
|
||||
LCD_RS = %00100000
|
||||
; .local LCD_E,LCD_RW,LCD_RS
|
||||
|
||||
; LCD Instructions
|
||||
LCD_CMD_CLEAR = %00000001 ; clear display
|
||||
LCD_CMD_ENTRY_MODE = %00000110 ; auto-shift cursor
|
||||
LCD_CMD_DISPLAY_ON = %00001111 ; everything on, with blinking cursor
|
||||
LCD_CMD_FUNCTION_SET = %00111000 ; 8-bit, 4 lines, 5x7 font
|
||||
LCD_CMD_SET_ADDRESS = %10000000 ; or with the address
|
||||
; LCD Constants
|
||||
LCD_LINE1 = $00 ; line 1
|
||||
LCD_LINE2 = $40
|
||||
LCD_LINE3 = $10
|
||||
LCD_LINE4 = $50
|
||||
|
||||
LCD_CLEAR = %00000000
|
||||
|
||||
|
||||
;********************************************************************************
|
||||
; @function Initialize the lcd module
|
||||
; @details call before doing anything else
|
||||
;********************************************************************************
|
||||
.proc lcd_init
|
||||
; init IO
|
||||
lda #$ff ; RB 0-7 output
|
||||
sta LCD_IO+IO_DDRB
|
||||
|
||||
UT_update_with_mask LCD_IO + IO_DDRA, (LCD_RS | LCD_RW | LCD_E), (LCD_RS | LCD_RW | LCD_E)
|
||||
; lda #(LCD_RS | LCD_RW | LCD_E) ; RA 5-7 output
|
||||
; sta LCD_IO+IO_DDRA
|
||||
|
||||
; init lcd
|
||||
lda #LCD_CMD_FUNCTION_SET
|
||||
jsr _lcd_cmd
|
||||
lda #LCD_CMD_DISPLAY_ON
|
||||
jsr _lcd_cmd
|
||||
lda #LCD_CMD_CLEAR
|
||||
jsr _lcd_cmd
|
||||
lda #LCD_CMD_ENTRY_MODE
|
||||
jsr _lcd_cmd
|
||||
|
||||
stz LCD_CHARCOUNT
|
||||
rts
|
||||
.endproc
|
||||
|
||||
;********************************************************************************
|
||||
; PRINTING TO LCD
|
||||
;********************************************************************************
|
||||
_lcd_clear: ; clear lcd
|
||||
stz LCD_CHARCOUNT
|
||||
lda #LCD_CLEAR
|
||||
jsr _lcd_cmd
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE1)
|
||||
jsr _lcd_cmd
|
||||
rts
|
||||
|
||||
;********************************************************************************
|
||||
; @function Clear the display and print a null-terminated string
|
||||
; @see lcd_print
|
||||
;********************************************************************************
|
||||
lcd_print_clear: ; clear lcd and print word located at message
|
||||
stz LCD_CHARCOUNT
|
||||
lda #LCD_CLEAR
|
||||
jsr _lcd_cmd
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE1)
|
||||
jsr _lcd_cmd
|
||||
|
||||
;********************************************************************************
|
||||
; @function Print a null-terminated string
|
||||
; @param ARG0-1 Address of the string to print
|
||||
;********************************************************************************
|
||||
lcd_print:
|
||||
ldx #$00
|
||||
_lcd_print_loop:
|
||||
lda (ARG0,x)
|
||||
beq _lcd_print_end
|
||||
jsr _lcd_char
|
||||
inx
|
||||
bra _lcd_print_loop
|
||||
_lcd_print_end:
|
||||
rts
|
||||
|
||||
;********************************************************************************
|
||||
; LCD Commands
|
||||
;********************************************************************************
|
||||
; read busy flag
|
||||
_lcd_wait_nbusy:
|
||||
stz LCD_IO + IO_DDRB ; set IO1-LCD_IO + IO_RB to input
|
||||
@lcd_wait_nbusy_loop: ; read the busy flag
|
||||
lda #LCD_RW
|
||||
sta LCD_IO + IO_RA
|
||||
lda #(LCD_RW | LCD_E)
|
||||
sta LCD_IO + IO_RA
|
||||
|
||||
lda LCD_IO + IO_RB
|
||||
and #%10000000 ; and updates zero flag, if not set retry
|
||||
bne @lcd_wait_nbusy_loop
|
||||
|
||||
lda #%00000000 ; TODO dont overwrite 0-4
|
||||
sta LCD_IO + IO_RA
|
||||
lda #%11111111 ; set IO1-LCD_IO + IO_RB to output
|
||||
sta LCD_IO + IO_DDRB
|
||||
rts
|
||||
|
||||
_lcd_cmd: ; send cmd in acc
|
||||
pha
|
||||
jsr _lcd_wait_nbusy
|
||||
pla
|
||||
|
||||
; TODO use UT_update_with_mask?
|
||||
sta LCD_IO + IO_RB
|
||||
lda #LCD_CLEAR
|
||||
sta LCD_IO + IO_RA
|
||||
lda #LCD_E
|
||||
sta LCD_IO + IO_RA
|
||||
lda #LCD_CLEAR
|
||||
sta LCD_IO + IO_RA
|
||||
rts
|
||||
|
||||
_lcd_char:
|
||||
pha
|
||||
pha
|
||||
; TODO use UT_update_with_mask?
|
||||
jsr _lcd_wait_nbusy
|
||||
pla
|
||||
sta LCD_IO + IO_RB
|
||||
lda #LCD_RS
|
||||
sta LCD_IO + IO_RA
|
||||
lda #(LCD_RS | LCD_E)
|
||||
sta LCD_IO + IO_RA
|
||||
lda #LCD_RS
|
||||
sta LCD_IO + IO_RA
|
||||
inc LCD_CHARCOUNT
|
||||
jsr _lcd_set_address
|
||||
pla ; put char back in a
|
||||
|
||||
;********************************************************************************
|
||||
; Set the LCD DD-RAM Address so that text linebreaks after 16 chars
|
||||
;********************************************************************************
|
||||
_lcd_set_address:
|
||||
; check if checks are necessary
|
||||
lda LCD_CHARCOUNT
|
||||
beq @lcd_line1
|
||||
and #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
|
||||
bne @lcd_set_address_done
|
||||
; checks necessary
|
||||
lda LCD_CHARCOUNT
|
||||
beq @lcd_line1
|
||||
cmp #$10
|
||||
beq @lcd_line2
|
||||
cmp #$20
|
||||
beq @lcd_line3
|
||||
cmp #$30
|
||||
beq @lcd_line4
|
||||
cmp #$40 ; set to line1 when full ; set to line1 when full
|
||||
beq @lcd_line1
|
||||
@lcd_set_address_done:
|
||||
rts
|
||||
@lcd_line1:
|
||||
stz LCD_CHARCOUNT
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE1)
|
||||
jsr _lcd_cmd
|
||||
rts
|
||||
@lcd_line2:
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE2)
|
||||
jsr _lcd_cmd
|
||||
rts
|
||||
@lcd_line3:
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE3)
|
||||
jsr _lcd_cmd
|
||||
rts
|
||||
@lcd_line4:
|
||||
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE4)
|
||||
jsr _lcd_cmd
|
||||
rts
|
41
system/spi.s65
Normal file
41
system/spi.s65
Normal file
@ -0,0 +1,41 @@
|
||||
;********************************************************************************
|
||||
; @module SPI
|
||||
; @type driver
|
||||
; @details
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
|
||||
.include "system/system.h65"
|
||||
|
||||
.ifndef INCLUDE_SPI
|
||||
INCLUDE_SPI = 1
|
||||
|
||||
.segment "CODE"
|
||||
|
||||
.struct SPI_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
|
||||
POCI_p .byte ; Peripheral Out / Controller In
|
||||
PICO_p .byte ; Peripheral In / Controller Out
|
||||
CSB_p .byte ; Chip Select
|
||||
; settings
|
||||
CPOL .byte ; Clock Polarity
|
||||
CPHA .byte ; Clock Phase
|
||||
.endstruct
|
||||
|
||||
;********************************************************************************
|
||||
; @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
|
||||
;********************************************************************************
|
||||
send_data:
|
||||
|
||||
|
||||
|
||||
_send_byte:
|
||||
|
||||
.endif
|
78
system/system.h65
Normal file
78
system/system.h65
Normal file
@ -0,0 +1,78 @@
|
||||
;********************************************************************************
|
||||
; @module system
|
||||
; @type header
|
||||
; @details
|
||||
; Variable definitions for the current hardware setup
|
||||
;********************************************************************************
|
||||
|
||||
.ifndef INCLUDE_SYSTEM
|
||||
INCLUDE_SYSTEM = 1
|
||||
; reserved RAM addresses
|
||||
; 00-0f - free
|
||||
; 10-1f - arguments / return values
|
||||
; 20-ff - free
|
||||
; 0100 - 01FF Stack
|
||||
; 0200,0201 keybuffer write/read pointer
|
||||
; 0202 - 02ff keybuffer
|
||||
; 0300 lcd character counter
|
||||
; 0301 - 0341 message to print
|
||||
; 0400, 0401, 0402 dht status, dht bit, dht_bit_rot
|
||||
; 0403 value offset
|
||||
; 0405 - 04a0 rh high/low, temp high/low, checksum
|
||||
|
||||
TO_PRINT = $300
|
||||
|
||||
; ARGUMENTS
|
||||
; a,x,y can also be used
|
||||
ARG0 = $10
|
||||
ARG1 = $11
|
||||
ARG2 = $12
|
||||
ARG3 = $13
|
||||
ARG4 = $14
|
||||
ARG5 = $15
|
||||
ARG6 = $16
|
||||
ARG7 = $17
|
||||
ARG9 = $19
|
||||
ARG10 = $1a
|
||||
ARG11 = $1b
|
||||
ARG12 = $1c
|
||||
ARG13 = $1d
|
||||
ARG14 = $1e
|
||||
ARG15 = $1f
|
||||
|
||||
.include "io_W65C22.asm6502"
|
||||
.include "utility.asm6502"
|
||||
|
||||
; RETURN VALUE
|
||||
; in a
|
||||
|
||||
IO1 = $6000
|
||||
IO2 = $7000
|
||||
|
||||
; struct method
|
||||
.org $6000
|
||||
VIA1: .tag VIA_Pins
|
||||
.org $7000
|
||||
VIA2: .tag VIA_Pins
|
||||
|
||||
; IO-1
|
||||
PB1 = $6000
|
||||
PA1 = $6001
|
||||
DDRB1 = $6002
|
||||
DDRA1 = $6003
|
||||
T1L1 = $6004
|
||||
T1H1 = $6005
|
||||
; IO-2
|
||||
PB2 = $7000
|
||||
PA2 = $7001
|
||||
DDRB2 = $7002
|
||||
DDRA2 = $7003
|
||||
T1L2 = $7004
|
||||
T1H2 = $7005
|
||||
ACR2 = $700b
|
||||
PCR2 = $700c
|
||||
IFR2 = $700d
|
||||
IER2 = $700e
|
||||
|
||||
|
||||
.endif ; include guard
|
58
test.s65
Normal file
58
test.s65
Normal file
@ -0,0 +1,58 @@
|
||||
.include "system/system.asm6502"
|
||||
.segment "CODE"
|
||||
|
||||
;********************************************************************************
|
||||
; Interrupts
|
||||
;********************************************************************************
|
||||
nmi:
|
||||
rti
|
||||
irq:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
nop
|
||||
rti
|
||||
|
||||
;********************************************************************************
|
||||
; Reset sequence
|
||||
;********************************************************************************
|
||||
reset:
|
||||
sei
|
||||
; setup io2 bank a 1-3
|
||||
lda #%11111111
|
||||
sta IO1 + IO_DDRA
|
||||
|
||||
@loop:
|
||||
lda #%00000000
|
||||
sta IO1 + IO_RANH
|
||||
.repeat 3
|
||||
nop
|
||||
.endrepeat
|
||||
lda #%11111111
|
||||
sta IO1 + IO_RANH
|
||||
.repeat 5
|
||||
nop
|
||||
.endrepeat
|
||||
bra @loop
|
||||
|
||||
;********************************************************************************
|
||||
; reset vector
|
||||
;********************************************************************************
|
||||
.segment "RESET_VECTOR"
|
||||
.word nmi
|
||||
.word reset
|
||||
.word irq
|
||||
|
23
utility.s65
Normal file
23
utility.s65
Normal file
@ -0,0 +1,23 @@
|
||||
.ifndef INCLUDE_UTILITY
|
||||
INCLUDE_UTILITY = 1
|
||||
|
||||
.macpack longbranch ; jeq, jge...
|
||||
|
||||
;********************************************************************************
|
||||
; @macro Update a byte in memory using a mask
|
||||
; @param orignal Address of the byte to update
|
||||
; @param new New value
|
||||
; @param mask Mask of the bits to affect by the new value
|
||||
; @details
|
||||
; xor new with original -> only bits that need to flip are 1
|
||||
; and result with mask -> only selected bits that need to flip stay 1
|
||||
; xor result with original -> flips selected bits
|
||||
;********************************************************************************
|
||||
.macro UT_update_with_mask original,new,mask
|
||||
lda #new
|
||||
eor original
|
||||
and #mask
|
||||
eor original
|
||||
sta original
|
||||
.endmacro
|
||||
.endif
|
Loading…
Reference in New Issue
Block a user