initial commit

This commit is contained in:
matthias@rpi 2023-10-26 19:51:20 +02:00
commit 7214f1fe6f
17 changed files with 1123 additions and 0 deletions

4
.dependencies Normal file
View 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
View File

@ -0,0 +1,2 @@
**.bin
**.o

28
Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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