REM > P1Acn10/src REM Source for Acorn Plus1 ROM v1.00 : ON ERROR REPORT:PRINT" at line ";ERL:END IF PAGE>&8000:SYS "OS_GetEnv"TOA$:IFLEFT$(A$,5)<>"B6502":OSCLI"B6502"+MID$(A$,INSTR(A$," ")) : name$="Plus1Acn":ver$="1.00" DIM mcode% &1000,L% -1:load%=&8000 OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0 OSFILE=&FFDD:OSARGS=&FFDA:OSBGET=&FFD7:OSBPUT=&FFD4 OSGBPB=&FFD1:OSFIND=&FFCE:GSINIT=&FFC2:GSREAD=&FFC5 : REM Workspace REM --------- REM &0D68-&0D6F Plus 1 Support REM REM &0D68 flags REM &Fx = 100Hz poll enabled REM &80 = Plus 1 100Hz handlers disabled REM &40 = printer buffer active REM &20 = ADC active REM &10 = serial active REM &08 = temporarily disabled for TAPE/ROM access REM &04 = ROM table has been moved during Reset REM &02 = ignore serial interupts REM &01 = Plus 1 disabled REM &0D69 Serial speed control register (&FC61) RAM copy REM &0D6A Serial interupt mask (&FC65) REM &80 = input port change (incoming CTS) REM &01 = serial output buffer active REM &02 = serial input buffer active REM &0D6B ROMSTROBE (&FC73) RAM copy REM &0D6C/D => Base of OSBYTE variables REM &0D6E/F Saved FILEV : REM I/O addresses REM ------------- REM &FC60-6F Electron 2681 serial controller REM &FC60 Control REM &FC61 Serial speed control register REM b7-b4=tranmit, b3-b0-receive REM &FC62 Serial command register REM &FC63 Transmit/Receive Data Register REM &FC64 Aux Control/Input Changed REM &FC65 Serial interupt mask - RAM copy in &0D6A REM &FC6D Output config/Input port REM Read bit 2 to read CTS REM &FC6E Serial set output bits REM Write &01 to clear RTS REM &FC6F Serial clear output bits REM Write &01 to set RTS REM REM &FC70-73 Electron expansion REM &FC70 AtoD convertor REM Read: data value, Write: control REM &FC71 Centronics port REM Write: write to port REM &FC72 Electron expansion status REM Read: b7=BUSY, b6=ADC, b5=Fire1, b4=Fire2 REM &FC73 Electron REM Write: ROMSTROBE REM : file$=LEFT$(name$+LEFT$(ver$,1)+MID$(ver$,3,2),10) FOR P=0 TO 1:opt%=P*2+4 P%=load%:O%=mcode% [OPT opt% .exec% .L8000:JMP L8043 :\ Language entry .L8003:JMP L807C :\ Service entry .L8006:EQUB &C0 :\ ROM type=Serv+Lang+6502 BASIC .L8007:EQUB L8035-L8000-1 :\ Copyright offset .L8008:EQUB &00 :\ ROM version byte .L8009:EQUS "Electron Expansion" :\ ROM title EQUS STRING$(LEN"Electron Expansion",CHR$127) EQUB 11:EQUB 11 :\ Causes title to be overwritten EQUB 0 EQUS ver$:EQUB 0 :\ ROM version string .L8035 EQUS "(C)1984 Acorn":EQUB 0 :\ Copyright string \ LANGUAGE HANDLER \ ================ \ If we are entered, we walk through the ROM table to find another language to enter. \ **BUG** We are executing in the language memory, so we can't see the ROM table!!!! \ .L8043 LDY #&AA:JSR L85DD :\ Read OSBYTE &AA - ROM table - *BAD* We are in language memory STX &00:STY &01 :\ (&00)=>ROM table LDX &F4 :\ Read my ROM number - *BAD* We are in language memory .L804E LDA L8064,X :\ Get next ROM to test BMI L8074 :\ Bit 7 set, end of list, print '?' and abort TAX :\ X=ROM to step to next TAY:LDA (&00),Y :\ Get ROM flags for this ROM - *BAD* We are in language memory ROL A:BPL L804E :\ Bit 6 = 0, no language, try next one \ \ Found a language, enter it LDA #&8E:LDY #&00 JSR OSBYTE :\ OSBYTE 142 - Enter language .L8061 JMP L8061 :\ Hang \ ROM table walk path \ ------------------- .L8064 EQUB &0B:EQUB &00:EQUB &01:EQUB &02 EQUB &03:EQUB &04:EQUB &05:EQUB &06 EQUB &FF:EQUB &FF:EQUB &FF:EQUB &0A EQUB &07:EQUB &0C:EQUB &0D:EQUB &0E \ \ ROMs will be scanned for a language starting from the ROM the \ Plus1 ROM is in in the order 15,14,13,12,7,6,5,4,3,2,1,0,11,10. \ Couldn't find a language \ ------------------------ .L8074 LDA #ASC"?":JSR OSWRCH :\ Print '?' .L8079 JMP L8079 :\ Hang \ SERVICE HANDLER \ =============== .L807C PHP:TAX CPX #&16:BCS L808E :\ Unsupported, exit PHA :\ Save call number ASL A:TAX :\ Index into dispatch table LDA L8092+1,X:PHA :\ Stack high byte of address LDA L8092+0,X:PHA :\ Stack low byte of address RTS :\ Return to jump to routine \ Unsupported call .L808E LDX &F4 :\ Restore ROM number (not needed) PLP :\ Restore flags (not needed) RTS \ Service call dispatch table \ --------------------------- .L8092 EQUW L80BE-1 :\ &00 - Null EQUW L80C8-1 :\ &01 - Private workspace EQUW L80BE-1 :\ &02 - Null EQUW L80BE-1 :\ &03 - Null EQUW L80BE-1 :\ &04 - Null EQUW L8102-1 :\ &05 - Interupt EQUW L8520-1 :\ &06 - Error EQUW L831C-1 :\ &07 - OSBYTE EQUW L80BE-1 :\ &08 - Null EQUW L842B-1 :\ &09 - Help EQUW L80BE-1 :\ &0A - Null EQUW L80BE-1 :\ &0B - Null EQUW L80BE-1 :\ &0C - Null EQUW L80BE-1 :\ &0D - Null EQUW L80BE-1 :\ &0E - Null EQUW L857D-1 :\ &0F - Vectors changed EQUW L80BE-1 :\ &10 - Null EQUW L80BE-1 :\ &11 - Null EQUW L80BE-1 :\ &12 - Null EQUW L81B7-1 :\ &13 - Character in serial buffer EQUW L81C0-1 :\ &14 - Character in printer buffer EQUW L8192-1 :\ &15 - 100Hz poll \ Unsupported call .L80BE LDX &F4 :\ Restore ROM number (not needed) PLA :\ Restore call number PLP :\ Restore flags (not needed) RTS \ Claim call and return \ --------------------- .L80C3 PLA :\ Drop saved call number LDA #&00 :\ A=0 to claim PLP :\ Restore flags (not needed) RTS \ SERVICE 1 - Shared workspace \ ============================ \ Set up Plus 1 support .L80C8 TYA:PHA :\ Save workspace pointer LDA #&00:STA &0D68 :\ No 100Hz calls, ROM table not moved, nothing disabled STA &0D6B :\ Set ROMSTROBE copy to &00 LDA #&A6:LDX #&00 LDY #&FF:JSR OSBYTE :\ Get address of ROM table STX &0D6C:STY &0D6D :\ &0D6C/D=>Base of OSBYTE variables LDX #&04:JSR L82E7 LDY #&FD:JSR L85DD :\ Read OSBYTE &FD - Break type TXA:AND #&03 :\ A=Break type CMP #&01:BCC L80FA :\ Soft Break, skip past LDX #&01 LDY #&F5:JSR L85DA :\ Set OSBYTE &F5 to &01, Printer=Parallel SEC :\ SEC=use default serial speed .L80FA JSR L8464 :\ Initialise serial interface PLA:TAY:JMP L80BE :\ Restore and return \ SERVICE 5 - Interrupt \ ===================== .L8102 LDA #&02 :\ Test bit 1 BIT &0D68:BNE L8117 :\ If IRQ Ignore, exit LDA &FC65 :\ Get 6281 IRQ register AND &0D6A:BMI L811A :\ Mask with 6281 IRQ, b7=input port changed (CTS) LSR A:BCS L8127 :\ b0 set -> TxRDY LSR A:BCS L8166 :\ b1 set -> RxRDY .L8117 JMP L80BE :\ Restore all and return unclaimed .L811A LDA #&04 :\ Test bit 2, CTS on IP2 BIT &FC64:BNE L8124 :\ CTS not changed JSR L84AD :\ Emable serial transmitter .L8124 JMP L80C3 :\ Claim call and return .L8127 LDA #&04 :\ Test CTS in bit 2 BIT &FC6D:BNE L8160 :\ Not CTS ok, skip to set serial inactive JSR L84D4 :\ Get byte from SerOut buffer BCC L8148 :\ If not empty, write it to SerTx LDY #&F5:JSR L85DD :\ Read OSBYTE &F5 - Printer type CPX #&02:BNE L8150 :\ Not 2=Serial, skip to check CTS and exit JSR L84DA :\ Get byte from Printer Buffer PHA:PHP JSR L8603 :\ Set/Clear printer Buffer Busy flag PLP:PLA BCS L8150 :\ Printer Buffer was empty, skip past .L8148 STA &FC63 :\ Write byte to DataTx LDX #&00:JMP L8158 :\ Set SerialFlag to 0 and return .L8150 JSR L84BE :\ Set serial inactive JSR L8258 :\ Set/Clear CTS from buffer space LDX #&FF :\ Set SerialFlag to &FF and return .L8158 LDY #&BF:JSR L85DA :\ Write to OSBYTE &BF - Serial Use flag JMP L80C3 :\ Claim call and return .L8160 JSR L84BE :\ Set serial inactive JMP L80C3 :\ Claim call and return .L8166 LDX &FC63 :\ Read from 2681 Data Register LDA &FC61 :\ Read from 2681 Status Register AND #&F0:BNE L8181 :\ If any error bit set, skip to generate event TXA:JSR L84CF :\ Insert into serial input buffer JSR L84E0:BCS L817E :\ At least 8 bytes left, exit LDA #&01:STA &FC6F :\ Raise RTS to stop other end sending .L817E JMP L80C3 :\ Claim and return .L8181 TXA:PHA :\ Save byte read LDX &FC61 :\ Read from 2681 Status again JSR L84A1 :\ Reset 6281 Error Status PLA :\ Get byte back LDY #&07:JSR &FFBF :\ Generate Event 7 - Serial Error JMP L80C3 :\ Claim and return \ SERVICE &15 - 100Hz Poll \ ======================== .L8192 TYA:PHA :\ Save semaphore LDA #&40:BIT &0D68 :\ Check printer buffer active BEQ L819E:JSR L81DE :\ If active, try to send character to printer .L819E LDA #&20:BIT &0D68 :\ Check if ADC active BEQ L81A8:JSR L8202 :\ If active, check for ADC conversion .L81A8 LDA #&10:BIT &0D68 :\ Check if serial active BEQ L81B2:JSR L8258 :\ If active, check CTS level .L81B2 PLA:TAY :\ Restore semaphore JMP L80BE :\ Return unclaimed \ SERVICE & 13 - Character entering serial output buffer \ ====================================================== .L81B7 JSR L84AD :\ Enable serial transmitter JSR L825F :\ Set/Clear CTS if input buffer almost full JMP L80C3 :\ Claim call and return \ SERVICE &14 - Character entering printer output buffer \ ====================================================== .L81C0 TYA:PHA :\ Preserve Y JSR L81CA :\ Process output character PLA:TAY:JMP L80C3 :\ Restore, claim call and return .L81CA LDY #&F5:JSR L85DD :\ Get OSBYTE &F5 - Printer Type CPX #&01:BEQ L81DE :\ Type=1 - Parallel printer CPX #&02:BNE L81DD :\ Type=2 - Serial printer \ Output to serial printer \ ------------------------ JSR L84AD :\ Enable serial transmitter JSR L825F :\ Set/Clear CTS if input buffer almost full .L81DD RTS \ Output to parallel printer \ -------------------------- .L81DE BIT &FC72:BMI L81FD :\ If printer busy, turn 100Hz poll on and return JSR L84DA :\ Get character from printer buffer BCS L81F4 :\ If buffer empty, turn off 100Hz poll STA &FC71 :\ Send to printer port LDA #&40:JSR L84F1 :\ Set b6 of &0D68, turn on 100Hz poll CLC:JMP L81FA :\ Clear Printer Buffer Busy flag and return \ Printer buffer empty \ -------------------- .L81F4 LDA #&40:JSR L8505 :\ Clear b6 of &0D68, turn off 100Hz poll SEC :\ Set b7 of &02C6 and return :\ Set Serial Error event flag .L81FA JMP L8603 :\ Set/Clear Printer Buffer Busy flag \ Printer busy \ ------------ .L81FD LDA #&40:JMP L84F1 :\ Set b6 of &0D68, turn on 100Hz poll \ Check for ADC conversion \ ======================== .L8202 BIT &FC72:BVS L823B :\ If no ADC ready, return LDY #&BC:JSR L85DD :\ Get OSBYTE &BC - Current ADC channel TXA:BEQ L823B :\ No ADC channel, return LDA #&00:STA &02F7,X :\ Set low byte to zero LDA &FC70:STA &02FB,X :\ Set high byte from ADC STX &02F7 :\ Store as last channel converted LDY #&03:JSR &FFBF :\ Event 3 - ADC complete LDX &02F7 :\ Get last channel converted DEX :\ Step down to next channel BNE L8238 :\ If nonzero, start this channel LDY #&BD:JSR L85DD :\ Get OSBYTE &BD - Max. ADC Channel TXA:BNE L8238 :\ If nonzero, start this channel LDA #&20:JSR L8505 :\ Clear b5 of &0D68, turn off 100Hz poll JMP L823B :\ Return .L8238 JSR L823C :\ Check channel number .L823B RTS :\ Return .L823C CPX #&05:BCC L8242 :\ If channel<5, use it LDX #&04 :\ Channel>4, force to channel 4 .L8242 TXA:PHA LDY #&BC:JSR L85DA :\ Write to OSBYTE &BC - Current ADC Channel PLA:TAX:BEQ L8253 :\ If channel zero, exit LDA L8254-1,X :\ Get control value for this channel STA &FC70 :\ Write to ADC control .L8253 RTS \ ADC control values \ ------------------ .L8254 EQUB &04:EQUB &05 EQUB &06:EQUB &07 \ Set CTS according to input buffer state \ --------------------------------------- .L8258 LDA &0D6A AND #&02:BEQ L8264 :\ Serial input buffer inactive, raise CTS \ Set/Clear CTS if serial input buffer nearly full \ ------------------------------------------------ .L825F JSR L84E0 :\ Count space in serial input buffer BCS L826A :\ Still space left in input buffer .L8264 LDA #&01:STA &FC6F :\ Raise RTS to pause sender RTS .L826A LDA #&01:STA &FC6E :\ Lower RTS to unpause sender RTS \ OSBYTE &A3 - Application call \ ============================= .L8270 LDA &F0 :\ Get OSBYTE 163,X parameter CMP #&80:BNE L8283 :\ Not reason &80, exit LDX &F1:BEQ L8286 :\ Subcall &00 DEX:BEQ L8295 :\ Subcall &01 DEX:BEQ L82A9 :\ Subcall &02 DEX:BEQ L82B4 :\ Subcall &03 .L8283 JMP L80BE :\ Restore and return unclaimed \ OSBYTE 163,128,0 \ ---------------- .L8286 LDA &0D68:PHA :\ Get Plus1 flags AND #&FE:STA &0D68 :\ Remove 'Plus1 disabled' JSR L8560 :\ Enable Plus1 JMP L82A1 :\ Jump to return old flags \ OSBYTE 163,128,1 - Disable Plus1 \ -------------------------------- .L8295 LDA &0D68:PHA :\ Get Plus1 flags ORA #&01:STA &0D68 :\ Set 'Plus1 disabled' JSR L853F :\ Disable Plus1 .L82A1 PLA:AND #&01 :\ Get old Plus1 flags STA &F0 :\ Return it in X JMP L80C3 :\ Jump to claim call \ OSBYTE 163,128,2 - Enable serial \ -------------------------------- .L82A9 LDA &0D68 :\ Get Plus1 flags AND #&FD:STA &0D68 :\ Remove 'Ignore serial' JMP L80C3 :\ Jump to claim call \ OSBYTE 163,128,3 - Disable serial \ --------------------------------- .L82B4 LDA &0D68 :\ Get Plus1 flags ORA #&02:STA &0D68 :\ Set 'Ignore serial' JMP L80C3 :\ Jump to claim call .L82BF JMP L80BE :\ Return unclaimed \ OSBYTE &80 - ADVAL \ ================== \ ADVAL 1-4 are performed by MOS .L82C2 LDA &F0:BNE L82BF :\ Not ADVAL(0), exit LDA &FC72:PHA :\ Read Plus 1 status BPL L82CF:JSR L81CA :\ If printer not busy, try to send a character .L82CF PLA:LSR A:LSR A :\ Move fire buttons into b0-b1 LSR A:LSR A AND #&03:EOR #&03 :\ Keep and toggle b0-b1 STA &F0 :\ Return in Y - b8-b15 of ADVAL result JMP L80C3 :\ Claim call and return \ OSBYTE &10 - Maximum ADC channel \ ================================ .L82DD LDX &F0:JSR L82E7 :\ Set maximum ADC channel STX &F0 :\ Set returned X to maximum actually set JMP L80C3 :\ Claim call and return .L82E7 TXA:BEQ L82F4 :\ Zero channels, set and return PHA JSR L823C :\ Check within range and initialise ADC LDA #&20:JSR L84F1 :\ Enable 100Hz poll for ADC PLA .L82F4 TAX LDY #&BD:JMP L85DA :\ Store in OSBYTE &BD - Max. ADC channel \ OSBYTE &11 - Start ADC conversion \ ================================= .L82FA LDA #&00:STA &02F7 :\ Clear 'last channel' LDX &F0:JSR L823C :\ Start conversion on channel X LDA #&20:JSR L84F1 :\ Enable 100Hz poll for ADC JMP L80C3 :\ Claim call and return \ OSBYTE &6E - Write to ROMSTROBE \ =============================== \ Writes X to ROMSTROBE at &FC73 and RAM copy at &0D6B \ Returns old ROMSTROBE from RAM copy \ .L830C LDX &F0 :\ Get new ROMSTROBE from X parameter LDA &0D6B :\ Get old ROMSTROBE STX &0D6B:STX &FC73 :\ Store new ROMSTROBE and output it STA &F0 :\ Return old ROMSTORE in X JMP L80C3 :\ Claim call and return \ SERVICE 7 - OSBYTE \ ================== .L831C LDA &EF :\ Get OSBYTE number CMP #&80:BEQ L82C2 :\ &80 - ADVAL CMP #&10:BEQ L82DD :\ *FX16 - Maximum ADC channel CMP #&11:BEQ L82FA :\ *FX17 - Start ADC conversion CMP #&07:BEQ L8348 :\ *FX7 - serial receive speed CMP #&08:BEQ L834F :\ *FX8 - serial transmit speed CMP #&9C:BEQ L839B :\ &9C - serial control CMP #&02:BEQ L8372 :\ *FX2 - input stream CMP #&6E:BEQ L830C :\ *FX110 - write to ROMSTROBE CMP #&A3:BNE L8345 JMP L8270 :\ &A3 - application call .L8345 JMP L80BE \ OSBYTE 7 and 8 - set serial speed \ ================================= \ On entry, X=baud rate setting (0=default) \ On exit X=control register setting that wasn't changed \ OSBYTE &07 - Serial receive speed \ ---------------------------------- .L8348 LDA #&F0:STA &F1 :\ Set &F1 to &F0 for 'receive' JMP L8353 \ OSBYTE &08 - Serial transmit speed \ ---------------------------------- .L834F LDA #&0F:STA &F1 :\ Set &F1 to &0F for 'transmit' \ Set serial speed, &F1=control mask \ ---------------------------------- .L8353 LDX &F0 :\ Get OSBYTE X value CPX #&0C:BCS L836F :\ If speed>11, exit unchanged LDA &F1:EOR #&FF :\ Get mask and toggle it AND &0D69 :\ Mask with current baud register copy STA &F0 :\ Keep the bits we aren't going to change LDA L8417,X :\ Translate X to baud rate control value AND &F1 :\ Mask to keep the half we are going to change ORA &F0 :\ Merge with current setting STA &0D69 :\ Update the baud register RAM copy STA &FC61 :\ Store in baud register .L836F JMP L80C3 :\ Claim call and return \ OSBYTE &02 - select input stream \ ================================ .L8372 LDA &F0:PHA :\ Save OSBYTE X value, input source AND #&01:TAX :\ Keep bit 0, keyboard/serial select LDY #&B1:JSR L85DA :\ Store in OSBYTE &B1 - Input source PLA:BEQ L83D6 :\ Get original selection, exit if X=0, serial disabled LDA #&01:STA &FC62 :\ Enable serial input LDA &0D6A:ORA #&02 :\ Enable receive interupts STA &0D6A:STA &FC65 :\ Write to IRQ mask and 6281 IRQ register JSR L8258 :\ Set/Clear CTS LDA #&10:JSR L84F1 :\ Increment ROM polling register if needed JMP L80C3 :\ Claim call and return \ OSBYTE &9C - serial control \ =========================== \ On entry, Y=action, X=parameters, in 6850 format .L839B LDA #&E3 :\ *FX156,x,227 to set word format CMP &F1:BNE L83F7 :\ Not Y=227 \ Y=227, set serial word format \ ----------------------------- BIT &F0:BNE L83D3 :\ X must be %000xxx00 LDA &F0 :\ Get X parameter LSR A:LSR A:NOP:TAX :\ Move up two bits JSR L84A7 :\ Select control register &10 LDA &FC60 :\ Read from control register &10 AND #&E0:STA &F1 :\ Save temporarily \ Manipulate stuff to set serial word size JSR L84A7 :\ Select control register &10 LDA L8423,X :\ AND #&1F :\ ORA &F1 :\ STA &FC60 :\ Write to control register LDA &FC60 :\ Read from control register AND #&F0 :\ Keep b7-b4 LDY L8423,X BMI L83CE :\ If b7 set, skip ORA #&0F :\ If b7 clear, set b3-b0 .L83CE ORA #&07 :\ Set to %xxxxx111 STA &FC60 :\ Write to control register .L83D3 JMP L80C3 :\ Claim call and return \ Turn off serial input \ --------------------- .L83D6 LDA #&02:STA &FC62 :\ Disable receiver JSR L8495 :\ Reset reciever JSR L84A1 :\ Reset error status LDA &0D6A:AND #&FD :\ Reset serial input IRQ STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register JSR L8258 :\ Set/Clear CTS LDA #&10:JSR L8505 :\ Clear b4 of flags, turn off polling JMP L80C3 :\ Claim call and return .L83F7 LDA #&9F :\ *FX156,x,159 for a serial break CMP &F1:BNE L83D3 :\ Not Y=159, exit \ Y=159, start/stop a serial break \ -------------------------------- BIT &F0:BNE L83D3 :\ X must be %0xx00000 LDA &F0 :\ Get X parameter CMP #&60:BEQ L840F :\ *FX156,96,159 - start a break LDA #&70:STA &FC62 :\ Else, stop transmitting a break JMP L83D3 :\ Claim call and return .L840F LDA #&64:STA &FC62 :\ Start transmitting a break JMP L83D3 :\ Claim call and return \ Baud rate look-up table \ ----------------------- .L8417 EQUB &BB:EQUB &00:EQUB &33 :\ 0=9600, 1=75, 2=150 EQUB &44:EQUB &66:EQUB &88 :\ 3=300, 4=1200, 5=2400 EQUB &99:EQUB &BB:EQUB &CC :\ 6=4800, 7=9600, 8=19200 EQUB &11:EQUB &55:EQUB &AA :\ 9=110, 10=600, 11=1800 \ Serial control look-up table \ ---------------------------- .L8423 EQUB &02:EQUB &06:EQUB &82:EQUB &86 EQUB &13:EQUB &93:EQUB &83:EQUB &87 \ SERVICE 9 - *Help \ ================= .L842B TYA:PHA LDX #&00 .L842F LDA L8440,X:BEQ L843B :\ Print help message JSR OSASCI:INX:JMP L842F .L843B PLA:TAY:JMP L80BE :\ Restore and return .L8440 EQUS "Expansion 1.00":EQUB 13 EQUS " ADC/Printer/RS423":EQUB 13 EQUB 0 \ Initialise serial interface \ --------------------------- \ CC=use current settings, CS=use default settings .L8464 JSR L84A7 :\ Reset MC6281 MR pointer LDA #&93:STA &FC60 :\ First write, RTS=enabled, NoParity, 8bit LDA #&07:STA &FC60 :\ Second write, StopBit=1 bit length LDA #&8F:STA &FC64 :\ Set AuxControl to Baud Rate 2, IRQs on LDA &0D69:BCC L847D :\ Get current baud setting LDA #&BB :\ if CS, get default baud rate=9600 .L847D STA &0D69:STA &FC61 :\ Set baud register and RAM copy JSR L8495 :\ Reset 6821 receiver JSR L849B :\ Reset 6821 transmitter JSR L84A1 :\ Reset 6821 error status LDA #&80:STA &0D6A :\ Set IRQ mask to allow serial interupts STA &FC65 :\ Enable 6821 interupts RTS .L8495 LDA #&20:STA &FC62:RTS :\ &20=Reset Receiver .L849B LDA #&30:STA &FC62:RTS :\ &30=Reset Transmitter .L84A1 LDA #&40:STA &FC62:RTS :\ &40=Reset Error Status .L84A7 LDA #&10:STA &FC62:RTS :\ &10=Reset 6821 MR pointer \ Enable serial transmitter \ ------------------------- .L84AD LDA &0D6A:ORA #&01 :\ Set serial buffer active STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register LDA #&04:STA &FC62 :\ Write &04=Transmitter Enabled to command register RTS .L84BE LDA &0D6A:AND #&FE :\ Set serial buffer inactive STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register .L84C9 LDA #&08:STA &FC62 :\ Write &08=Transmitter Disabled to command register RTS .L84CF LDX #&01 :\ X=1 - serial input buffer JMP (&022A) :\ Jump to INSV .L84D4 CLV :\ CLV=remove character LDX #&02 :\ X=2 - serial output buffer JMP (&022C) :\ Jump to REMV .L84DA CLV :\ CLV=remove character LDX #&03 :\ X=3 - printer buffer JMP (&022C) :\ Jump to REMV \ Count space left in serial input buffer \ --------------------------------------- \ Returns CS=more than 8 bytes left \ CC=less than 8 bytes left .L84E0 JSR L84EA :\ Count space in serial input buffer CPY #&01:BCS L84E9 :\ If >&00FF, return CS CPX #&09 :\ If >&0008, return CS .L84E9 RTS .L84EA SEC :\ SEC=count space left CLV :\ CLV=count buffer LDX #&01 :\ X=1 - serial input buffer JMP (&022E) :\ Jump to CNPV .L84F1 ORA &0D68 :\ Merge into current flags LDX &0D68 :\ Get old value of flags to X STA &0D68 :\ Store updated flags TXA :\ Get old flags into A AND #&F0:BNE L8504 :\ If old flags had polling enabled, exit : :\ We've changed to needing polling, increment semaphore .L84FF LDA #&16:JSR OSBYTE :\ Inc. ROM polling semaphore .L8504 RTS .L8505 TAX :\ Save mask in X LDA #&F0:BIT &0D68 :\ Check current polling flags BEQ L851F :\ No flags have polling enabled, exit TXA:EOR #&FF :\ Get mask back and toggle it AND &0D68:STA &0D68 :\ Remove the bit and update flags AND #&F0:BNE L851F :\ If any polling enabled, exit : :\ Nothing left needing polling, decrement semaphor .L851A LDA #&17:JSR OSBYTE :\ Dec. ROM polling semaphore .L851F RTS \ SERVICE 6 - Error \ ================= .L8520 LDA #&01:BIT &0D68:BNE L853C :\ Not temporarily disabled, skip LDA &EF:PHA LDA &F0:PHA:LDA &F1:PHA :\ Save OSBYTE/OSWORD parameters JSR L8560 PLA:STA &F1:PLA:STA &F0 PLA:STA &EF .L853C JMP L80BE :\ Restore and return unclaimed \ Disable Plus 1 functions \ ======================== \ Called on way to calling vector, so all registers need to be saved .L853F PHA:TXA:PHA:TYA:PHA LDA &0D68:BMI L855A :\ Bit 7 set, already disabled PHA ORA #&80:STA &0D68 :\ Set bit 7 of flags PLA:BEQ L855A :\ No handlers to disable JSR L851A :\ Decrement ROM polling semaphore LDA #&01:STA &FC6F :\ Raise 'RTS', stop serial sender .L855A PLA:TAY:PLA:TAX:PLA RTS \ Enable Plus 1 functions \ ======================= \ Called after calling filing vector, so all registers need to be saved .L8560 PHA:TXA:PHA:TYA:PHA LDA &0D68:BPL L8577 :\ Bit 7 clear, already enabled AND #&7F:STA &0D68 :\ Clear bit 7 of flags BEQ L8577 :\ No handlers to enable JSR L84FF :\ Increment ROM polling semaphore JSR L8258 :\ Restore CTS state .L8577 PLA:TAY:PLA:TAX:PLA RTS \ SERVICE &0F - Vectors changed \ ============================= \ If vectors changed, and now using TAPE/ROM, intercept \ FILEV to prevent Plus1 interfering with tape action. \ .L857D LDA #&00:TAY:JSR OSARGS :\ Read current filing system CMP #&03:BCS L85CB :\ Not TAPE/ROM, exit CMP #&00:BEQ L85CB :\ No FS, exit LDA &0212:STA &0D6E :\ Save FILEV LDA &0213:STA &0D6F CMP #&FF:BEQ L85CB :\ Already redirected, skip past LDY #&A8:JSR L85DD :\ Read base of extended vectors PHP:SEI :\ Disable IRQs while changing vectors LDA &FD:PHA:LDA &FE:PHA :\ Save FD/E for workspace STX &FD:STY &FE :\ &FD/E=>extended vectors LDY #&1B:STY &0212 :\ FILEV=>extended vector LDA #&FF:STA &0213 LDA #L85CE AND 255 :\ Point XFILEV=>L85CE STA (&FD),Y:INY LDA #L85CE DIV 256 STA (&FD),Y:INY LDA &F4:STA (&FD),Y :\ This ROM PLA:STA &FE:PLA:STA &FD :\ Restore workspace PLP :\ Restore IRQs .L85CB JMP L80BE \ Redirected FILEV \ ---------------- .L85CE JSR L853F :\ Disable Plus1 JSR L85D7 :\ Call saved FILEV JMP L8560 :\ Enable Plus1 .L85D7 JMP (&0D6E) :\ Jump to saved FILEV \ Read or write OSBYTE variable directly \ ====================================== \ CS Y=OSBYTE number, X=byte to write \ CC Y=OSBYTE number, returns X=byte read, Y=next byte \ .L85DA SEC:BCS L85DE :\ CS to write byte .L85DD CLC :\ CC to read byte .L85DE LDA &FD:PHA:LDA &FE:PHA :\ Save to use as pointer LDA &0D6C:STA &FD :\ Point to OSBYTE variables base LDA &0D6D:STA &FE BCC L85F5 :\ Skip past to read TXA:STA (&FD),Y :\ Write byte BCS L85FC :\ Branch to exit .L85F5 LDA (&FD),Y:TAX :\ Get byte INY:LDA (&FD),Y:TAY :\ Get next byte .L85FC PLA:STA &FE:PLA:STA &FD :\ Restore RTS \ Set/Clear buffer 3 busy flag \ ---------------------------- .L8603 ROR &02C6:RTS :\ Move Carry into Busy flag : ]:IF O%>L%:PRINT "Code overrun":END NEXT OSCLI"Save "+file$+" "+STR$~mcode%+" "+STR$~O%+" 0 FFFBBC00" OSCLI"Stamp "+file$ ON ERROR ON ERROR OFF:END *Quit