diff --git a/.gitignore b/.gitignore
index 9fe2c9e..97dc189 100755
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ hardware/6502-backups
hardware/_autosave-6502.kicad_sch
hardware/#auto_saved_files#
_autosave*
+msbasic
diff --git a/README.md b/README.md
index ec6ae05..bd8a3c0 100755
--- a/README.md
+++ b/README.md
@@ -2,13 +2,13 @@ ABNielsen.com 6502 Single Board Computer R1
This is a 6502-based complete single board computer intended to help during the global IC shortage. Why use new chips when you can reuse scrap?
-Complete hardware overview of R1:
+Complete hardware overview of R1:
-Video about the wireless bootloader:
+Video about the wireless bootloader:
@@ -25,12 +25,20 @@ Build instructions:
1) Send gerber files from /hardware to your favorite board house
2) Build the project using assemble.sh - this will also try to burn the main ROM using Minipro. Dependencies: [CC65] (https://github.com/cc65/cc65) and a way to burn the ROM's.
3) Source the IC's - the spirit of this project is to contribute as little as possible to the global IC shortage and get used chips locally or from Ebay/AliExpress/etc.
-4) Burn the ROMs. I use a TL866II Plus variant for the actual ROMs.
+4) Burn the ROMs. I use a TL866II Plus variant for the actual ROMs.
5) Solder away
-6) For the PS/2-keyboard I use Ben Eater's (a.k.a. Dieter Müller's) interface: https://www.reddit.com/r/beneater/comments/mjeilv/keyboard_interface_diagram/
+6) For the PS/2-keyboard I use the 6522's Shift Register, PB6, and a 74xx74 flip flop. See my R1 Hardware overview at 7:46: https://youtu.be/w5cA64xof2I?t=466 This will hardware-wise be included on the next build.
7) Enjoy!
Optional:
Setup SSH keys with a Raspberry Pi, connect an nRF24L01+ compatible module to it and compile the wireless bootloader code in /software_linux
+Also optional:
+Microsoft BASIC can be enabled by cloning the msbasic Github repo into the same folder you cloned this repo.
+git clone https://github.com/mist64/msbasic.git
+Then uncomment ;BASIC := 1 (Remove the ";") and run assemble.sh - this will let you run BASIC by pressing F4.
+To change settings for BASIC, values can be changed in defines_abn6502.s
+
+Also, please note that the current code assumes VRAM starts at $0800 rather than the default $2000 in the schematic - resistors will have pads for configuring in the next build, but for now it requires jumpers.
+
License: Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) https://creativecommons.org/licenses/by-nc/4.0/
diff --git a/abn6502rom.s b/abn6502rom.s
index 87803f7..e0de9d3 100755
--- a/abn6502rom.s
+++ b/abn6502rom.s
@@ -1,7 +1,12 @@
.feature string_escapes ; Allow c-style string escapes when using ca65
.feature org_per_seg
-DEBUG = 1
+.feature c_comments
+
+.export main, kb_rptr, PRIMM, printk, printbyte, wkey, PORTB, TIMEOUT,exitirq, printa, newline, setpulses, scrp, scwp, simpledelay, selectbaudrate, MILLISH,resetkb, clrscn,checkkeyboard, kb_buffer, MONRDKEY,CRSRPNT, t2irqreg1, MILLIS
+
+;BASIC := 1 ; 1 if BASIC is enabled
+;DEBUG = 1
PORTB = $6000 ; PB0: SCK/SCL, PB1: RF CS, PB2: RF CE, PB3: SDA, PB4,PB5: MISO ,PB6: PS/2 Clock In, PB7: MOSI/T1 Out (Tape drive output)
PORTA = $6001
DDRB = $6002
@@ -20,16 +25,7 @@ IER = $600E ; [7:0] S/C Tl T2 CBl CB2 SR CA1 CA2
PORTANHS = $600F
CTRL = $5000
-TIMEOUT = 7998 ; Should be around 4ms
-
-kb_wptr = $0000
-kb_rptr = $0001
-kb_flags = $0002
-kb_last = $0004
-scwp = $0005
-scrp = $0006
-kbshift = $07
-kbbit = $09 ; Used to count bits
+TIMEOUT = 7998 ; Should be around 2ms
RELEASE = %00000001
SHIFT = %00000010
@@ -39,8 +35,16 @@ CRSRF = %10000000
KTIMEOUT= %00100000
DBGFLAG = %00010000
-kb_buffer = $0200 ; 256-byte kb buffer 0200-02ff
-scbuf = $0300 ; Scan code buffer
+kb_buffer = $0200 ; 128-byte kb buffer 0200-0280
+scbuf = $0280 ; Scan code buffer
+USERLANDH = $03 ; RAM page userland code starts
+
+; Screen constants
+SCREENSTARTH = $08 ; Change this to the page your Video RAM starts! (VRAM at $0800 requires a few jumpers to change from the default $2000 - this will change in the next build of R1)
+SCREENSTARTL = $4c ; Top left of screen - may differ between VGA screens
+LINESTART = $0c
+LINEEND = $3E
+NUMLINES = 28
;Custom keyboard mappings
DN_ARR_KEY = $F3
@@ -57,68 +61,91 @@ F11_KEY = $EB
F10_KEY = $EA
F9_KEY = $E9
-; Tape vars
-CBIT = $45
-PULSES = $49
-TAPEFLAGS = $15
-PULSESL = $16 ; Config variable if we do something other than KCS
-PULSESH = $17 ; ^^
-KCS300PL = 4 ; Kansas City Standard takes 4 1200 Hz pulses for a 0
-KCS300PH = 8 ; and 8 2400Hz pulses for a 1
-RXBYTE = $14
-NRZBYTE = $0E
-onesinarow = $e4
-plzpnt = $e2
-plsperiod = $d8
+movedfromzp = scbuf+8
+brkcnt = movedfromzp
+RF_STS = movedfromzp+1
+MONCNT = movedfromzp+2
+TMP = movedfromzp+3;
+TMP2 = movedfromzp+4
+RF_ERR = movedfromzp+5
+ERRS = movedfromzp+6
+TMP3 = movedfromzp+7
-;If using port A instead of the shift register then change this to PORTA
-KEYBOARD = $0C
+ABUF = movedfromzp+8 ; 8 bytes
+;to $2F
+;ABUF = $28
+TMP4 = movedfromzp+16
+SVCSR = movedfromzp+17
+;+1
-DEBUGP = $19
-DEBUGPH = $1A
-CRSRT = $1B
-CRSRCHR = $1C
-RF_ERR = $1D
-ERRS = $1F
+zp_s = $f8
+kb_wptr = zp_s
+kb_rptr = zp_s+1
+kb_flags = zp_s+2
+kb_last = zp_s+3
+scwp = zp_s+4
+scrp = zp_s+5
+outb = zp_s+6
+inb = zp_s+7
-
-LASTKB = $3E
-LASTKBH = $3F
-MILLIS = $40
-MILLISH = $41
-
-HXH = $44
-MONCNT = $46
-
-SLB = $47 ; Size low byte
-SHB = $48
-SVP = $42 ; Save pointer
-SVPH =$43
-
-TMP = $50;
-TMP2 = $51
-
-CRSRPNT = $52
+zp_s2 = $e0
+MONH = zp_s2+1
+MONL = zp_s2
+KEYBOARD = zp_s2+2
+SPITMP = zp_s2+3
+MILLIS = zp_s2+4
+MILLISH = zp_s2+5
+CRSRPNT = zp_s2+6
CRSRPNT2 = CRSRPNT+1
-SCREENSTARTH = $20
-SCREENSTARTL = $CD ; Top left of screen - may differ between VGA screens
-LINESTART = 13
-LINEEND = 61
-NUMLINES = 29
+zp_s3 = $e8
+SVP = zp_s3 ; Save pointer
+SVPH =zp_s3+1
+HXH = zp_s3+2
+SLB = zp_s3+3 ; Size low byte
+SHB = zp_s3+4
+CRSRCHR = zp_s3+5
+PRIMMZP1 = zp_s3+6
+PRIMMZP2 = zp_s3+7
-MONH = $59
-MONL = $58
-ABUF = $5A
-;to $61
+zp_s4 = $f0
+t2irqreg1 = zp_s4
+t2irqreg2 = zp_s4+1
+USERLANDP = zp_s4+2 ; JMP Pointer
+USERLANDPH = zp_s4+3
-outb = $56
-inb = $57
+DEBUGP = zp_s4+4
+DEBUGPH = zp_s4+5
+
+zp_s5 = $d8
+SCRLPNT = zp_s5 ; also +1
+SCRLPNT2 = zp_s5+2 ; also +3
+
+; Tape constants
+KCS300PL = 4 ; Kansas City Standard takes 4 1200 Hz pulses for a 0
+KCS300PH = 8 ; and 8 2400Hz pulses for a 1
+; Tape vars
+TAPEVARS = movedfromzp+32
+CBIT = TAPEVARS
+RXBYTE = TAPEVARS+1
+TAPEFLAGS = TAPEVARS+2
+PULSES = TAPEVARS+3
+NRZBYTE = TAPEVARS+4
+onesinarow = TAPEVARS+5
+plsperiod = TAPEVARS+6 ; also +7
+PULSESL = TAPEVARS+8 ; Config variable if we do something other than KCS
+PULSESH = TAPEVARS+9 ; ^^
+plzpnt = zp_s4+6 ; also +7
+CT1L = TAPEVARS+10
+CT1H = TAPEVARS+11
+LT1L = TAPEVARS+12
+LT1H = TAPEVARS+13
+LOADTIMEOUT = TAPEVARS+14
-RF_STS = $68
; CE = $69
-MSGBUF = $90
-;+32bytes == To $AF
+MSGBUF = TAPEVARS+15
+;+32bytes == To
+RF24REGS = MSGBUF+32
uservia = PORTB
mosi = %10000000
@@ -137,39 +164,43 @@ SCL_INV = $FE
cld ; Because you never know
;CLEAR RAM
- sei
+ sei ; In case this was not a hw reset
ldx #$0
- clearram:
lda #0
+ clearzp:
sta $00,x
inx
- bne clearram
+ bne clearzp
;Assumes x and A are 0 from above
clearstack:
sta $0100,x
inx
bne clearstack
+ clearp2:
+ sta $0200,x
+ inx
+ bne clearp2
+ clearp3:
+ sta $0300,x
+ inx
+ bne clearp3
+
+ ldx #$FF
+ txs
- lda #8
- sta kbbit
- lda #10
- sta kbshift
noclear: ;Soft reset point - BRK
- lda #$03 ;
- sta CTRL ; Enable video, bank 0
- ;debug, ca1 disabled
-
jsr clrscn
+ lda #$F1
+ sta CTRL
+
lda #SCREENSTARTL
sta CRSRPNT
lda #SCREENSTARTH
sta CRSRPNT2
- tax
- txs
;lda #2
;sta PORTB ; Set SPI CS high
@@ -181,25 +212,20 @@ noclear: ;Soft reset point - BRK
sta kb_rptr ; Init keyboard pointers before enabling interrupts
sta kb_wptr
sta RF_ERR ; Reset RF error
- sta $1A
- ;cli
-
+ ;cli ; Enable interrupts
lda #%11000000 ; Set T1
sta IER
LDA #%01000000
STA ACR ; T1 continuous, PB7 disabled
- ;cli ; Enable interrupts Let's do this when KB is ready
+
LDA #TIMEOUT
STA T1CH ; Set high byte of timer1 counter
- lda #01
- sta $5000
-
ldx #$10 ; Read first tx addr byte = should be default, if not then no module connected
+ stx kb_flags ; Debug enabled
jsr rw_reg
- sta $0f
cmp #$E7
bne norfmodule
jsr initrf24
@@ -214,40 +240,15 @@ message: .asciiz "GREETINGS PROFESSOR FALKEN.", "\n", "SHALL WE PLAY A GAME?", "
welcomedone:
;Let's enable the keyboard
-
-LDA #%01000000
-STA ACR ; T1 continuous - disable Shift register
-LDA #%01101100
-STA ACR ; T1 continuous, T2 count, PB7 disabled, Shift In External
-lda #5
-sta T2CL
-lda #%11100100 ; Set T1 + T2 + SR
-sta IER
-lda #0
-sta SR1
-sta T2CH
-
-jsr simpledelay
-
+lda #$91
+sta CTRL
+jsr resetkb
+lda #1
+sta CTRL
cli
main: ; loop
-
-;Debug
-LDA LASTKB
-sta ERRS
-
-lda MILLIS ; Don't do RF if key just pressed
-cmp LASTKB
-lda MILLISH
-sbc LASTKBH
-bcc skiprf
-
-notyet:
-
lda RF_ERR
-;DEBUG
-;lda #1
bne skiprf
bit ACR ; If ACR.7 is set then we can't use SPI since MOSI is outputting TM1.
bpl rfstuff
@@ -255,9 +256,7 @@ skiprf:
jmp nomsg
rfstuff:
;jsr readrf24regs ; Debug - we can also just do an rf_nop to read rf24 status (RF_STS)
-
jsr rf_nop ; Not debug
-
;If msg received, put it in MSGBUF
bit RF_STS
bvs gtgm ; Check irq
@@ -270,18 +269,18 @@ jmp nomsg; No msg received
gtgm:
jsr getmessage
-lda $90
+lda MSGBUF
bne datapacket ; Check for control message
-lda $91
+lda MSGBUF+1
cmp #$31 ; Trust but verify
beq ctrlmsg
jsr initrf24 ; Junk package. Reset radio.
jmp nomsg
ctrlmsg:
-lda $92
+lda MSGBUF+2
sta SLB ; Data size low byte
-lda $93
+lda MSGBUF+3
sta SHB ; Data size high byte
jsr PRIMM
.asciiz "Receiving $"
@@ -294,24 +293,22 @@ sta SHB ; Data size high byte
inc SHB
lda #0
sta SVP
- lda #4
- sta SVPH ; Save pointer starts at $0400
+ lda #USERLANDH
+ sta SVPH ; Save pointer starts at #USERLANDH
jmp main
datapacket:
getmsg:
-inc $d2 ; Debug
+;inc $d2 ; Debug
;lda $90
;cmp #1
;bne nextpacket ; Data package with ID > 1
-
-
nextpacket:
ldx #2
fetchpacket:
-lda $90,x
+lda MSGBUF,x
ldy #0
sta (SVP),y
inc SVP
@@ -341,69 +338,42 @@ bne fetchpacket
jmp main
txdone:
- lda #4
- sta $31
+ lda #USERLANDH
+ sta USERLANDPH
lda #0
sta SLB
sta SHB
sta SVPH ; Reset
sta kb_rptr ; Reset the keyboard pointers here.
sta kb_wptr
- sta $30
+ sta USERLANDP
jsr PRIMM
- .asciiz "\nData loaded into RAM at $0400. \nPress F5 or type \"run\" to start executing at $0400. \n"
+ .asciiz "\nData loaded into RAM at $"
+ LDA #USERLANDH
+ jsr printbyte
+ ;lda #USERLAND
+ ;jsr printbyte
+ jsr PRIMM
+ .asciiz "00. \nPress F5 or type \"run\" to start executing. \n"
nomsg:
- bit CRSRT
- bmi isneg
- lda kb_flags
- and #$7f
- sta kb_flags ; Reset flip
- sec
- bcs skippedcursor ; BRA
+ jsr checkcursor
- isneg:
- bit kb_flags ; Same as last?
- bpl flip
- bmi skippedcursor ; We already flipped
-
-flip:
- ldy #0
- lda kb_flags
- eor #CRSR
- ora #CRSRF ; Set flip bit
- sta kb_flags
- bit kb_flags
- bvs cursoroff
- cursoron:
- lda #'_'
- sta (CRSRPNT),y
- bne cursordone ; BRA
- cursoroff:
- lda #0
- sta $fa
- ; sta SR1
- lda CRSRCHR
- sta (CRSRPNT),y
- cursordone:
- skippedcursor:
-
-
-.if DEBUG
+.ifdef DEBUG
lda kb_flags
and #DBGFLAG
beq nodebug
lda CRSRPNT ; Save cursor..
- sta $54
+ sta SVCSR
pha
lda CRSRPNT2
- sta $55
+ sta SVCSR+1
pha
- LDA #$4e ; Print debug in bottom right corner of screen
+ LDA #$65 ; Print debug in top right corner of screen
sta CRSRPNT
- lda #$27
+ lda #$08
sta CRSRPNT2
;lda #$6f
@@ -418,9 +388,9 @@ beq nodebug
lda ERRS
jsr printbyte
inc CRSRPNT ; Space
- lda $55
+ lda SVCSR+1
jsr printbyte
- lda $54
+ lda SVCSR
jsr printbyte
inc CRSRPNT ; Space
lda MILLISH
@@ -432,9 +402,9 @@ beq nodebug
lda IFR
jsr printbyte
inc CRSRPNT ; Space
- lda kbshift
- jsr printbyte
- inc CRSRPNT ; Space
+ ;lda kbshift
+ ;jsr printbyte
+ ;inc CRSRPNT ; Space
pla
sta CRSRPNT2
@@ -450,21 +420,29 @@ bne key_pressed
jmp main
checkkeyboard: ; Returns Z flag if nothing ready, not Z if something, kb_rptr in x
- sei ; Instead of disabling IRQ we might want to use the re-compare method.
+ ;sei ; Instead of disabling IRQ we might want to use the re-compare method.
;Load to x, then do the compare, then check if changed. Redo if changed. Idea for later..
- ldx kb_rptr
- cpx kb_wptr
- bne nosc
- lda scrp
- cmp scwp
- cli
- beq nosc
+ lda #0
+ ldx scrp
+ cpx scwp
+ beq nonewsc
+ rescan:
jsr keyboard_handling
- nosc:
- sei
+ lda #0
+ ldx scrp
+ cpx scwp
+ bne rescan
+ cpx #7 ; Top of buffer
+ bcc nonewsc
+ sta scrp ; 0
+ sta scwp ; 0
+ nonewsc:
ldx kb_rptr
cpx kb_wptr
- cli
+ ;bne gotkey
+ ;sta kb_rptr
+ ;sta kb_wptr
+ gotkey:
rts
copyscreen:
@@ -485,7 +463,7 @@ checkkeyboard: ; Returns Z flag if nothing ready, not Z if something, kb_rptr in
lda #0
sta SVP
sta SLB
- lda #$20
+ lda #SCREENSTARTH
sta SVPH
lda #$38
sta SHB
@@ -506,7 +484,7 @@ sta SVP
sta SLB
lda #$38
sta SVPH
-lda #$20
+lda #SCREENSTARTH
sta SHB
ldx #8
jsr copyscreen
@@ -521,6 +499,8 @@ key_pressed:
lda kb_buffer, x
cmp #$0a ; enter - go new line
beq enter_pressed
+ cmp #$0d
+ beq enter_pressed
cmp #$1b ; escape - clear display
beq esc
cmp #$08
@@ -695,10 +675,8 @@ err:
clkbptr:
; Clear keyboard pointers if this is the end of message
inc kb_rptr
- sei
lda kb_rptr
cmp kb_wptr
- cli
bne notdone
eom:
; lda (CRSRPNT),y ; Save new char under cursor ; Here or in err:?
@@ -710,7 +688,7 @@ eom:
jmp main
run:
- jmp ($0030)
+ jmp (USERLANDP)
esc_pressed:
jsr clrscn
@@ -721,21 +699,7 @@ esc_pressed:
jmp clkbptr
backspace_pressed:
- ldy #0
- lda CRSRCHR
- sta (CRSRPNT),y
-normcrsr:
- dec CRSRPNT
- lda CRSRPNT
- cmp #255
- bne notunder
- dec CRSRPNT2
- notunder:
- lda #' '
- sta (CRSRPNT),y
- dec kb_rptr
- dec kb_wptr
- dec kb_wptr
+ jsr rubout
jmp main
f1_pressed:
@@ -746,18 +710,38 @@ f1_pressed:
jmp monmon
f2_pressed:
+ lda #$10
+ sta SVPH
+ lda #$01
+ sta SHB
+ lda #0
+ sta SVP
+ sta SLB
+ inc SLB
jsr savetotape
jmp eom
f3_pressed:
+ lda #>RAMSTART2
+ sta SVPH
+ lda #main
sta $105,x
jmp exitirq
@@ -1257,6 +1508,8 @@ irq:
txa
pha ; Save X
+ tya
+ pha ; Save y
lda #%00100000 ; We need T2 to fire super fast, so we check it first.;
and IFR
@@ -1266,7 +1519,7 @@ lda IER ; Priority to ca1 but only if enabled
and IFR
tax
and #2 ; CA1
-bne ca1_irq
+bne ca1_irq ; Disabled so it doesn't mess up things...
;Alt approach
@@ -1290,6 +1543,7 @@ txa ; IER AND IFR
; bvs t1_irq
tsx
+ inx
lda $0103,x ; Pull status register off stack and check break flag
and #$10
bne hitbrk
@@ -1332,6 +1586,7 @@ txa ; IER AND IFR
lda #1 ; Mask = LSB
sta CBIT
here: ; New bit
+ ldy #0
and (SVP),y ; Assuming y is 0
beq send0 ; Bit was 0
send1:
@@ -1355,34 +1610,29 @@ there:
asl CBIT ;Next bit
bne notdoneyet
inc SVP ; Increment pointer = New byte
- bne notdoneyet
+ bne arewedone
inc SVPH ; High byte
- lda SVPH
- cmp SHB ; Maybe not the right variable to use?
- bcc notdoneyet
+ ;lda SVPH
+ ;cmp SHB ; Maybe not the right variable to use?
+ ;bcc notdoneyet
+ arewedone:
+ dec SLB
+ bne notdoneyet
+ dec SHB
+ bne notdoneyet
lda ACR
and #$7f
sta ACR
bne t1_irq_exit ; BRAnch always
-
notdoneyet:
-;Manual test on device
-;To output 2400Hz, set the latches first, disable T1 in IER, then enable output on PB7 (Keyboard input will break, reset required)
-;write 6006 9f01
-;write 600e 40
-;write 600b c0
-
gmillis:
- inc CRSRT
- inc CRSRT
+
inc MILLIS
bne t1_irq_exit
inc MILLIS+1
-
+ dec LOADTIMEOUT
t1_irq_exit:
- ; pla
- ; rti
jmp exitirq
; cb1_IRQ:
@@ -1394,12 +1644,11 @@ there:
keyboard_handling: ; SR, not IRQ any longer
- ldx scrp ; Scan code read pointer
lda scbuf, x
+ inc scrp
tax
lda reversebits, x
tax
- inc scrp
; Fall through to scancode -> ascii parsing -> key buffer
@@ -1418,13 +1667,15 @@ keyboard_handling: ; SR, not IRQ any longer
beq shift_up
cmp #$59 ; right shift
beq shift_up
- jmp exit
+ cmp #$14
+ beq ekey_up
+ bne exit
- ekey_up:
- lda kb_flags
- and #%11111011 ; Turn off ecode
- sta kb_flags
- jmp exit
+ ekey_up:
+ lda kb_flags
+ and #%11111011 ; Turn off ecode
+ sta kb_flags
+ jmp exit
shift_up:
lda kb_flags
@@ -1447,11 +1698,13 @@ keyboard_handling: ; SR, not IRQ any longer
beq shift_down
cmp #$E0
beq ekey_down
+ cmp #$14
+ beq ekey_down
- tax
lda kb_flags
and #ECODE
bne ecode_key
+
lda kb_flags
and #SHIFT
bne shifted_key
@@ -1541,10 +1794,10 @@ keyboard_handling: ; SR, not IRQ any longer
keymap_ecode:
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 00-0F
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 10-1F
- .byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED; 20-2F
+ .byte $ED,"^",$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED; 20-2F
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 30-3F
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 40-4F
- .byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 50-5F
+ .byte $ED,$ED,$ED,$ED,$ED,'$',$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 50-5F
.byte "0123456789A",L_ARR_KEY, HOME_KEY, "DEF" ; 60-6F
.byte "01",DN_ARR_KEY,"3",R_ARR_KEY, UP_ARR_KEY, "6789",PGDN_KEY,"B",PRTSC_KEY, PGUP_KEY,"EF" ; 70-7F $F6 = PGUP(7D), $F5 = PGDOWN(7A), $F4 = UP Arr.(75), Down arr.(72) = $F3
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; 80-8F $F8 = F7 key
@@ -1556,7 +1809,8 @@ keyboard_handling: ; SR, not IRQ any longer
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; E0-EF
.byte $ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED,$ED ; F0-FF
-
+;This is a table of all reversed bits - for example $0F is $F0 and $AA is $55.
+;We need this to convert the scan code from LSB first to MSB first. The alternative is to rewrite the three tables above -- and I really don't have the patience for that right now.
reversebits:
.byte 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240
.byte 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120
@@ -1588,7 +1842,7 @@ reversebits:
lda PORTB
and #%01011100
- sta $1E ; Save bits not used by SPI
+ sta SPITMP ; Save bits not used by SPI
TXA
@@ -1606,7 +1860,7 @@ reversebits:
bcc spibyte1 ; (2)
ora #mosi ; (2) set MOSI if MSB set
spibyte1:
- ora $1E ; Debug - set preserved port B bits. If interrupts are enabled be careful when using this.
+ ora SPITMP ; Debug - set preserved port B bits. If interrupts are enabled be careful when using this.
sta uservia ; (4) output (MOSI, SCS low, SCLK low)
tya ; (2) set A to 0 (Do it here for delay reasons)
inc uservia ; (6) toggle clock high (SCLK is bit 0)
@@ -1632,17 +1886,23 @@ reversebits:
rts
exitnochange: ; Can jump here from save and load
- lda #0 ; Reset KB pointers
- sta kb_rptr
- sta kb_wptr
- sta scrp
- sta scwp
- jsr newline
+ ;lda #0 ; Reset KB pointers
+ ;sta kb_rptr
+ ;sta kb_wptr
+ ;sta scrp
+ ;sta scwp
+ sec ; Cancel flag
rts
selectbaudrate:
+ sty TMP4
jsr PRIMM
- .asciiz "Press 1 for 300 baud KCS\nPress 2 for 1200 baud KCS \nPress ESC to cancel."
+ .asciiz "Press 1 for 300 baud KCS. Press 2 for 1200 baud.\n"
+ jsr PRIMM
+ .asciiz "Press ESC to cancel.\n"
+ jsr checkbottom
+ ;jsr resetkb
+
waitloop:
jsr wkey
cmp #$31
@@ -1665,43 +1925,38 @@ reversebits:
sta PULSESH
readytosave:
- jsr newline
+ ldy TMP4
+ clc
rts
savetotape:
- lda SVPH
- bne dontset
- lda #$10
- sta SVPH
- dontset:
- lda SHB
- bne dontsetshb
- lda #$11
- sta SHB
- dontsetshb:
jsr PRIMM
.asciiz "Ready to save $"
-
- sec
+ dec SHB
lda SHB
- sbc SVPH
+ ;sbc SVPH
+ jsr printbyte
+ inc SHB
+
+ dec SLB
+ lda SLB
jsr printbyte
-
+ inc SLB
jsr PRIMM
- .asciiz " pages of data starting from address $"
+ .asciiz " bytes of data starting from address $"
lda SVPH
jsr printbyte
lda SVP
jsr printbyte
- jsr newline
+ ;jsr newline
jsr selectbaudrate
jsr PRIMM
- .asciiz "Start rec on tape and press ENTER after leader. Press ESC to cancel..\n"
+ .asciiz "\nStart rec on tape and press ENTER after leader. Press ESC to cancel..\n"
jsr setpulses
@@ -1727,7 +1982,7 @@ reversebits:
cmp scwp
bne waitfor2
- lda #1 ; Reset KB pointers
+ lda #0 ; Reset KB pointers
sta kb_rptr
sta kb_wptr
sta scrp
@@ -1777,14 +2032,54 @@ reversebits:
lda #0 ; Reset KB pointers
sta kb_rptr
sta kb_wptr
- sta SVPH
- sta SHB
rts
+ basicsavetotape:
+ .ifdef BASIC
+
+ lda #RAMSTART2
+ sta SVPH
+ sec
+ ;lda VARTAB
+ .byte $A5 ; Explicitly using ZP addressing LDA to kill warning
+ .byte VARTAB
+ sbc #RAMSTART2
+ sta SHB
+ inc SHB
+ jsr savetotape
+ .endif
+ rts
+
+ basicloadfromtape:
+ .ifdef BASIC
+ lda #RAMSTART2
+ sta SVPH
+ jsr loadfromtape
+ lda SVP
+ .byte $85
+ .byte VARTAB
+ lda SVPH
+ .byte $85
+ .byte VARTAB+1
+ .endif
+ rts
+
+ ; FIX HARDCODED ADDRESSES HERE!
loadfromtape:
jsr PRIMM
- .asciiz "Loading from tape.\n\n"
+ .asciiz "Loading from tape.\n"
jsr selectbaudrate
+ bcs statusloop
+
ldx #0
txa
cleardata:
@@ -1792,87 +2087,93 @@ reversebits:
dex
bne cleardata
- lda SVPH ; Check if preloaded save address
- bne gotit10
- lda #$10
- sta SVPH
- lda #0
- sta SVP
- gotit10:
-
- lda #ca1irq
- sta $33
-
lda #$FF
sta T1LL
- lda #$FF
sta T1LH
- ;sta T1CH ; This should reset T1?
+ sta T1CH ; This should reset T1?
sta RXBYTE
; Activate CA1 irq to trigger IRQ
- lda IER
- ora #2 ; CA1 bit
+ lda #$82 ; S+CA1 bit
sta IER
; Receive data in irq
-
lda #0
;stx CBIT
;sta TAPEFLAGS
sta plzpnt
sta PULSES
sta onesinarow
-
-
lda #8
sta CBIT
- sta $0f
-
+ sta LOADTIMEOUT
lda #$32
sta plzpnt+1
-
lda #$ff
sta NRZBYTE
-
- clc ; Catch keyboard release
- lda scwp
- adc #2
- waitfor2x:
- cmp scwp
- bne waitfor2x
- sta scrp
- sta scwp
-
jsr PRIMM
.asciiz "Press play on tape! \n"
-
; Write status here
statusloop:
+ lda LOADTIMEOUT
+ bne noproblem
+ lda TAPEFLAGS
+ and #$20
+ beq timeout
+ lda #3
+ sta LOADTIMEOUT
+ noproblem:
lda TAPEFLAGS
and #$20
beq noleader
jsr PRIMM ;
- .asciiz "Got leader... \n"
- nop
+ .asciiz "Got leader.\n"
lda TAPEFLAGS
and #%11011111 ;
sta TAPEFLAGS
noleader:
- lda scrp
- cmp scwp
- bne exituserland
+ lda SVP
+ cmp #RAMSTART2
+ beq notstarted
+ noz:
+ lda CRSRPNT
+ and #%11000000 ; keep only section bits
+ ora #LINESTART ;
+ sta CRSRPNT
+ ldy #0
+ lda #'$'
+ jsr printfast
+ sec
+ lda SVPH
+ sbc #>RAMSTART2
+ jsr printbyte
+ lda SVP
+ sbc #TIMEOUT
sta T1LH
-
- lda #0
- sta kb_rptr
- sta kb_wptr
- sta scwp
- sta scrp
-
- lda SCREENSTARTL
- sta CRSRPNT
- lda SCREENSTARTH
- sta CRSRPNT2
+ sta T1CH
rts
ca1irq:
- bit PORTA ; Clear IRQ flag
+ bit PORTA ; Clear IRQ flag
inc PULSES
readtime:
ldx T1CH
@@ -1904,15 +2195,15 @@ reversebits:
cpx T1CH
bne readtime
- sta $12 ; T1CL
- stx $13 ; T1CH
+ sta CT1L ; T1CL
+ stx CT1H ; T1CH
sec
- lda $10 ; Last T1CL
- sbc $12 ; Current T1CL
+ lda LT1L ; Last T1CL
+ sbc CT1L ; Current T1CL
sta plsperiod
- lda $11 ; Last T1CH
- sbc $13 ; Current T1CH
+ lda LT1H ; Last T1CH
+ sbc CT1H ; Current T1CH
sta plsperiod+1 ; ResultH
@@ -1964,13 +2255,11 @@ reversebits:
; inc plzpnt+1
donedebug:
-
- stx $11
- lda $12
- sta $10
+ stx LT1H
+ lda CT1L
+ sta LT1L
lda plsperiod+1
-
cmp #6
bcs was0 ; Definitely a 0, skip extra check
@@ -2128,12 +2417,13 @@ reversebits:
savekcs:
lda RXBYTE
rplss:
+ ldy #0
sta (SVP),y
inc SVP
bne samepage
inc SVPH
samepage:
- jsr printbyte
+ ;jsr printbyte
;lda #' '
;jsr printk
lda #8
@@ -2170,6 +2460,7 @@ NOP
bne delay
rts
+/*
i2c_start: ; Let's assume i2c addr is in A and RW bit is in C
rol ; Move address to top bits and RW bit to bit0
sta outb ; Save addr + rw bit
@@ -2287,8 +2578,25 @@ i2c_test:
failed:
rts
+*/
-
+rubout:
+ldy #0
+lda CRSRCHR
+sta (CRSRPNT),y
+normcrsr:
+dec CRSRPNT
+lda CRSRPNT
+cmp #255
+bne notunder
+dec CRSRPNT2
+notunder:
+lda #' '
+sta (CRSRPNT),y
+dec kb_rptr
+dec kb_wptr
+dec kb_wptr
+rts
rf_nop:
lda PORTB
@@ -2357,7 +2665,7 @@ i2c_test:
readrf24:
lda #0 ; Let's read first byte of all registers
jsr rw_reg
- sta $70,x
+ sta RF24REGS,x
dex
bpl readrf24
rts
@@ -2367,7 +2675,7 @@ i2c_test:
ldx #$60 ; Get top of RX fifo length - R_RX_PL_WID
lda #0
jsr rw_reg
- sta $81 ; Overwrite P0 payload length location in mem
+ sta RF24REGS+$11;$81 ; Overwrite P0 payload length location in mem
ldy #0
lda PORTB
@@ -2379,9 +2687,9 @@ i2c_test:
sta RF_STS
bytes:
jsr spibyte
- sta $90, y ;
+ sta MSGBUF, y ;
iny
- cpy $81
+ cpy RF24REGS+$11
bne bytes
lda PORTB
ora #2 ; Set CS high
@@ -2394,27 +2702,29 @@ i2c_test:
; Wait for keypress subroutine -
wkey:
- ; lda kb_rptr
- ; cmp kb_wptr
- ; bne havekey
- ; lda scrp
- ; cmp scwp
- ; beq wkey
- ; getkey:
- ; jsr keyboard_handling
- jsr checkkeyboard
- beq wkey
-
+ jsr checkkeyboard
+ beq wkey
havekey:
- ; lda kb_rptr
- ; cmp kb_wptr
- ; beq nokey
- ; ldx kb_rptr
lda kb_buffer, x
inc kb_rptr
- ;jsr printbyte
- nokey:
rts
+
+ delay20ms:
+ ldx MILLISH
+ lda MILLIS
+ cpx MILLISH
+ bne delay20ms ; In case we hit bad cycle
+ clc
+ adc #5 ; 20ms
+ bcc stallhere
+ inx
+ stallhere:
+ cpx MILLISH
+ bne stallhere
+ cmp MILLIS
+ bne stallhere
+ rts
+
setpulses:
; Here we load some default values if not specified something non-zero
lda PULSESL ; Number of pulses pr lower frequency bit
@@ -2429,6 +2739,32 @@ setpulses:
plss:
rts
+ ; APPLE := 1
+ ; .include "msbasic/defines_apple.s"
+.ifdef BASIC
+ OSI := 1
+ .include "defines_abn6502.s"
+
+ ;CBM2 := 1
+ ;.include "msbasic/defines_cbm2.s"
+
+ ;KIM := 1
+ ;.include "msbasic/defines_kim.s"
+
+ .include "msbasic/msbasic.s"
+ ; lda #LIST
+.else
+.segment "INIT"
+.segment "HEADER"
+.segment "VECTORS"
+.segment "KEYWORDS"
+.segment "ERROR"
+.segment "CODE"
+.segment "CHRGET"
+.segment "EXTRA"
+.segment "DUMMY"
+.endif
+
; Inline printing routine from http://6502.org/source/io/primm.htm
.segment "PRIMM"
.org $ffc8
@@ -2441,14 +2777,14 @@ setpulses:
TSX ; get stack pointer
LDA $0104,X ; get return address low byte (+4 to
; correct pointer)
- STA $BC ; save in page zero
+ STA PRIMMZP1 ; save in page zero
LDA $0105,X ; get return address high byte (+5 to
; correct pointer)
- STA $BD ; save in page zero
+ STA PRIMMZP2 ; save in page zero
LDY #$01 ; set index (+1 to allow for return
; address offset)
PRIM2:
- LDA ($BC),Y ; get byte from string
+ LDA (PRIMMZP1),Y ; get byte from string
BEQ PRIM3 ; exit if null (end of text)
JSR printk ; else display character
@@ -2458,11 +2794,11 @@ setpulses:
PRIM3:
TYA ; copy index
CLC ; clear carry
- ADC $BC ; add string pointer low byte to index
+ ADC PRIMMZP1 ; add string pointer low byte to index
STA $0104,X ; put on stack as return address low byte
; (+4 to correct pointer, X is unchanged)
LDA #$00 ; clear A
- ADC $BD ; add string pointer high byte
+ ADC PRIMMZP2 ; add string pointer high byte
STA $0105,X ; put on stack as return address high byte
; (+5 to correct pointer, X is unchanged)
PLA ; pull value
@@ -2473,10 +2809,7 @@ setpulses:
RTS
-
-.segment "VECTORS"
+.segment "VECTORS6502"
.ORG $fffa
.word nmi,reset,irq
.reloc
-
-.export PRIMM, printk, printbyte, wkey, PORTB, TIMEOUT,exitirq, printa, newline, setpulses, scrp, scwp, simpledelay, selectbaudrate
diff --git a/assemble.sh b/assemble.sh
index 1fc49d5..57ad171 100755
--- a/assemble.sh
+++ b/assemble.sh
@@ -1,13 +1,12 @@
#!/bin/zsh
-ca65 -vv --cpu 6502 -l build/listing.txt -o build/abn6502rom.o abn6502rom.s
+ca65 -vvv --cpu 6502 -l build/listing.txt -o build/abn6502rom.o abn6502rom.s
ca65 crom.s -o build/crom.o
ca65 userland.s --cpu 65c02 -l build/userlisting.txt -o build/userland.o
ld65 -o build/abn6502rom.bin -C memmap.cfg "./build/abn6502rom.o" "./build/crom.o" "./build/userland.o"
-minipro -s -p "SST39SF010A" -w build/abn6502rom.bin
+minipro -s -p "SST39SF010A" -w build/abn6502rom.bin
#minipro -s -p "W27C512@DIP28" -w build/abn6502rom.bin
#The lines below are used to copy the output to a Raspberry Pi and load it
ssh openhabian@openhabiandevice.local killall bootload
scp build/userland.bin openhabian@openhabiandevice.local:./
-
ssh openhabian@openhabiandevice.local bootload -s userland.bin
ssh openhabian@openhabiandevice.local killall bootload
diff --git a/defines_abn6502.s b/defines_abn6502.s
new file mode 100755
index 0000000..a37f7d1
--- /dev/null
+++ b/defines_abn6502.s
@@ -0,0 +1,40 @@
+; configuration
+CONFIG_11A := 1
+
+CONFIG_DATAFLG := 1
+;CONFIG_NULL := 1
+;CONFIG_PRINT_CR := 1 ; print CR when line end reached
+CONFIG_SCRTCH_ORDER := 3
+CONFIG_SMALL := 1
+
+ZP_START1 = $00; $00
+ZP_START2 = $0D ;$0D
+ZP_START3 = $5b; $5B ;10b
+ZP_START4 = $65 ;$65 ; 114b
+
+
+CRLF_1 := $0A
+CRLF_2 := $00
+
+;extra ZP variables
+USR := $000A; $000A
+
+; constants
+STACK_TOP := $80
+SPACE_FOR_GOSUB := $33
+NULL_MAX := $0A
+WIDTH := 46
+WIDTH2 := 46
+
+; memory layout
+RAMSTART2 := $1000
+
+; magic memory locations
+L0200 := $0200
+
+; monitor functions
+;MONRDKEY := $FFEB
+;MONCOUT := printk ;$FFEE
+;MONISCNTC := clcrts;$FFF1
+LOAD := basicloadfromtape ;$FFF4
+SAVE := basicsavetotape ;$FFF7
diff --git a/memmap.cfg b/memmap.cfg
index 494009e..fa53dae 100755
--- a/memmap.cfg
+++ b/memmap.cfg
@@ -1,15 +1,29 @@
MEMORY {
ZP: start = $0, size = $100, type = rw, define = yes;
KBRAM: start = $200, size = $200, define = yes;
- RAM: start = $400, size = $1C00, file = "build/userland.bin";
+ RAM: start = $0300, size = $3700, file = "build/userland.bin";
ROM: start = $8000, size = $8000, file = %O;
CROM: start = $10000, size = $10000, file = "build/crom.bin";
+ DUMMY: start = $0000, size = $00FF, file = "";
}
SEGMENTS {
USERLAND: load = RAM, type = rw;
RODATA: load = ROM, type = ro;
- VECTORS: load = ROM, type = ro, offset = $7FFA;
CROM: load = CROM, type = ro;
+ ZEROPAGE: load = ZP, type = zp;
+
+ HEADER: load = ROM, type = ro;
+ VECTORS: load = ROM, type = ro;
+ KEYWORDS: load = ROM, type = ro;
+ ERROR: load = ROM, type = ro;
+ CODE: load = ROM, type = ro;
+ CHRGET: load = ROM, type = ro;
+ INIT: load = ROM, type = ro;
+ EXTRA: load = ROM, type = ro;
+ DUMMY: load = ROM; # don't include
+
PRIMM: load = ROM, start = $FFC8, type = overwrite;
+ VECTORS6502: load = ROM, start = $FFFA, type = overwrite;
+
}
diff --git a/userland.s b/userland.s
index a01d9b6..7f39c67 100755
--- a/userland.s
+++ b/userland.s
@@ -2,7 +2,7 @@
.feature string_escapes ; Allow c-style string escapes when using ca65
;PRIMM = $FFC8 ; Userland can use ROM subroutines if we tell them where they are. Check listing.txt for current subroutine addresses
;.require "abn6502rom.s"
-.import scrp: zeropage, scwp: zeropage
+.import kb_rptr: zeropage, scrp: zeropage, scwp: zeropage, CRSRPNT: zeropage, MILLIS: zeropage, MILLISH: zeropage
.autoimport + ; Try to import anything unknown from other modules
PORTB = $6000 ; PB0: SCK/SCL, PB1: RF CS, PB2: RF CE, PB3: SDA, PB4,PB5: MISO ,PB6: PS/2 Clock In, PB7: MOSI/T1 Out (Tape drive output)
@@ -21,19 +21,14 @@ PCR = $600C ; [7:5] CB2 Control, [4] CBl Control, [3:1] CA2 Control, [0] CAl Co
IFR = $600D ; [7:0] IRQ Tl T2 CBl CB2 SR CA1 CA2
IER = $600E ; [7:0] S/C Tl T2 CBl CB2 SR CA1 CA2
-MILLIS = $40
-
-SVP = $42 ; Save pointer
-SVPH =$43
-
-TMP = $50;
-TMP2 = $51;
-
-kb_wptr = $00
-kb_rptr = $01
-ESC_KEY = $1b
-
.segment "USERLAND"
+jsr newline
+jsr checkkeyboard
+beq userland
+lda kb_buffer,x
+inc kb_rptr
+jsr printa
+
userland:
lda #$0A
jsr printk
@@ -48,5 +43,35 @@ cOhtwotest:
jsr PRIMM
.asciiz "Hi! Im a CMOS 65C02! \n\n"
exitnow:
+ ;nop ;
+
+ PHA
+ tsx
+ txa
+ jsr printbyte
+ pha
+ TSX
+ txa
+ jsr printbyte
+ pla
+ pla
+
+
+ lda #>main
+ jsr printbyte
+ lda #