Skip to content
  • Unwatch
    Notifications
  • Fork

/vectron_64

Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
375 lines (316 sloc) 6.42 KB
;;;;
; Operating system for a custom 6502 computer.
; Nick Bild - nick.bild@gmail.com
; https://github.com/nickbild/6502_os
;
; Reserved memory:
; $0000 - LCD enable
; $0001 - Unused -- read it to disable any IC (except RAM).
; $0002 - Current LCD cursor position.
; $0003 - Flag to indicate if next scan code should be skipped.
; $0100-$01FF - 6502 stack
; $7FBE-$7FBF - Temporary location for LCD data manipulation.
; $7FC0-$7FFF - Data to write to LCD.
; Each character (16 x 2 lines) is represented by
; 2 consecutive bytes (4-bit mode).
; Most sig. 4 bits are for LCD data.
; Least sig. 4 bits - only bit 3 used (tied to RS pin).
;
; $FFF8 - Clock keyboard shift register and enable line buffer.
; $FFF9 - Reset binary counter (counts bits received from PS/2 keyboard packets).
;
; $FFFA - NMI IRQ Vector
; $FFFB - NMI IRQ Vector
; $FFFC - Reset Vector - Stores start address of this ROM.
; $FFFD - Reset Vector
; $FFFE - IRQ Vector - Keyboard ISR address.
; $FFFF - IRQ Vector
;;;;
processor 6502
; Named variables in RAM.
ORG $0002
CursorPosition
.byte #$00
SkipNextScanCodeFlag
.byte #$00
; Start at beginning of ROM.
StartExe ORG $8000
sei
jsr InitLcd
jsr ZeroLCDRam
jsr ResetKeyboardCounter
; Initialize LCD cursor position to 0.
lda #$00
sta CursorPosition
; Do not skip the first scan code.
lda #$00
sta SkipNextScanCodeFlag
cli
MainLoop
jmp MainLoop
;;;
; Long Delay
;;;
Delay ldx #$FF
DelayLoop1 ldy #$FF
DelayLoop2 dey
bne DelayLoop2
dex
bne DelayLoop1
rts
;;;
; Short Delay
;;;
DelayShort ldx #$80
DelayShortLoop1 dex
bne DelayShortLoop1
rts
;;;
; Send high pulse to LCD enable pin.
;;;
LcdCePulse sta $01
jsr DelayShort
sta $00
jsr DelayShort
sta $01
jsr DelayShort
rts
;;;
; LCD initialization sequence.
;;;
InitLcd jsr Delay
lda #$30 ; 00110000 - data 0011, RS 0
jsr LcdCePulse
jsr Delay
lda #$30
jsr LcdCePulse
jsr Delay
lda #$30
jsr LcdCePulse
lda #$20
jsr LcdCePulse
jsr DelayShort
; Set 8 bit, 2 line, 5x8.
lda #$20
jsr LcdCePulse
lda #$80
jsr LcdCePulse
; Display on.
lda #$00
jsr LcdCePulse
lda #$C0
jsr LcdCePulse
; Clear display.
lda #$00
jsr LcdCePulse
lda #$10
jsr LcdCePulse
jsr Delay
; Entry mode.
lda #$00
jsr LcdCePulse
lda #$60
jsr LcdCePulse
rts
;;;
; Write LCD-reserved RAM addresses to LCD.
;;;
WriteLCD lda #$80 ; Line 1 : 1000 (line1) 0000 (RS 0)
jsr LcdCePulse
lda #$00 ; Position 0 : 0000 (position 0) 0000 (RS 0)
jsr LcdCePulse
ldy #$00
Line1Loop lda $7FC0,y
jsr LcdCePulse
iny
cpy #$20
bcc Line1Loop
lda #$C0 ; Line 2 : 1100 (line2) 0000 (RS 0)
jsr LcdCePulse
lda #$00 ; Position 0 : 0000 (position 0) 0000 (RS 0)
jsr LcdCePulse
ldy #$00
Line2Loop lda $7FE0,y
jsr LcdCePulse
iny
cpy #$20
bcc Line2Loop
rts
;;;
; Zero out LCD reserved RAM (set all positions to space character).
;;;
ZeroLCDRam ldx #$00
ZeroLoop lda #$28
sta $7FC0,x
inx
lda #$08
sta $7FC0,x
inx
cpx #$40
bcc ZeroLoop
rts
;;;
; Reset binary counter tracking receipt of complete packets from keyboard.
;;;
ResetKeyboardCounter
lda $0001
lda $FFF9
lda $0001
rts
;;;
; Read in all of the initialization data from the keyboard and discard it.
;;;
SkipKeyboardInit
ldy #$00
KBInitLoop jsr ResetKeyboardCounter
jsr DelayShort
iny
cpy #$20
bcc KBInitLoop
rts
;;;
; Keyboard Interrupt Service Routine.
;;;
KbIsr
pha
.byte #$DA ; phx - mnemonic unknown to DASM.
; Is this scan code flagged to be skipped?
ldx SkipNextScanCodeFlag
cpx #$01
beq SkipScanCodeAndResetSkip
; Display shift register contents on output pins,
; and enable line buffer.
; Read shift register contents into accumulator.
lda $FFF8
; Skip key up scan codes.
; Remeber to skip the next scan code after them.
cmp #$F0
bne DoNotSkipScanCode
ldx #$01
stx SkipNextScanCodeFlag
jmp SkipScanCode
DoNotSkipScanCode
; Convert scan code into LCD code.
sbc #$14
tax
lda ScanCodeLookup,x
; Store data in memory location read by LCD.
sta $7FBE
sta $7FBF
; Make sure RS (bit 3) is set to 1.
lda #$0F
ora $7FBE
; If CursorPosition >= 64, reset it to 0.
ldx CursorPosition
cpx #$40
bcc CursorPositionLessThan32
ldx #$00
stx CursorPosition
CursorPositionLessThan32
ldx CursorPosition
sta $7FC0,x
inc CursorPosition
; Move least sig. nibble to most sig. position, then make sure RS is 1.
rol $7FBF
rol $7FBF
rol $7FBF
rol $7FBF
lda #$0F
ora $7FBF
ldx CursorPosition
sta $7FC0,x
inc CursorPosition
jsr WriteLCD
SkipScanCodeAndResetSkip
; Do not skip the next scan code.
ldx #$00
stx SkipNextScanCodeFlag
; Finished ISR, reset binary counter.
SkipScanCode
lda $FFF9
lda $0001
.byte #$FA ; plx
pla
rti
; PS/2 Code Set 2 Scan Code Lookup Table
; Subtract $14 from scan code to determine
; byte offset into this table.
; Value at lookup location is character
; LCD data corresponding to scan code.
ScanCodeLookup
.byte #$51 ; Q
.byte #$31 ; 1
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$5A ; Z
.byte #$53 ; S
.byte #$41 ; A
.byte #$57 ; W
.byte #$32 ; 2
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$43 ; C
.byte #$58 ; X
.byte #$44 ; D
.byte #$45 ; E
.byte #$34 ; 4
.byte #$33 ; 3
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; <space>
.byte #$56 ; V
.byte #$46 ; F
.byte #$54 ; T
.byte #$52 ; R
.byte #$35 ; 5
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$4E ; N
.byte #$42 ; B
.byte #$48 ; H
.byte #$47 ; G
.byte #$59 ; Y
.byte #$36 ; 6
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$4d ; M
.byte #$4a ; J
.byte #$55 ; U
.byte #$37 ; 7
.byte #$38 ; 8
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$2C ; ,
.byte #$4B ; K
.byte #$49 ; I
.byte #$4F ; O
.byte #$30 ; 0
.byte #$39 ; 9
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$2E ; .
.byte #$2F ; /
.byte #$4C ; L
.byte #$3B ; ;
.byte #$50 ; P
.byte #$2D ; -
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$27 ; '
.byte #$20 ; unused
.byte #$5B ; [
.byte #$3D ; =
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; unused
.byte #$20 ; <enter>
; Store the location of key program sections.
ORG $FFFC
ResetVector
.word StartExe ; Start of execution.
IrqVector
.word KbIsr ; Interrupt service routine.
You can’t perform that action at this time.