I'm gonna post my code thus far. I'm getting spurts of perfect operation, mixed with periods of constant crashes. I still suspect it's a wiring issue, but if I'm doing something clearly stupid in the code that could cause instability...
Couple things first. I'm still very much in the learning processes with 6502 assembly, so I'm sure I'm doing some stuff the hard way. For instance, other than initializing it, I use no stack instructions, although I'm sure I'd benefit from them. Still getting to that!
While I'm not specifically looking for critique of my methods, I do welcome it.
The one thing that I think might be bad is how much happens inside the ISR for reading the keyboard. the ISR itself is short, but it calls a routine that includes my entire command recognition code. The ACIA is the only interrupt generator, but I suppose it still might be a thing.
My problems are, lock-ups (often), garbage on the screen (less often), and other strange behaviors.
Here's the code: (formating sure doesn't look as nice on here as it does on my editor)
Code:
;WOPRjr OS
.ORG $0000
ACIA_DAT = $5000
ACIA_STA = ACIA_DAT+1
ACIA_CON = ACIA_DAT+3
ACIA_COM = ACIA_DAT+2
STRING_PTR .DS $02 ;pointer to current output message string
STRING_INDEX .DS $01 ;index into input buffer
LINE_CNT .DS $01 ;clear screen line count
CMD_INDEX .DS $02 ;index into command string list
SELECTED_CMD: .DS $02 ;pointer to slected command routine
.ORG $0200
ACIA_RXBUF .DS $100 ;input buffer
.ORG $8000
;command strings
commands:
cmd_empty: .BYTE $0D, $00 ;empty:user pressed enter with no characters
cmd_write: .BYTE "write", $00 ;command to write to memory
cmd_read: .BYTE "read", $00 ;command to read from memory
cmd_test: .BYTE "test", $00 ;command for system self-test
cmd_list_end: .BYTE $FF ;marker for end of list
;list of pointers to command strings
cmd_indices:
empty_index: .WORD cmd_empty
write_index: .WORD cmd_write
read_index: .WORD cmd_read
test_index: .WORD cmd_test
;list of pointers to command routines
cmd_routines:
empty_rtn_ptr: .WORD empty_rtn
write_rtn_ptr: .WORD write_rtn
read_rtn_ptr: .WORD read_rtn
test_rtn_ptr: .WORD test_rtn
no_cmd_rtn_ptr: .WORD no_cmd_rtn
strings:
prompt: .BYTE $0D, $0A, "WOPRjr:" ,$00 ;commandline prompt
empty_msg .BYTE $0D, $0A, $00 ;empty string
message: .BYTE $0D, $0A, "You entered: ", $00 ;input response message
write_msg: .BYTE $0D, $0A, "writing", $00 ;temp write message
read_msg: .BYTE $0D, $0A, "reading", $00 ;temp read message
test_msg: .BYTE $0D, $0A, "testing", $00 ;temp test message
no_cmd_msg: .BYTE $0D, $0A, "unknown command", $00 ;default message for unknown string
start: LDX #$FF
TXS ;Set stack pointer to top of page 1
STZ STRING_INDEX ;initialize string index to 0
JSR uartinit ;initialize ACIA
CLI ;turn on interrupts
LDX #$1A
clr_loop: LDA ACIA_STA ;get ACIA status register
AND #@00010000 ;check Tx buffer empty. 1 is empty, 0 is not empty
BEQ clr_loop ;keep waiting until Tx buffer is empty
LDA #$0A
STA ACIA_DAT
DEX
BNE clr_loop
STA ACIA_DAT
LDA #$0D
STA ACIA_DAT
LDA #<prompt ;get lower byte of prompt message
STA STRING_PTR ;store it in first byte of the string pointer
LDA #>prompt; ;get upper byte of prompt message
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;display prompt
inf_loop: NOP
JMP inf_loop
uartinit:
STZ ACIA_STA ;write a zero to ACIA status regidter to reset chip
LDA #@00011110 ;ACIA control register setting for 1 stop,, 8 data, 9600 baud
STA ACIA_CON ;set ACIA control register
LDA #@00001001 ;no parity, no echo, no Tx IRQ, RTSB LOW, Rx IRQ enabled, DTRB LOW
STA ACIA_COM ;set ACIA command register
RTS
terminal_w: LDY #$00 ;set index to zero
write_loop: LDA ACIA_STA ;get ACIA status register
AND #@00010000 ;check Tx buffer empty. 1 is empty, 0 is not empty
BEQ write_loop ;keep waiting until Tx buffer is empty
LDA (STRING_PTR),Y ;put current character A
BEQ tw_end
STA ACIA_DAT ;send character to ACIA
INY ;move to next character
BNE write_loop ;if not NULL keep going
tw_end: RTS
terminal_r: LDA ACIA_DAT ;get data from ACIA Rx
CMP #$0D ;check if enter was pressed
BEQ process_cmd ;if enter pressed, write string to screen
STA ACIA_DAT
LDX STRING_INDEX ;get string index
STA ACIA_RXBUF,X ;place recieved data into input buffer
INX ;increment it
STX STRING_INDEX ;put incremented version back in memory
RTS
process_cmd:
STZ ACIA_RXBUF,X ;put NULL on end of string
STZ STRING_INDEX ;reset index
JSR parse_cmd ;parse the command
JMP (SELECTED_CMD) ;run routine for selected command
rtn_to_tr: LDA #<prompt ;get lower byte of prompt message
STA STRING_PTR ;store it in first byte of the string pointer
LDA #>prompt; ;get upper byte of prompt message
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;display prompt
RTS
parse_cmd: LDX #$00 ;reset X register
cmd_list_lp: LDA cmd_routines,X ;get address of currently being checked command's routine
STA SELECTED_CMD ;store it in first byte of command routine pointer
LDA cmd_indices,X ;get address of next command string
STA CMD_INDEX ;store it in zero page so it can used as a pointer
INX ;increment x so we can get next byte of command string address
LDA cmd_routines,X ;get second byte of current command routine pointer
STA SELECTED_CMD+1 ;put byte in secdond half of 0 page command routine pointer
LDA cmd_indices,X ;get next byte of command string address
STA CMD_INDEX+1 ;put byte in zero page to form the completed address
INX ;increment X in case we need to check next command string
LDY #$00 ;reset Y register
LDA #$FF ;$FF is marker for end of command string list
CMP (CMD_INDEX),Y ;check if we are at end of command string list
BEQ no_match ;got to no match routine
string_cmp: LDA ACIA_RXBUF,Y ;get current character of input string
CMP (CMD_INDEX),Y ;compare character to same char position in command string being checked
BNE cmd_list_lp ;if no match, try next command string
INY ;incrementY to index of next character in case we need to loop again
CMP #$00 ;check if current character is NULL (end of string)
BNE string_cmp ;if not NULL, check next characters for match
RTS ;if IS NULL, we have a match at this point. Proper routine's pointer will be in SELECTED_CMD
no_match: LDA #<no_cmd_rtn ;get lower byte of Unknown Command rotine's address
STA SELECTED_CMD ;put in first byte of selcected command pointer
LDA #>no_cmd_rtn ;get upper byte
STA SELECTED_CMD+1 ;put in second byte of pointer
RTS ;return. Unknown Command routine is in sELECTED_CMD
empty_rtn: STZ STRING_INDEX ;reset index
LDA #<empty_msg ;get lower byte of canned output response
STA STRING_PTR ;put it in first byte of the string pointer
LDA #>empty_msg ;get upper byte
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;output canned message
JMP rtn_to_tr ;back to command handler
write_rtn: STZ STRING_INDEX ;reset index
LDA #<write_msg ;get lower byte of canned output response
STA STRING_PTR ;put it in first byte of the string pointer
LDA #>write_msg ;get upper byte
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;output canned message
JMP rtn_to_tr ;back to command handler
read_rtn: STZ STRING_INDEX ;reset index
LDA #<read_msg ;get lower byte of canned output response
STA STRING_PTR ;put it in first byte of the string pointer
LDA #>read_msg ;get upper byte
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;output canned message
JMP rtn_to_tr ;back to command handler
test_rtn: STZ STRING_INDEX ;reset index
LDA #<test_msg ;get lower byte of canned output response
STA STRING_PTR ;put it in first byte of the string pointer
LDA #>test_msg ;get upper byte
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;output canned message
JMP rtn_to_tr ;back to command handler
no_cmd_rtn: STZ STRING_INDEX ;reset index
LDA #<no_cmd_msg ;get lower byte of canned output response
STA STRING_PTR ;put it in first byte of the string pointer
LDA #>no_cmd_msg ;get upper byte
STA STRING_PTR+1 ;store it in second byte of string pointer
JSR terminal_w ;output canned message
JMP rtn_to_tr ;back to command handler
isr: LDA ACIA_STA ;get ACIA status register
BPL end_isr ;if no IRQ, return from ISR
JSR terminal_r
end_isr: RTI
.ORG $FFFA ;6502 NMI, RST, and IRQ vectors
.WORD start ;NMI
.WORD start ;RST
.WORD isr ;IRQ