;======================================================= ; Pilot: Serial Interface ; ----------------------------------------------------- ; W65C02 CPU at 1.8432MHz ; AT28C64 ROM $8000-$FDFF & $FF00-$FFFF ; AS62256 RAM $0000-$7FFF ; W65C51 ACIA $FE14-$FE17 ; MAX232 RS232 Driver ; 74LS30 $FEXX Range IO Select ; 74LS00 Not Gates, ROM Select, Write Sync ; 74LS138 ACIA Select ; ----------------------------------------------------- ; USE: ; Assemble with DASM 6502 ; Write this BIN to $FB00 ; Note the first two bytes are the origin ; when assembled with dasm these must ; be removed before writing the bin ; Connect to Serial Port ; ----------------------------------------------------- ; TODO: ; find the extra crlf bug ; error checking ; SPI Bit Bang ; Load ; Save ; EPROM Programmer Software ; Format ; Unassemble ; Assemble ; Hardware TODO: ; enable hand shaking RTS and CTS on 6551 ; hard wire ROM write to high ; change address space ; Wire up 6522 Interrupts ;======================================================= processor 6502 IOADDR = $FE00 ; START OF IO AREA ZPADDR = $00 ; START OF ZERO PAGE (INCASE USING SMALL MEMORY) STACK = $FF ; TOP OF STACK (INCASE USING SMALL MEMORY) BUFFER = $0300 ; START OF INPUT BUFFER ACIDLY = $27 ; DELAY FOR THE ACIA INT = $0200 ; ADDRESS FOR USER INT (SMALL MEMORY) NMI = $0203 ; ADDRESS FOR USER NMI (SMALL MEMORY) MEMADR = $FC00 ; ORIGINE FOR ASSEMBLING ;INTACT = $01 ; INTERRUPT ACTIVE (6507 DOESN'T HAVE INTERRUPT) ;ACIBUG = $01 ; NEW ACIA RECEIVE BUG ACIDAT = IOADDR+$14 ; ACIA ADDRESSES ACISTT = IOADDR+$15 ACICMD = IOADDR+$16 ACICTL = IOADDR+$17 ADDR1L = ZPADDR+$00 ; ZERO PAGE ADDRESSES ADDR1H = ZPADDR+$01 ADDR2L = ZPADDR+$02 ADDR2H = ZPADDR+$03 ADDR3L = ZPADDR+$04 ADDR3H = ZPADDR+$05 BUFPTR = ZPADDR+$06 DLYCNT = ZPADDR+$07 DATBYT = ZPADDR+$08 ORG $FB00 ;------------------------------------------------------- ; To Uppercase V0.12 ;------------------------------------------------------- TOUP: CMP #$61 ; CMP "a" BCC TOUP1 ; IF LESS THAN A DON'T CHANGE CMP #$7A ; CMP "z" BCS TOUP1 ; IF GREATER THAN Z DON'T CHANGE AND #$DF ; IF LOWER CASE CHANGE TO UPPER CASE TOUP1: RTS ; RETURN ;------------------------------------------------------- ; Hex Nibble In V0.12 ;------------------------------------------------------- HNIN: JSR TOUP ; Make sure byte is upper case HNIN1: CLC ; Subtract "0" SBC #$2F CMP #$0A ; Check if we are greater than 9 BCC HNIN2 CLC ; if greater than 9 subtract 6 SBC #$06 HNIN2: RTS ; Return ;------------------------------------------------------- ; Hex Out V0.12 ;------------------------------------------------------- HOUT: PHA ; Save a LSR ; SHIFT in upper Nibble LSR LSR LSR JSR HNOUT ; Output upper Nibble PLA ; Restore A ;------------------------------------------------------- ; Hex Nibble Out V0.12 ;------------------------------------------------------- HNOUT: AND #$0F ; Clear upper bitss CMP #$0A ; Check greater than "9" BCC HNOUT2 CLC ; If greater than "9" add 7 ADC #$07 HNOUT2: CLC ; Add "0" ADC #$30 ;------------------------------------------------------- ; Character Out V0.12 ;------------------------------------------------------- COUT: PHA ; Save A LDA #ACIDLY ; W65C51 Error use delay JSR DELAY PLA ; Restore A STA ACIDAT ; Output byte to serial RTS ; Return ;------------------------------------------------------- ; String Out V0.12 ;------------------------------------------------------- STOUT: NOP NOP NOP LDY #$00 ; Zero counter STOUT2: LDA (ADDR3L),Y ; Load byte text+x BEQ STOUT3 ; If zero wait for key JSR COUT ; Output character INY ; Increment pointer JMP STOUT2 ; Write next character NOP NOP NOP STOUT3: RTS ; Return ;------------------------------------------------------- ; Memory Copy Routine V0.12 ; ADDR2 Source ; ADDR1 Destination ; x number of bytes to write ;------------------------------------------------------- MEMCPY: LDY #$00 ; Zero pointer MEMCP2: LDA (ADDR2L),Y ; Get byte from source address STA (ADDR1L),Y ; Store byte at destination address INY ; Increment pointer DEX ; Decriment byte count BNE MEMCP2 ; next byte RTS ; return ;------------------------------------------------------- ; CRLF V0.12 ;------------------------------------------------------- CRLF: LDA #$0D ; Print carrage return JSR COUT LDA #$0A ; Print line feed JSR COUT RTS ; Return ;------------------------------------------------------- ; Command Help V0.12 ;------------------------------------------------------- CHELP: LDA #HELP ; Load high help STA ADDR3H JSR STOUT ; Print String RTS ; Return HELP: .BYTE "help: h", $0D, $0A .BYTE "read: r mmmm", $0D, $0A .BYTE "dump: d mmmm", $0D, $0A .BYTE "move: m ssss dddd cc", $0D, $0A .BYTE "write: w mmmm bb [bb...]", $0D, $0A .BYTE "call: c mmmm", $0D, $0A .BYTE $00 ;------------------------------------------------------- ; Command Read V0.12 ;------------------------------------------------------- CREAD: JSR RDVAL JSR TA3A1 LDA ADDR1H ; Print high address JSR HOUT LDA ADDR1L ; Print low address JSR HOUT LDA #":" ; Print ":" JSR COUT LDA #" " ; Print space JSR COUT LDY #$00 ; Print byte at that address LDA (ADDR1L),Y JSR HOUT JSR CRLF ; Print crlf RTS ; Return ;------------------------------------------------------- ; Command Dump V0.12 ;------------------------------------------------------- CDUMP: JSR RDVAL ; Get address from ascii JSR TA3A1 ; Place into Address 1 LDY #$00 ; Zero data pointer LDX #$08 ; Display 8 rows STX DATBYT ; Store row counter CDUMP1: LDA ADDR1H ; Print high address JSR HOUT LDA ADDR1L ; Print low address JSR HOUT LDA #":" ; Print ":" JSR COUT LDX #$10 ; Display 16 bytes CDUMP2: LDA #" " ; Print space JSR COUT LDA (ADDR1L),Y ; Print byte JSR HOUT INC ADDR1L ; Next byte BNE CDUMP3 INC ADDR1H CDUMP3: DEX BNE CDUMP2 JSR CRLF ; Next row DEC DATBYT BNE CDUMP1 RTS ; Return ;------------------------------------------------------- ; Command Move V0.12 ;------------------------------------------------------- CMOVE: JSR RDVAL ; 3 JSR TA3A2 ; 6 JSR RDVAL ; 9 JSR TA3A1 ; 12 JSR RDVAL ; 15 LDX ADDR3L ; 17 JSR MEMCPY ; 20 ;------------------------------------------------------ ; Command write V0.12 ;------------------------------------------------------- CWRITE: JSR RDVAL JSR TA3A1 CWRT2: JSR RDVAL JSR TA3DB TYA PHA LDA #$00 TAY LDA DATBYT STA (ADDR1L),Y PLA TAY INY LDA BUFFER,Y ; CHECK FOR $00 BEQ CWRT3 DEY INC ADDR1L BNE CWRT2 INC ADDR1H JMP CWRT2 CWRT3: RTS ; Return ;------------------------------------------------------ ; Command Call V0.12 ;------------------------------------------------------- CCALL: JSR RDVAL JSR TA3A1 JSR CCALL2 CCALL2: PLA CLC ADC #$08 PHA JMP (ADDR1L) ; Call address RTS ; Return ;------------------------------------------------------- ; Delay V0.12 ;------------------------------------------------------- DELAY: STA DLYCNT PHA ; Save a TXA ; Save x PHA DELAY1: LDX #$FF ; Delay value DELAY2: DEX ; Decrement delay value BNE DELAY2 ; Keep going until we reach zero DEC DLYCNT BNE DELAY1 PLA ; Restore x TAX PLA ; Restore a RTS ; Return ;------------------------------------------------------- ; Read Value in Buffer V0.12 ;------------------------------------------------------- RDVAL: LDA #$00 STA DLYCNT STA ADDR3H SKPWHT: INY LDA BUFFER,Y BEQ VALDON CMP #" " BEQ SKPWHT RDNIB: LDA BUFFER,Y BEQ VALDON CMP #" " BEQ VALDON LDX #$04 ROTA3: CLC ROL ADDR3L ROL ADDR3H DEX BNE ROTA3 JSR HNIN ORA ADDR3L STA ADDR3L INY INC DLYCNT JMP RDNIB VALDON: LDA DLYCNT RTS ;------------------------------------------------------- ; Transfer ADDR3 to ADDR2 V0.12 ;------------------------------------------------------- TA3A2: LDA ADDR3H STA ADDR2H LDA ADDR3L STA ADDR2L RTS ;------------------------------------------------------- ; Transfer ADDR3 to ADDR1 V0.12 ;------------------------------------------------------- TA3A1: LDA ADDR3H STA ADDR1H LDA ADDR3L STA ADDR1L RTS ;------------------------------------------------------- ; Transfer ADDR3 To DATBYT V0.12 ;------------------------------------------------------- TA3DB: LDA ADDR3L STA DATBYT RTS ;------------------------------------------------------- ; Command Unassemble ;------------------------------------------------------- CUASM: RTS ;------------------------------------------------------- ; IO Area can't be seen by the computer ;------------------------------------------------------- ORG $FE00 .BYTE "Pilot Version 0.12", $0D, $0A .BYTE "(C)Copyright 2018 DeskMachines", $0D, $0A ;------------------------------------------------------- ; Setup V0.12 ;------------------------------------------------------- ORG $FF00 START: CLD ; CLEAR DECIMAL MODE SEI ; TURN INTERRUPTS OFF LDX #STACK ; SETUP STACK POINTER ($01FF) TXS LDA #$4C ; SETUP USER MODIFABLE IRQ/NMI STA INT ;STA NMI LDA #FINT STA INT+2 ;LDA #FNMI ;STA NMI+2 LDA #$00 ; RESET BUFFER INDEX STA BUFPTR LDA #ACIDLY ; WAIT FOR ACIA TO RESET JSR DELAY ; INITIALIZE ACIA LDA #$09 ; No parity, no echo, no interrupt STA ACICMD LDA #$1E ; 1 stop bit, 8 data bits, 9600 baud STA ACICTL LDA #INTRO ; ... and the high byte STA ADDR3H JSR STOUT ; then call STOUT. CLI ; turn on interrupts DIE: JMP DIE ; Die routine ;------------------------------------------------------- ; Interrupt V0.12 ;------------------------------------------------------- FINT: SEI ; Turn off interrupts PHA ; Save A PHP ; SAVE P TYA ; Save Y PHA ; turn off clear to send LDA ACISTT ; Get Status ; CHECK IF ACIA BEFORE PROCEEDING LDY BUFPTR ; load buffer ptr into y LDA ACIDAT ; Get character JSR TOUP ; To upper case CMP #$0D ; Check for carrage return BEQ INTCMD ; CMP #$0A ; Check for line feed (Adds linux txt file upload support) ; BEQ INTCMD STA BUFFER,Y INY ; Increment buffer index STY BUFPTR JMP INTDON ; We are done INTCMD: LDA #$00 ; Store zero STA BUFPTR STA BUFFER,Y LDA #BUFFER ; Load high buffer STA ADDR3H JSR STOUT ; Print received command JSR CRLF LDA #$00 ; BECAUSE STOUT DESTROYS Y TAY CMPCMD: LDA CMDS,Y ; LOAD BYTE FROM CMDS BEQ INTDON ; IF $00 WE HIT THE END ; UNKNOWN COMMAND ERROR INY ; NEXT COMMAND CMP BUFFER ; COMPARE TO COMMAND IN BUFFER BNE CMPCMD ; IF NOT COMMAND GET NEXT COMMAND JSR RETADR RETADR: DEY PLA CLC ADC #$0F ;ADC #$D8 ; INTDONE PHA LDA CMDSAH,Y PHA LDA CMDSAL,Y PHA LDY #$00 RTS INTDON: ; turn on clear to send PLA ; Restore Y TAY PLP ; RESTORE P PLA ; Restore A CLI ; Turn on interrupts FNMI: RTI ; Return from Interrupt ;------------------------------------------------------- ; Data ;------------------------------------------------------- INTRO: .BYTE "Pilot v0.12", $0D, $0A .BYTE " TYPE H", $0D, $0A, $00 CMDS: .BYTE "HWDMRCU", $00 CMDSAL: .BYTE #CHELP, #>CWRITE, #>CDUMP, #>CMOVE, #>CREAD, #>CCALL, #>CUASM ;ERR: .BYTE "ERR" ;ERRORS: .BYTE "ADR", "BYT", "CMD" ;ERR: CMD? ;ERR: ADR? ;ERR: BYT? ;------------------------------------------------------- ; Vectors ;------------------------------------------------------- ORG MEMADR+$03FA .WORD FNMI ; NMI .WORD START ; Reset .WORD INT ; IRQ/BRK