;******************************************************************** ; ; Title: 6800 Monitor ; Author: Les Hildenbrandt ; Date: 10-15-2013 (Started) ; Revision: 1.2 ; Tool: Universal Cross Asssemblers Meta16 cross assembler ; Description: ROM monitor for MC6800 front panel computer. ; ; RAM: 0000-EFFF ; ROM: F800-FDFF, FE00-FFFF ; PAGED WINDOW: F000-F7FF ; PAGE_SELECT: FE0F ; PANEL SWITCHES: FE00-FE03 ; PANEL LED CLR: FE07 <- makes LED address latches transparent ; PANEL LED SET: FE09 <- latches address into LEDs ; PANEL LED LATCH: FE0E <- latches address into LEDs in 3 clock cycles ; ; Any 2k RAM page in the 512k memory space ; can be mapped into the page window by ; writing the page number into the page select register. ; ;******************************************************************** CPU "6800.TBL" HOF "MOT8" TITL "MC6800 Monitor" FILL 0ffh ; SOH: EQU 01h EOT: EQU 04h ACK: EQU 06h NAK: EQU 15h CAN: EQU 18h ; UART Hardware addresses UART_BASE: EQU 0FE10H UART_RHR: EQU UART_BASE+0 UART_THR: EQU UART_BASE+0 UART_IER: EQU UART_BASE+1 UART_FCR: EQU UART_BASE+2 UART_ISR: EQU UART_BASE+2 UART_LCR: EQU UART_BASE+3 UART_MCR: EQU UART_BASE+4 UART_LSR: EQU UART_BASE+5 UART_MSR: EQU UART_BASE+6 UART_SPR: EQU UART_BASE+7 UART_BAUDL: EQU UART_BASE+0 UART_BAUDH: EQU UART_BASE+1 ; Front panel addresses FP_SWITCH1: EQU 0FE00h FP_SWITCH2: EQU 0FE01h FP_SWITCH3: EQU 0FE02h FP_SWITCH4: EQU 0FE03h LED_CLR: EQU 0FE09h LED_SET: EQU 0FE0Eh ; Memory banking register BANK_SEL: EQU 0FE0Fh STACK: EQU 0efffh ORG 0EE00h CommandBuf: DFS 32 ; uart command buffer CommandBufPtr: DFS 2 ; pointer into command buffer CommandBufCtr: DFS 1 ; nuber of chars in command buffer StartPtr: DFS 2 EndPtr: DFS 2 DestPtr: DFS 2 DataVal: DFS 1 TempPtr: DFS 2 BuffPtr: DFS 2 TempWord: DFS 2 XMState: DFS 1 XMRecNum: DFS 1 XMLastRec: DFS 1 XMRetries: DFS 1 XMTimer: DFS 2 XMCsum: DFS 1 XModemData: DFS 1 TempPhex: DFS 2 DumpBuf: DFS 128 DumpCtrA: DFS 1 DumpCtrB: DFS 1 TempChar: DFS 1 FP_Addr: DFS 2 FP_Data: DFS 1 ; ORG 04000h ORG 0f800H RESET: JMP DORESET JMP Uart1In JMP Uart1Out JMP Uart1Stat JMP DispString JMP UpdateLEDs DORESET: LDS #STACK LDX #0 DELAY: DEX BNE DELAY JSR InitUART LDX #HelloStr JSR DispString MAIN_LOOP: JSR ShowPrompt ; Show the prompt LDX #CommandBuf STX CommandBufPtr ; Reset the command buffer ptr CLR CommandBufCtr LDAA #32 ClrLoop: CLR X INX DECA BNE ClrLoop ; Clear the buffer MAIN_LOOP1: JSR Uart1Stat ; Get uart data ready status BNE MAIN_LOOP3 ; Jump if serial data is ready MAIN_LOOP2: ; Handle fake front panel ; Read switches ; If new Read, Read next, Write, Write Next or run do that JSR HandleFrontPanel BRA MAIN_LOOP1 ; MAIN_LOOP3 - data has been recieved by uart MAIN_LOOP3: JSR Uart1In ; Get data from uart CMPA #0ah BEQ MAIN_LOOP3A ; ignore LFs LDX CommandBufPtr ; get the pointer STAA X ; store the new character in the buffer STAA TempChar INX STX CommandBufPtr ; JSR Uart1Out ; Echo the character LDAA TempChar ; Handle enter key CMPA #0dh ; Was enter pressed BEQ ProcessCommand ; Process the command ; Handle ^X CMPA #"X"-40h ; Was ^X BEQ MAIN_LOOP ; Reset command buffer ; Handle back space, CMPA #08h ; Backspace? BNE MAIN_LOOP3B LDAA CommandBufCtr ; BEQ MAIN_LOOP3A ; jump if buffer is allready empty LDX CommandBufPtr ; get the pointer DEX STX CommandBufPtr ; DEC CommandBufCtr ; MAIN_LOOP3A: JMP MAIN_LOOP1 ; Wait for next char ; Handle next character MAIN_LOOP3B: INC CommandBufCtr ; LDAA #32 ; max number of chars CMPA CommandBufCtr ; Do we have that many chars? BEQ MAIN_LOOP ; buffer overflow, show prompt again BRA MAIN_LOOP1 ; Wait for next char ;**************************************************** ; ProcessCommand: ; Commands are: ; First ; D - Dump mem (D, D start, D start end) (DONE) ; F - Fill mem (F start value count) (DONE) ; G - Go execute (G, G start) (DONE) ; M - Move (M start end destination-start) (DONE) ; S - Set -display and change memory (S start) (DONE) ; ; Next ; X - XModem download (X start) (DONE) ; ; OUT OF ROM SPACE - CANT DO THESE IN THE MONITOR ; Next ; A - Assemble (A, A start) - mini assembler ; L - List (L, L start, L start End) dissasemble ; ; Next ; R - Examine registers ; T - Trace (T, T count) ; U - Untrace (U, U count) ;**************************************************** ProcessCommand: LDAA #0dh JSR Uart1Out ; New line after enter LDAA #0ah JSR Uart1Out ; New line after enter LDX #CommandBuf LDAA X CMPA #"a" ; is it lower case BCS PC_1 ; Not lower case SUBA #"a"-"A" ; Convert to upper case PC_1: CMPA #"D" BNE PC_2 ; Jump if not the Dump command JSR Dump ; do the dump JMP MAIN_LOOP ; Reset pointers, Show prompt PC_2: CMPA #"F" ; Is it the Fill command BNE PC_3 ; Jump if not the Fill command JSR Fill ; do the fill JMP MAIN_LOOP ; Reset pointers, Show prompt PC_3: CMPA #"G" ; Is it the Go command BNE PC_4 ; Jump if not the Fill command JSR GoTo ; execute code JMP MAIN_LOOP ; Reset pointers, Show prompt PC_4: CMPA #"S" ; Is it the Substitute command BNE PC_5 ; Jump if not the Fill command JSR Substitute ; Substitute some memory JMP MAIN_LOOP ; Reset pointers, Show prompt PC_5: CMPA #"M" ; Is it the Move command BNE PC_6 ; Jump if not the Move command JSR Move ; Move some memory JMP MAIN_LOOP ; Reset pointers, Show prompt PC_6: CMPA #"X" ; Is it the XModem download command BNE PC_END ; Jump if not the XModem download command JSR XModem ; download some bytes JMP MAIN_LOOP ; Reset pointers, Show prompt PC_END: LDAA #"?" JSR Uart1Out ; Unknown command JMP MAIN_LOOP ;************************************ ; Get start address * ; Uses GetWord to get a 16 bit value* ; Saves value in StartPtr * ;************************************ GET_START_ADD: ; Get start address JSR GetWord LDAA TempWord STAA StartPtr LDAA TempWord+1 STAA StartPtr+1 RTS ;************************************ ; Get end address * ; Uses GetWord to get a 16 bit value* ; Saves value in EndPtr * ;************************************ GET_END_ADD ; Get end address JSR GetWord LDAA TempWord STAA EndPtr LDAA TempWord+1 STAA EndPtr+1 RTS ;************************************ ; Get destination address * ; Uses GetWord to get a 16 bit value* ; Saves value in DestPtr * ;************************************ GET_DEST_ADD ; Get end address JSR GetWord LDAA TempWord STAA DestPtr LDAA TempWord+1 STAA DestPtr+1 RTS ;************************************ ; Get byte * ; Uses GetWord to get a 16 bit value* ; Saves value in DataVal. Also * ; returns value in acca * ;************************************ GET_BYTE: JSR GetWord LDAA TempWord+1 STAA DataVal RTS ;************************************ ; Get word * ; generic function to get a 16 bit * ; value from buffered characters * ; pointed to by X. * ; Saves value in TempWord * ;************************************ GetWord: CLR TempWord CLR TempWord+1; ; start with 0 GetWord0: INX LDAA X JSR IsHexDigit BNE GetWord1 ; yes, it is a valid hex digit, jump RTS ; return, all done with digits GetWord1: ASL TempWord+1 ; ROL TempWord ; ASL TempWord+1 ; ROL TempWord ; ASL TempWord+1 ; ROL TempWord ; ASL TempWord+1 ; ROL TempWord ; Shift the existing word left 4 bits ORAB TempWord+1 STAB TempWord+1 ; Add in the new nibble BRA GetWord0 ; and continue ;************************************ ; Test if valid ascii hex digit * ; Enter with ascii character in acca* ; Return acca = 0 if not a valid * ; number (0-9, a-f, A-F) * ; Returns acca = 0ffh if valid ascii* ; number. Returns number in accb * ;************************************ IsHexDigit: CMPA #"a" ; is it lower case BCS IHD_1 ; Not lower case SUBA #"a"-"A" ; Convert to upper case IHD_1: TAB SUBA #"0" ; Convert ascii to bin BCS IHD_NO ; The value was less than ASCII "0" TAB ; Save in B CMPA #10 ; Is it > 9? BCS IHD_YES ; No, it is a valid 0-9 IHD_2: SUBA #7 ; Convert "A"-"F" to 0x0a - 0x0f TAB ; Save in B ANDA #0f0h ; is it greater than 0fh? BNE IHD_NO ; Yes, if was greater than 'F', exit IHD_YES: LDAA #0ffh ; Valid RTS ; Return IHD_NO: CLRA ; Not valid RTS ; Return ;******************************************** ; Monitor GoTo command * ; Accepts a 16 bit address and jumps to * ; that address * ;******************************************** GoTo: ;Enable the front panel LEDs to show real time data JSR GET_START_ADD ; Get start address LDAA StartPtr+1 PSHA LDAA StartPtr PSHA ; Push address onto stack RTS ; RTS will jump to Start Address RTS ; Return to the monitor if the code returns ;******************************************** ; Monitor Fill command * ; Accepts a 16 bit start address, a 16 bit * ; end address and a data value. * ; Fills all memory locations between the * ; start and end with that data value. * ;******************************************** Fill: JSR GET_START_ADD ; Get start address JSR GET_END_ADD ; Get end address JSR GET_BYTE ; Get fill value LDX StartPtr LDAA DataVal Fill_1: STAA X CPX EndPtr BEQ Fill_2 INX BRA Fill_1 Fill_2: RTS ;******************************************** ; Monitor Move command * ; Accepts a 16 bit start address, a 16 bit * ; end address and a 16 bit destination * ; address. * ;******************************************** Move: LDAA 1,X ; see if a start address was entered CMPA #0dh BEQ MoveDone ; No start address was entered JSR GET_START_ADD ; Get start address LDAA 1,X ; see if a start address was entered CMPA #0dh BEQ MoveDone ; No start address was entered JSR GET_END_ADD ; Get end address LDAA 1,X ; see if a start address was entered CMPA #0dh BEQ MoveDone ; No start address was entered JSR GET_DEST_ADD ; Destination MoveLoop: LDX StartPtr LDAA X LDX DestPtr STAA X INX STX DestPtr LDX StartPtr CPX EndPtr BNE MoveLoop1 MoveDone: RTS MoveLoop1: INX STX StartPtr BRA MoveLoop ;******************************************** ; Monitor Substitute command * ; Accepts a 16 bit start address. * ; Show the existing value in each memory * ; location and allow the user to change it * ; Press enter or space for next address * ; Enter hex value followed by enter or space* ; to save new data. * ; Press any unused key to exit * ;******************************************** Substitute: LDAA 1,X ; see if a start address was entered CMPA #0dh BEQ Sub0 ; Not start address was entered, use the previous value JSR GET_START_ADD ; Get start address Sub0: LDAA #0dh JSR Uart1Out LDAA #0ah JSR Uart1Out LDAA StartPtr JSR PhexU1 ; Display MSB LDAA StartPtr+1 JSR PhexU1 ; Display LSB LDAA #" " JSR Uart1Out ; Display " " LDAA #"-" JSR Uart1Out ; Display "-" LDAA #" " JSR Uart1Out ; Display " " LDX StartPtr JSR UpdateLEDs ; update the front panel LEDs LDAA X JSR PhexU1 ; Display Data currently at memory address LDAA #" " JSR Uart1Out ; Display " " ; ; ; Get new byte from user, or enter / space to leave alone ; or non hex digit to exit ; ; LDX #CommandBuf STX CommandBufPtr ; Reset the command buffer ptr CLR CommandBufCtr Sub1: JSR HandleFrontPanel JSR Uart1Stat BEQ Sub1 ; Scan front panel while waiting for key press JSR Uart1In JSR Uart1Out LDX CommandBufPtr ; get the pointer STAA X ; store the new character in the buffer INX STX CommandBufPtr ; CMPA #" " BEQ Sub3 ; show next address with space CMPA #0dh BEQ Sub3 ; show next address with enter CMPA #"X"-40h ; Was ^X BEQ Sub0 ; Reset this byte JSR IsHexDigit BNE Sub1 ; It is a valid hex digit RTS ; Not a valid hex digit, all done Sub3: LDX CommandBufPtr DEX CPX #CommandBuf BEQ Sub4 ; this was the first char, just display the next LDX #CommandBuf DEX JSR GetWord ; Decode the value in the buffer LDAA TempWord+1 ; get the user entered value LDX StartPtr ; Get the memory pointer STAA X ; Save it in memory Sub4: ; Update the LEDs LDX StartPtr ; Get memory address INX ; Point at next STX StartPtr ; And save JMP Sub0 ; and do the next ram location ;******************************************** ; Monitor Dump command * ; Accepts a 16 bit start address, and * ; optionaly a 16 bit end address. Displays * ; the memory contents in that range. If no * ; end address is entered, 128 bytes are * ; displayed. * ;******************************************** Dump: LDAA 1,X ; see if a start address was entered CMPA #0dh BNE Dump0 ; A start address was entered LDAA StartPtr+1 ; Use the previous value ADDA #7fh STAA EndPtr+1 LDAA StartPtr ADCA #0 STAA EndPtr ; Assume there is no end address, add 80h to start address BRA Dump1 ; No start address, so assume no end address and dump Dump0: JSR GET_START_ADD ; Get start address LDAA StartPtr+1 ADDA #7fh STAA EndPtr+1 LDAA StartPtr ADCA #0 STAA EndPtr ; Assume there is no end address, add 80h to start address ; LDAA X ; get the char following the start address CMPA #0dh ; was it enter? BEQ Dump1 ; just one address was given LDAA 1,X ; get the char following the start address CMPA #0dh ; was it enter? BEQ Dump1 ; just one address was given JSR GET_END_ADD ; Get end address Dump1: LDX StartPtr STX TempWord LDX EndPtr STX TempWord CLR DumpCtrA DumpLoop1: LDAA DumpCtrA BNE DumpLoop2 ; Jump if not the first byte on this line LDX #DumpBuf STX BuffPtr ; Start a new line in the display buffer LDX StartPtr STX TempPtr ; save the address of the start of this line LDX BuffPtr ; Get display buffer pointer LDAA StartPtr JSR PhexBuf ; Display address MSB LDAA StartPtr+1 JSR PhexBuf ; Display Address LSB LDAA #9 ; add a tab STAA X ; Save in buffer INX STX BuffPtr ; Save display buffer pointer DumpLoop2: LDX StartPtr LDAA X ; Get a byte from memory INX ; Point at the next location STX StartPtr ; Save the memory pointer LDX BuffPtr ; Get display buffer pointer JSR PhexBuf ; put the hex for this byte in the buffer LDAA #" " ; add a space STAA X ; Save in buffer INX STX BuffPtr ; Save display buffer pointer INC DumpCtrA ; how many bytes on this line? LDAA DumpCtrA STAA DumpCtrB CMPA #16 ; a full line BEQ DumpLoop3 ; we have displayed all 16 bytes, go add ascii LDX StartPtr DEX CPX EndPtr ; At end of buffer ? BNE DumpLoop1 ; not at end of buffer or line yet, print another digit ; Handle additional spaces for lines with fewer than 16 bytes DumpLoop2a: LDX BuffPtr ; Get display buffer pointer LDAA #" " ; add a space STAA X ; Save in buffer INX STAA X ; Save in buffer INX STAA X ; Save in buffer INX STX BuffPtr ; Save display buffer pointer <--- Add 3 spaces for each byte not displayed on a line INC DumpCtrA ; LDAA DumpCtrA CMPA #16 ; a full line BNE DumpLoop2a ; More spaces to add ; Add a space between hex and ascii DumpLoop3: LDX BuffPtr ; Get display buffer pointer LDAA #" " ; add a space STAA X ; Save in buffer INX STX BuffPtr ; Save display buffer pointer ; Now display the ASCII values DumpLoop4: LDX TempPtr LDAA X ; Get a byte of memory INX STX TempPtr CMPA #20h BCC DumpLoop5 ; less than a ' ' LDAA #"." DumpLoop5: CMPA #80h BCS DumpLoop6 ; less than a '~' LDAA #"." DumpLoop6: LDX BuffPtr ; Get display buffer pointer STAA X ; Save ASCII char in buffer INX STX BuffPtr ; Save display buffer pointer LDX TempPtr DEX CPX EndPtr ; At end of buffer ? BEQ DumpLoop6B ; No more to do DEC DumpCtrB ; Have we done 16 BNE DumpLoop4 ; No - display more DumpLoop6B: ; Add a CR LF and send it out the serial port LDX BuffPtr ; Get display buffer pointer LDAA #0dh STAA X ; Add a CR INX LDAA #0ah STAA X ; Add a LF INX CLR X ; Null terminate LDX #DumpBuf STX BuffPtr ; Reset pointer JSR DispString ; send out serial port ; Check if more memory to dump LDX TempPtr DEX CPX EndPtr ; At end of buffer ? BEQ DumpLoop7 ; not at end of buffer or line yet, print another digit JMP Dump1 ; not at end of buffer, go do another line DumpLoop7: RTS ;************************************ ; XModem protocol downloadd * ; Recieve * ; data[128] and checksum * ; Checksum is the sum of data[128] * ; IF = ! and checksum = * ; sum of data[128] then save data[1]* ; into RAM at the start address and * ; respond with an , if those * ; conditions are not met, respond * ; with a * ; Continue until or is * ; received instead of . * ;************************************ XModem: LDAA 1,X ; see if a start address was entered CMPA #0dh BNE XModem0 ; A start address was entered LDX #NoAddMes JSR DispString ; Display no address error message RTS ; And return to monitor NoAddMes: DFB 0dh,0ah,"Must enter address!",0 XModem0: JSR GET_START_ADD ; Get start address CLR XMState ; Start with state 0, waiting for SOH LDAA #20h STAA XMTimer CLR XMTimer+1 ; clear nak timer LDX #DumpBuf STX TempPtr LDAA #10 STAA XMRetries STAA XMLastRec CLR XMRecNum CLR XMState XModem1: JSR HandleFrontPanel ; Scan front panel while waiting for data LDX XMTimer DEX STX XMTimer ; run the timer LDAA XMTimer ORAA XMTimer+1 ; test if expired BNE XModem1a JMP XMSendNak ; Timed out, send a NAK XModem1a: JSR Uart1Stat ; is data ready BEQ XModem1 ; No, keep waiting LDAA #20h STAA XMTimer CLR XMTimer+1 ; clear nak timer JSR Uart1In STAA XModemData ; save the recieved byte LDAA XMState ; Get state CMPA #0 BNE XMState1 XMState0: ; State 0, waiting for or LDAA XModemData CMPA #SOH BNE XMState0a ; Not a SOH INC XMState ; State 1 LDX #DumpBuf STX TempPtr ; reset pointer CLR XMCsum ; reset the checksum BRA XModem1 ; and wait for next byte using state 1 XMState0a: CMPA #CAN BEQ XMState0b ; yes, a CAN CMPA #EOT BNE XModem1 ; Not a EOT XMState0b: LDAA #ACK JSR Uart1Out RTS XMState1: CMPA #1 BNE XMState2 LDAA XModemData STAA XMRecNum ; save the ID byte INC XMState ; State 2 BRA XModem1 ; and wait for next byte using state 2 XMState2: CMPA #2 BNE XMState3 LDAA XModemData COMA CMPA XMRecNum ; does the invere byte match the true byte? BNE XMSendNak ; did not match CMPA XMLastRec BEQ XMSendAck ; same record again, ignore INC XMState ; State 3 STAA XMLastRec BRA XModem1 ; and wait for next byte using state 3 XMState3: CMPA #3 BNE XMState4 LDAA XModemData LDX TempPtr ; get the pointer STAA X INX STX TempPtr ; save the pointer ADDA XMCsum STAA XMCsum ; update the checksum CPX #DumpBuf+128 BNE NearXModem1 ; keep getting data bytes INC XMState ; State 4 BRA NearXModem1 ; and wait for next byte using state 4 XMState4: CMPA #4 BNE XMState5 LDAA XModemData CMPA XMCsum ; Did the checksum match? BNE XMSendNak ; did not match LDAA #128 STAA XMCsum LDX #DumpBuf STX TempPtr ; reset pointer XMState4a: LDX TempPtr LDAA X INX STX TempPtr LDX StartPtr STAA X INX STX StartPtr DEC XMCsum BNE XMState4a ; Copy to the target memory address BRA XMSendAck ; All done with this record XMState5: CLR XMState NearXModem1: JMP XModem1 ; Unknown state? XMSendNak: LDAA #NAK JMP XMSendEither XMSendAck: LDAA #ACK XMSendEither: JSR Uart1Out CLR XMState ; Start with state 0, waiting for SOH LDAA #20h STAA XMTimer CLR XMTimer+1 ; clear nak timer JMP XModem1 ; wait for the net SOH PhexBuf: PSHA ; Save a copy of the value PSHA ; Save a copy of the value LSRA LSRA LSRA LSRA ; put the MSN in the LSN CMPA #10 BCS PhexBuf2 ; if less than 10 ADDA #7 ; Convert 10-15 to a-f PhexBuf2: ADDA #"0" ; convert to ascii STAA X ; Save in buffer INX PULA ; Get the origianl value ANDA #0fh ; get LSN only CMPA #10 BCS PhexBuf3 ; if less than 10 ADDA #7 ; Convert 10-15 to a-f PhexBuf3: ADDA #"0" ; convert to ascii STAA X ; Save in buffer INX CLRA STAA X ; Null terminate PULA RTS PhexU1: PSHA ; Save a copy of the value LDX #TempPhex JSR PhexBuf LDX #TempPhex LDAA X JSR Uart1Out LDAA 1,X JSR Uart1Out PULA ; Get the origianl value RTS ;;**************************************************** ; Uart functions to Initialize, get rx status, * ; receive a byte, get tx status and send a byte * ;**************************************************** InitUART: LDAA #80h JSR UART_Convert STAA UART_LCR ; Enable baud rate access STAA UART_LCR+8 ; Enable baud rate access LDAA #12 BSR UART_Convert STAA UART_BAUDL ; Baud rate low STAA UART_BAUDL+8 ; Baud rate low LDAA #00h BSR UART_Convert STAA UART_BAUDH ; Baud rate high STAA UART_BAUDH+8 ; Baud rate high LDAA #07h BSR UART_Convert STAA UART_LCR ; 8,n,2, disable baud rate reg access STAA UART_LCR+8 ; 8,n,2, disable baud rate reg access RTS Uart1Stat: LDAA UART_LSR ; Get RX status BSR UART_Convert ANDA #1 ; Strip to RX ready bit RTS ; And return Uart2Stat: LDAA UART_LSR+8 ; Get RX status BSR UART_Convert ANDA #1 ; Strip to RX ready bit RTS ; And return Uart1In: BSR Uart1Stat BEQ Uart1In ; Wait for data ready LDAA UART_RHR ; Get data BSR UART_Convert RTS ; And return Uart2In: BSR Uart2Stat BEQ Uart2In ; Wait for data ready LDAA UART_RHR+8 ; Get data BSR UART_Convert RTS ; And return Uart1OutStat: LDAA UART_LSR ; Get RX status BSR UART_Convert ANDA #40h ; Strip to TX Empty RTS ; And return Uart2OutStat: LDAA UART_LSR+8 ; Get RX status JSR UART_Convert ANDA #40h ; Strip to TX Empty RTS ; And return Uart1Out: PSHA ; Save data to transmit PSHA ; Save data to transmit Uart1Out1: BSR Uart1OutStat BEQ Uart1Out1 ; Wait for TX empty PULA ; Get data to send BSR UART_Convert STAA UART_THR ; Send data PULA ; Get data to send RTS ; And return Uart2Out: PSHA ; Save data to transmit PSHA ; Save data to transmit Uart2Out1: BSR Uart2OutStat BEQ Uart2Out1 ; Wait for TX empty PULA ; Get data to send BSR UART_Convert STAA UART_THR+8 ; Send data PULA ; Get data to send RTS ; And return DispString: LDAA X BNE DispString1 RTS DispString1: BSR Uart1Out INX BRA DispString ShowPrompt: LDX #PromptStr BSR DispString RTS UART_Convert: PSHB LDAB #80h UC0: ASLA RORB BCC UC0 TBA PULB RTS HandleFrontPanel: LDAA FP_SWITCH1 LDAA #0ffh BITA #0 BNE NotGo ; run switch address NotGo: BITA #1 BNE NotLoad ; display the data at the address specified by the switches BSR ReadFPSwitches LDX FP_Addr BRA UpdateLEDs ; Will return to caller NotLoad: BITA #2 BNE NotDeposit ; store and display the data BSR ReadFPSwitches ; Read the address and data switcheds LDX FP_Addr LDAA FP_Data STAA X ; put the value in memory BRA UpdateLEDs ; Will return to caller NotDeposit: BITA #3 BNE NotLoadNext ; display the data at the next address LDX FP_Addr INX STX FP_Addr ; Next Addr BRA UpdateLEDs ; Will return to caller NotLoadNext: BITA #4 BNE NotDepositNext ; store and display the next data LDX FP_Addr ; get the previous address BSR ReadFPSwitches ; Read the address and data switches (need a new data value) INX STX FP_Addr ; Next Addr LDAA FP_Data STAA X ; put the value in memory BRA UpdateLEDs ; Will return to caller NotDepositNext: RTS UpdateLEDs: LDAA 0fe07h ; Make latches transparent LDAA 0fe0eh ; Start counter LDAA X ; Put address and data on busses to latch RTS ReadFPSwitches: LDAA FP_SWITCH2 STAA FP_Addr LDAA FP_SWITCH3 STAA FP_Addr+1 LDAA FP_SWITCH4 STAA FP_Data RTS PromptStr: DFB 0dh,0ah,">",0 HelloStr: DFB 0dh,0ah,"LESTAIR 680",0 EndAdd: EQU $ ORG 0fffeh DWM 0f800h END