;////////////////////////////////////////////////////////////////////////////// ; TITLE 'MEX Overlay for Toshiba T100 and Serial Interface Adapter ' ; ; NOTE - this overlay is designed to be specific for a Toshiba T00 ; together with a Hayes Smartmodem 300/1200 driven in conjunction with ; a Toshiba Support Group Serial Async Interface Adapter. ; ; --- A very good starting point for ANY 2651 usart IO device, however. ; ;////////////////////////////////////////////////////////////////////////////// ; REV EQU 10 ; revision number * 10 ; ;****************************************************************************** ; ; One problem with the Toshiba T100 is the inabillity to do 1200 ; bps. This is due to the fact that Toshiba, for some reason - which is ; completely beyond comprehension of civilized man - had decided to ; implement a software usart on an 8255 PIA. It is impossible to get ; 1200 bps out of the infernal thing. Need I say that 300 bps gets ; a bit frustrating to sysops, including myself. Well, to solve the ; problem, I've designed a serial interface with a National INS2651 ; usart to get up to 19.2K baud out of the Tosh. (I don't own a Tosh, ; but I got tired of all of the bitching about not being able to do ; 1200 with the thing). Tha adapter plugs into the rampack 2 expansion ; slot. You still can use slot 1 for the prom expansion. ; ; Tosh does furnish a serial port adapter - matter of fact, they are ; glad to sell you one. So would I at $400.00+ - arrghhhh ... gag me with ; a microchip.... whats that old saying coined by Ward..... ; ; Sempus Non Rippus Offis ; ; My adapter goes for about 40 bucks (+/-) in small quanity. If there ; is a demand for it, this will be reduced as it costs a lot less to ; build 100 of 'em than it does 10. If you are 1) a poor soul with a ; Tosh, 2) are tired of paying Ma Bell and 3) would really like to do ; 1200/2400 all the way up to 19,200 (dream on, we all wish...) baud on ; dialups, then contact me, the Sysop at Smokin Silicon RCP/M to leave ; a private message in 'TOS' - Ill get back to you. Smokin Silicon is ; the central point for the Toshiba Support group. If Toshiba won't ; support it at a reasonable price, We will. I'll be happy to fill yall ; in on the details. Flawless performance in computer <=> computer batch ; xfers with MEX at 9600 bps. This is the first in a series of RCPM ; overlays to support the serial adapter and the machine. ; ; modem to the max / happy hacking ; ; JP Sojak - sysop - ; Smokin Silicon RCP/M ; (312)941-0049 24 hrs ; ; ps - if you have a special problem with your machine, Ill try to help out. ; By helping you out, many benifit. (Sempus Non Rippus Offis - FIGHT ; BACK - don't put up with the garbage many manufactures try to feed ; you) ; ;****************************************************************************** ; ; 02/24/84 ... mxo-tsa.asm (for TS A-dapter) ; ; Base version for a Toshiba T100 and a serial adapter. Roots ; are everywhere by a cast of thousands. Thanks all... ; - Especially Ron Fowler for doing the single most important ; public domain work since the original Modem7 ; ; JP Sojak ; ;////////////////////////////////////////////////////////////////////////////// ; ; There is a Zilog SIO style full featured SET command implemented on ; the INS2651 USART device ... The SET is specific to Smartmodem ; compatables. The available commands are: ; ; delay (seconds) .... SET the delay between dial and "NO CARRIER" ; baud 110-19.2k .. SET the baud rate 110-19.2K, no 450 and 710 ; orig (originate mode) .. SET the modem originate (callout) carrier ; answer (answer mode) .. SET the modem answer (callin) carrier ; tone ................... SET touch tone dialing ; pulse .................. SET pulse dialing ; monitor ................ SET the speaker ON ; quiet .................. SET the speaker OFF ; parity ................. SET the parity to odd, even, or none ; stop ................... SET 1, 1.5, or 2 stopbits ; bits ................... SET 5, 6, 7, or 8 bit data word length ; digit .................. SET the interdigit dial time in mS ; ; "SET" will bring up the current settings. ; "SET ?" will bring up the syntax for the SET commands available. ; And additionally, all 'SET'tings are 100% cloneable to new defaults. ; ;////////////////////////////////////////////////////////////////////////////// ; ; adapter port definitions ; BASEP EQU 018H ; port base address DATAPT EQU BASEP ; serial data port SPORT EQU BASEP+1 ; status register MODE1 EQU BASEP+2 ; first mode register MODE2 EQU BASEP+2 ; second mode register CPORT EQU BASEP+3 ; command register ; ; ; 2651 usart bit definitions ; MDRCVB EQU 00000010B ; modem receive bit (dav) MDRCVR EQU 00000010B ; modem receive ready MDSNDB EQU 00000001B ; modem send bit MDSNDR EQU 00000001B ; modem send ready bit MDMDTR EQU 00000010B ; modem data trm ready bit ; ; PLEASE NOTE ... The use of DCD (Data Carrier Detect) status register bit ; within the USART should be avoided. It is actually a Tx enable for the ; hardware. It MUST be pulled high on the EIA cable or the USART will seem ; to "hang". When it is active, the initialization routine thinks there ; is returning from CP/M with a carrier present even when there isnt - ; improper switch settings could unconditionally force an active (HIGH) state ; - and abort the routine. The adapter has been defaulted with a pullup to ; avoid "hanging" the hardware if the DCD #8 is left unconnected. It is ; desirable to redefine the carrier sence bit to DSR #6 (Data Set Ready). It ; is customary to leave DCD #8 open on the interface side and connect DCD #8 ; from the modem to DSR #6 (Data Set Ready) on the interface side. In this ; way, the USART will never "hang". If you wish to use DCD then by all means ; do so. As a matter of fact, ANY rcpm work REQUIRES it, but if you do not ; follow what all of this is about, then it is best to leave the equate as ; is and prepare a cable as follows.... ; ; MODEM INTERFACE ; (DCE) (DTE) ; ; #1 <------------------------> #1 water pipe ground (optional) ; #2 <------------------------> #2 \ ; (Tx and Rx data) ; #3 <------------------------> #3 / ; ; #7 <------------------------> #7 Signal Ground ; (DCD) #8 <------------------------> #6 Data Set Ready ; #20 <------------------------> #20 Data Terminal Ready ; ; ;MDMDCD EQU 01000000B ; DCD used to sence carrier present ; MDMDCD EQU 10000000B ; DSR used to sence a carrier present ; ; ;****************************************************************************** ; ; Status register definitions within the 8251 USART device: ; ; MODE 0 REGISTER (base + 2) ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; | 00 - invalid | X0 - no parity | 00 - 5 bits | must be | ; | 01 - 1 stop | 01 - odd | 01 - 6 bits | 1 | 0 | ; | 10 - 1.5 stop | 10 - no parity | 10 - 7 bits | for the adapter | ; | 11 - 2 stops | 11 - even | 11 - 8 bits | | | ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; ; MODE 1 REGISTER (base + 2) ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; | | | must be | internal baud rate select register| ; | X | X | 1 | 1 | + + + | ; | | | for the adapter| B3 | B2 | B1 | B0 | ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; ; Where the internal generator is selected and is represented by: ; ; NOTE - some of these are NOT supported by MEX - the USART does em, ; but MEX has no idea they exist. ; ; Bx= 3 2 1 0 | 3 2 1 0 ; ----------------------------+------------------------------- ; 0 0 0 0 .... 50 baud | 0 0 0 1 .... 75 baud ; 0 0 1 0 .... 110 baud | 0 0 1 1 .... 134.5 baud ; 0 1 0 0 .... 150 baud | 0 0 0 1 .... 300 baud ; 0 1 1 0 .... 600 baud | 0 1 1 1 .... 1200 baud ; 1 0 0 0 .... 1800 baud | 1 0 0 1 .... 2000 baud ; 1 0 1 0 .... 2400 baud | 1 0 1 1 .... 3600 baud ; 1 1 0 0 .... 4800 baud | 1 1 0 1 .... 7200 baud ; 1 1 1 0 .... 9600 baud | 1 1 1 1 .... 19.2K baud ; ; COMMAND REGISTER (base + 3) ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; | 00 - normal | RTS | ERROR | FORCE | RECV | DTR | TRNSMT | ; | 01 - auto echo | CTRL | RESET | BREAK | CTRL | CTRL | CTRL | ; | 10 - lcl lopbak | 0 - hi | 0 -norm| 0 -norm| 0 -dsbl| 0 -hi | 0 -dsbl| ; | 11 - rmt lopbak | 1 - lo | 1 -rst | 1 -brk | 1 -enbl| 1 -lo | 1 -enbl| ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; ; STATUS REGISTER (base + 1) ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; | | | FRAME | OVERRUN| PARITY |Tx SHIFT| Rx CHAR| Tx BUFR| ; | DSR lo | DCD lo | ERROR | ERROR | ERRORY |REGISTER| READY | EMPTY | ; | | | | | | EMPTY | | | ; +--------+--------+--------+--------+--------+--------+--------+--------+ ; ; MODE 1 register must be written into before MODE 2 - it is a toggle ; type operation. a COMMAND register operation will reset the ; toggle so the next MODE operation will be performed on the first ; register - REGISTER 1. ; ;****************************************************************************** ; ; standard mex service processor hooks ; MEX EQU 0D00H ;address of the service processor INMDM EQU 255 ;get char from port to a, cy=no more in 100 ms TIMER EQU 254 ;delay 100ms * reg b TMDINP EQU 253 ;b=# secs to wait for char, cy=no char CHEKCC EQU 252 ;check for ^c from kbd, z=present SNDRDY EQU 251 ;test for modem-send ready RCVRDY EQU 250 ;test for modem-receive ready SNDCHR EQU 249 ;send a character to the modem (after sndrdy) RCVCHR EQU 248 ;recv a char from modem (after rcvrdy) LOOKUP EQU 247 ;table search: see cmdtbl comments for info PARSFN EQU 246 ;parse filename from input stream BDPARS EQU 245 ;parse baud-rate from input stream SBLANK EQU 244 ;scan input stream to next non-blank EVALA EQU 243 ;evaluate numeric from input stream LKAHED EQU 242 ;get nxt char w/o removing from input GNC EQU 241 ;get char from input, cy=1 if none ILP EQU 240 ;inline print DECOUT EQU 239 ;decimal output PRBAUD EQU 238 ;print baud rate ; CONOUT EQU 2 ;simulated bdos function 2: console char out PRINT EQU 9 ;simulated bdos function 9: print string INBUF EQU 10 ;input buffer, same structure as bdos 10 ; ; msc crud ; TPA EQU 100H CR EQU 13 LF EQU 10 TAB EQU 9 DING EQU 'G'-40H ; YES EQU 0FFFFH ;it is so NO EQU NOT YES ;it is not so ; ;////////////////////////////////////////////////////////////////////////////// ; ORG TPA ; ;////////////////////////////////////////////////////////////////////////////// ; DS 3 ;mex has a jmp start here DS 2 ;not used by mex TPULSE: DB 'T' ;t=touch, p=pulse (used by this overlay) CLOCK: DB 40 ;clock speed x 10 (up to 25.5 mhz.) MSPEED: DB 5 ;sets display time for sending a file ;0=110 1=300 2=450 3=600 4=710 ;5=1200 6=2400 7=4800 8=9600 9=19200 BYTDLY: DB 5 ;default time to send character in ;terminal mode file transfer (0-9) ;0=0 delay, 1=10 ms, 5=50 ms, 9=90 ms CRDLY: DB 5 ;end-of-line delay after crlf in terminal ;mode file transfer for slow bbs systems ;0=0 delay, 1=100 ms, 5=500 ms, 9=900 ms COLUMS: DB 5 ;number of directory columns SETFL: DB YES ;yes=user-defined set command SCRTST: DB YES ;yes=if home cursor and clear screen ;routine at clrscrn DB 0 ;was once acknak, now spare BAKFLG: DB YES ;yes=make .bak file CRCDFL: DB YES ;yes=default to crc checking ;no=default to checksum checking TOGCRC: DB YES ;yes=allow toggling of checksum to crc CVTBS: DB NO ;yes=convert backspace to rub TOGLBK: DB YES ;yes=allow toggling of bksp to rub ADDLF: DB NO ;no=no lf after cr to send file in ;terminal mode (added by remote echo) TOGLF: DB YES ;yes=allow toggling of lf after cr TRNLOG: DB NO ;yes=allow transmission of logon ;write logon sequence at location logon SAVCCP: DB YES ;yes=do not overwrite ccp LOCNXT: DB NO ;yes=local cmd if extchr precedes ;no=not local cmd if extchr precedes TOGLOC: DB YES ;yes=allow toggling of locnxtchr LSTTST: DB YES ;yes=allow toggling of printer on/off ;in terminal mode. set to no if using ;the printer port for the modem XOFTST: DB NO ;yes=allow testing of xoff from remote ;while sending a file in terminal mode XONWT: DB NO ;yes=wait for xon after sending cr while ;transmitting a file in terminal mode TOGXOF: DB YES ;yes=allow toggling of xoff testing IGNCTL: DB NO ;yes=do not send control characters ;above ctl-m to crt in terminal mode ;no=send any incoming ctl-char to crt EXTRA1: DB 0 ;for future expansion EXTRA2: DB 0 ;for future expansion BRKCHR: DB '@'-40H ;^@ = send a 300 ms. break tone NOCONN: DB 'N'-40H ;^n = disconnect from phone line LOGCHR: DB 'L'-40H ;^l = send logon LSTCHR: DB 'P'-40H ;^p = toggle printer UNSVCH: DB 'R'-40H ;^r = close input text buffer TRNCHR: DB 'T'-40H ;^t = transmit file to remote SAVCHR: DB 'Y'-40H ;^y = open input text buffer EXTCHR: DB '^'-40H ;^^ = send next character ; DS 2 ;not used ; ; low-level modem i/o routines. ; INCTL1: JMP INC ;in modem control port DB 0,0,0,0,0,0,0 ;spares if needed for non-pmmi ; OTDATA: JMP OUTD ;out modem data port DB 0,0,0,0,0,0,0 ;spares if needed for non=pmmi ; INPORT: JMP IND ;in modem data port DB 0,0,0,0,0,0,0 ;spares if needed for non-pmmi ; ; bit-test routines. ; MASKR: ANI MDRCVB ! RET ;bit to test for receive ready TESTR: CPI MDRCVR ! RET ;value of receive bit when ready MASKS: ANI MDSNDB ! RET ;bit to test for send ready TESTS: CPI MDSNDR ! RET ;value of send bit when ready ; DS 12 ; LOGON: DS 2 ;needed for mdm compat, not ref'D BY MEX DIALV: JMP DIAL DISCV: JMP DISCON GOODBV: JMP GOODBYE ;called before exit to cp/m INMODV: JMP NITMOD ;initialization. called at cold-start NEWBDV: JMP PBAUD ;set baud rate NOPARV: RET!NOP!NOP ;set modem for no-parity PARITV: RET!NOP!NOP ;set modem parity SETUPV: JMP SETCMD ;set cmd: jump to a ret if you don'T WRITE SET SPMENV: RET!NOP!NOP ;not used with mex VERSNV: JMP SYSVER ;overlay'S VOICE IN THE SIGN-ON MESSAGE BREAKV: JMP SBREAK ;send a break ; ; mdm calls supported in mex 1.0 but not recommended for use. ; ILPRTV: DS 3 ;replace with mex function 9 INBUFV: DS 3 ;replace with mex function 10 ILCMPV: DS 3 ;replace with table lookup funct. 247 INMDMV: DS 3 ;replace with mex function 255 NXSCRV: DS 3 ;not supported by mex (returns w/no action) TIMERV: DS 3 ;replace with mex function 254 ; ; terminal specific control sequences ; ; if you wish to use the terminal screen operations, uncomment the code below ; and insert your terminal specific routines at the clsmsg and eosmsg string ; areas. ; CLREOS: ; lxi d,eosmsg ; mvi c,print ; call mex RET ; CLS: ; lxi d,clsmsg ; mvi c,print ; call mex RET ; ; put your terminal specific strings here ... (I don't know what they are) ; ... dont forget the '$' ; EOSMSG: DB 17H,'$' ;clear to end-of-screen CLSMSG: DB 1AH,'$' ;clear whole screen ; ;------------------------------------------------------------ ; ; input control/status port ; INC: IN SPORT ; get the status bits RET ; ; input data port ; IND: IN DATAPT RET ; ; output data port ; OUTD: OUT DATAPT RET ; ; print out the overlay version ; SYSVER: CALL MILP DB 'Toshiba Support Group Serial Interface',CR,LF ; DB 'Trashiba T100 - V' ;he.. he.. he... DB 'Toshiba T100 - V' DB REV/10+'0' DB '.' DB REV MOD 10+'0' DB CR,LF DB 0 RET ; ; send break routine ; SBREAK: ; ; disconnect routine ; DISCON: ; ; goodbye routines are called by mex prior to exit to cp/m ; GOODBYE:MVI A,00011101B ; drop cts, dtr and force break a OUT CPORT MVI B,3 ; 300 ms CALL MTIME MVI A,00100111B ; initial default OUT CPORT RET ; ; initialize rs-232 to default modes. ; NITMOD: CALL INC ;see if carrier ie returning to mex with ANI MDMDCD ;a call active RNZ ;skip if connected LDA SPEED ; load default ascii baud rate STA MSPEED ;and keep it current CALL PBAUD ;set the baud rate ; ; default the modem to either speaker ON or OFF - as CLONED ; LDA MONFLG ;get monitor default ORA A MVI A,'0' ;speaker off JZ NIT4 MVI A,'1' ;speaker on NIT4: STA SMINIT+3 ;put it in sminit string ; ; default the modem mode to either answer or originate - as CLONED ; LDA ANSFLG ;get mode default ORA A MVI A,'0' ;originate JZ NIT5 MVI A,'1' ;answer NIT5: STA S0NIT+3 ;put it in sminit string ; ; set up the modem with the initial string ; LXI H,SMINIT SINIT: CALL SMSEND ;send the init string SMTLP1: MVI C,INMDM ;wait for modem response CALL MEX JNC SMTLP1 ;eat everything until silence for RET ; 100 msec ; ; set command processor ; SETCMD: MVI C,SBLANK ;any arguments? CALL MEX JC SETSHO ;if not, display default(s) LXI D,CMDTBL MVI C,LOOKUP CALL MEX ;parse the argument PUSH H ;save any parsed arguments on stack RNC ;if we have one, return to it POP H ;oops, input not found in table SETERR: LXI D,SETEMS MVI C,PRINT CALL MEX CALL CRLF RET SETEMS: DB CR,LF,'Unrecognized SET command',DING,CR,LF,'$' ; SETBAD: LXI D,SETBMS MVI C,PRINT CALL MEX RET SETBMS: DB CR,LF,'Invalid SET parameter',DING,CR,LF,'$' ; ; argument table ; CMDTBL: DB '?'+80H ; help DW SETHELP DB 'ORI','G'+80H ; originate mode DW ORIG DB 'ANSWE','R'+80H ; answer mode DW ANS DB 'TON','E'+80H ; tone dialing DW STTONE DB 'PULS','E'+80H ; pulse dialing DW STPULSE DB 'MONITO','R'+80H ; monitor on DW MONIT DB 'QUIE','T'+80H ; monitor off DW QUIET DB 'BAU','D'+80H ; set baud DW STBAUD DB 'DELA','Y'+80H ; set delay DW DELAY DB 'PARIT','Y'+80H ; set parity DW STPRTY DB 'STO','P'+80H ; set stopbits DW STSTOP DB 'BIT','S'+80H ; set length DW STBITS DB 'DIGI','T'+80H ; set inter-digit delay DW SDIGIT DB 0 ;table terminator ; ; "set (no args): print current statistics ; SETSHO: CALL MILP DB CR,LF DB 'Current settings:',CR,LF,0 CALL CRLF CALL TPSHOW CALL CRLF CALL BDSHOW CALL CRLF CALL MONSHO CALL CRLF CALL SHOWP CALL CRLF CALL SHOWS CALL CRLF CALL SHOWBT CALL CRLF CALL DLSHOW CALL CRLF CALL DDSHOW CALL CRLF CALL CRLF RET ; ; "set ?" processor ; SETHELP: CALL MILP DB CR,LF,'SET ORIG - Modem Originate mode' DB CR,LF,'SET ANSWER - Modem Answer mode' DB CR,LF,'SET TONE - Touch Tone dial' DB CR,LF,'SET PULSE - Dial Pulse dial' DB CR,LF,'SET PARITY - None, Even or Odd' DB CR,LF,'SET STOP - 1, 1.5 or 2' DB CR,LF,'SET BITS - 5, 6, 7 or 8' DB CR,LF,'SET QUIET - Speaker Off' DB CR,LF,'SET MONITOR - Speaker On' DB CR,LF,'SET BAUD - = 110, 300, 600, 1200, 2400, ' DB '4800, 9600, 19200' DB CR,LF,'SET DELAY - seconds' DB CR,LF,'SET DIGIT - 0-99 mS' DB CR,LF,CR,LF,0 RET ; ; "set baud" processor ; STBAUD: MVI C,BDPARS ;function code: parse a baudrate CALL MEX ;let mex look up code JC SETERR ;jump if invalid code CALL PBAUD ;no, try to set it JC SETERR ;if not one of ours, bomb out ; ; let MEX print the baud rate ; BDSHOW: LDA MSPEED ;get current baud rate MVI C,PRBAUD ;let mex print it CALL MEX RET ; ; this routine sets baud rate passed as mspeed code in a. ; returns cy=1 if baud rate not supported. ; PBAUD: PUSH H ;don't alter anyboby PUSH D PUSH B ; LXI H,BAUDS ; get the table base MOV E,A MVI D,00 DAD D ; offset it MOV A,M CPI 11111111B ; is it bad ? STC JZ BADEX ; yup - quit now ; ; selected rate is good ... save parameters ; STA DFTBAUD ; setup for reinitialization MOV A,E STA SPEED ; save it in case of CLONE command STA MSPEED CALL SINITL ; reinitialize the usart STC CMC ; no error here BADEX: POP B POP D POP H RET ; ; lookup table for all of the valid bit rates ; BAUDS: DB 00000010B ; 110 baud DB 00000101B ; 300 baud DB 11111111B ; 450 baud DB 00000110B ; 600 baud DB 11111111B ; 710 baud DB 00000111B ; 1200 baud DB 00001010B ; 2400 baud DB 00001100B ; 4800 baud DB 00001110B ; 9600 baud DB 00001111B ; 19.2k baud ; ; "set mode" processor ; ORIG: XRA A STA ANSFLG ;set orig flag LXI H,SMO ;send out ats0=0 CALL SINIT CALL MILP DB 'Originate mode',0 RET ; ANS: MVI A,0FFH STA ANSFLG ;set ans flag LXI H,SMA ;send out ats0=1 CALL SINIT CALL MILP DB 'Answer mode',0 RET ; SMO: DB 'ATS0=0',CR,0 SMA: DB 'ATS0=1',CR,0 ; ; ; "monitor" processor ; QUIET: XRA A STA MONFLG LXI H,SMQT CALL SINIT JMP MONSHO MONIT: MVI A,0FFH STA MONFLG LXI H,SMMON CALL SINIT MONSHO: LDA MONFLG ORA A JZ MONOFF CALL MILP DB 'Speaker On',0 RET MONOFF: CALL MILP DB 'Speaker Off',0 RET SMQT: DB 'ATM0',CR,0 SMMON: DB 'ATM1',CR,0 ; ; "dial" processor ; STTONE: MVI B,'T' JMP SDIAL1 STPULSE:MVI B,'P' SDIAL1: LDA TPULSE CPI B JZ TPSHOW MOV A,B STA TPULSE CPI 'P' MVI A,01010000B ;pulse dial JZ SDIAL2 MVI A,01000000B ;tone dial SDIAL2: STA DIALWD TPSHOW: LDA DIALWD ANI 00010000B JZ TPTONE CALL MILP DB 'Pulse Dial',0 RET TPTONE: CALL MILP DB 'Tone Dial',0 RET ; ; "delay" processor ; DELAY: MVI C,EVALA CALL MEX MOV A,H ORA A JNZ SETERR MOV A,L CPI 100 ;too big ? JNC SETERR PUSH D ; convert binary to ascii CALL CVDCML MOV A,D STA S7NIT+3 ; 10's digit STA LDSTR+5 MOV A,E STA S7NIT+4 ; 1's digit STA LDSTR+6 POP D LXI H,LDSTR ; send the local string to the modem CALL SMSEND DLSHOW: CALL MILP ;finally tell the user about it DB 'Answer delay is ',0 ; LDA S7NIT+3 ;print 10'S DIGIT MOV E,A MVI C,CONOUT CALL MEX ; LDA S7NIT+4 ;print 1'S DIGIT MOV E,A MVI C,CONOUT CALL MEX ; CALL MILP ;print units DB ' Seconds.',0 RET LDSTR: DB 'ATS7=30',CR,0 ; ; "digit" processor - interdigit time SDIGIT: MVI C,EVALA CALL MEX MOV A,H ORA A JNZ SETERR MOV A,L CPI 100 ;too big ? JNC SETERR ; PUSH D ; convert binary to ascii CALL CVDCML MOV A,D STA S11NIT+4 ; 10's digit STA LSTR+6 MOV A,E STA S11NIT+5 ; 1's digit STA LSTR+7 POP D ; LXI H,LSTR ; send the local string to the modem CALL SMSEND DDSHOW: CALL MILP ;finally tell the user about it DB 'Dial digit time is ',0 ; LDA S11NIT+4 ;print 10'S DIGIT MOV E,A MVI C,CONOUT CALL MEX ; LDA S11NIT+5 ;print 1'S DIGIT MOV E,A MVI C,CONOUT CALL MEX ; CALL MILP ;print units DB ' Ms.',0 RET LSTR: DB 'ATS11=40',CR,0 ; ; convert to ascii the hard way ; CVDCML: MVI B,0 ; make ascii out of 7 bit binary TENS: SUI 10 JC ONES ; gone negative yet ? INR B JMP TENS ; nope... keep bumping the 10'S DIGIT ; ONES: ADI 10 ; fix it PUSH PSW ; save the number for a sec MOV A,B ADI '0' ; add in the ascii bias MOV D,A POP PSW ADI '0' ; add in the ascii bias - must be 0-9 MOV E,A RET ; ; set parity command: reset transmit/receive parity ; ; parity is controlled by bits 4 and 5 of mode register 1 ; for the 2651 ; ; parity bit 5 bit 4 ; off - 0 ; odd 0 1 ; even 1 1 ; STPRTY: MVI C,SBLANK ;check for parity code CALL MEX ; JC SETERR ;if none, print error LXI D,PARTBL ;check for proper syntax MVI C,LOOKUP CALL MEX PUSH H ;match found, go do it! RNC ; POP H ;no match: fix stack and JMP SETERR ; print error ; PROFF: MVI A,00000000B STA DFTPAR JMP SHOWP1 PREVEN: MVI A,00110000B STA DFTPAR JMP SHOWP1 PRODD: MVI A,00010000B STA DFTPAR SHOWP1: CALL SINITL SHOWP: LDA DFTPAR RRC RRC RRC RRC ANI 00000011B ADD A MOV E,A MVI D,00 PUSH D CALL MILP ;display parity DB 'Parity is ',0 POP D LXI H,PVECT DAD D MOV A,M INX H MOV H,M MOV L,A PCHL PVECT: DW OFFMSG DW ODDMSG DW OFFMSG DW EVNMSG OFFMSG: CALL MILP ; DB '(None)',0 ; RET ODDMSG: CALL MILP ; DB 'Odd',0 ; RET ; EVNMSG: CALL MILP ; DB 'Even',0 ; RET ; ; set parity command table ; PARTBL: DB 'NON','E'+80H ;"set parity off" DW PROFF DB 'EVE','N'+80H ;"set parity even" DW PREVEN DB 'OD','D'+80H ;"set parity odd" DW PRODD DB 0 ;<<== end of parity table ; ; set stopbits command: reset number of stop bits ; ; the stop bits are controlled by bits 7 and 8 of mode register ; 1 for the 2651 ; ; stop bits bit 7 bit 8 ; 1 0 1 ; 1.5 1 0 ; 2 1 1 ; ; STSTOP: MVI C,SBLANK ;check for stop bits CALL MEX JC SETERR ;if none, print error LXI D,STPTBL ;check syntax MVI C,LOOKUP CALL MEX PUSH H ;match found, go do it! RNC POP H ;no match: fix stack and JMP SETERR ;print error ; STOP01: MVI A,01000000B ; 1 stop bit STA DFTSTP JMP SHOWS ; STOP02: MVI A,11000000B ; 2 stop bits STA DFTSTP JMP SHOWS ; STOP15: MVI A,10000000B ; 1 1/2 stop bits STA DFTSTP ; SHOWS: LDA DFTSTP ; print the current setting RRC RRC RRC RRC RRC RRC ANI 00000011B ; mask any possible crap ADD A ; * 2 MOV E,A MVI D,00 PUSH D CALL SINITL ; reinit the usart CALL MILP DB 'There ',0 POP D LXI H,SVECT DAD D MOV A,M ; dispatch INX H MOV H,M MOV L,A PCHL SVECT: DW MSG0 DW MSG1 DW MSG15 DW MSG2 MSG0: CALL MILP DB 'is an INVALID MODE COMMAND - UNKNOWN ERROR in MEX' DB DING,CR,LF,0 RET MSG1: CALL MILP ; display '1' DB 'is 1 stop bit',0 ; RET MSG2: CALL MILP ; display '2' DB 'are 2 stop bits',0 ; RET MSG15: CALL MILP ; display '1.5' DB 'are 1.5 stop bits',0 RET ; set stopbits command table ; STPTBL: DB '1'+80H ;"set stop 1" DW STOP01 DB '2'+80H ;"set stop 2" DW STOP02 DB '1.','5'+80H ;"set stop 1.5" DW STOP15 DB 0 ;<<== end of stop-bits table ; ; set length command: set bits per character ; ; the number of bits per character is controlled by ; bits 3 and 2 of mode register 1 for the 2651 ; 3 only, but are the same for register 5: ; ; bpc bit 3 bit 2 ; 5 0 0 ; 6 0 1 ; 7 1 0 ; 8 1 1 ; STBITS: MVI C,SBLANK ;check for bits/char CALL MEX JC SETERR ;if none, print error LXI D,BITTBL ;check syntax MVI C,LOOKUP CALL MEX PUSH H ;match found, go do it! RNC POP H ;no match: fix stack and JMP SETERR ;print error ; BIT5: MVI A,00000000B STA DFTBITS JMP SHOWBT BIT6: MVI A,00000100B STA DFTBITS JMP SHOWBT BIT7: MVI A,00001000B STA DFTBITS JMP SHOWBT BIT8: MVI A,00001100B STA DFTBITS SHOWBT: LDA DFTBITS ; get default setting RRC RRC ANI 00000011B ; mask garbage if any ADD A ; * 2 MOV E,A MVI D,00 PUSH D CALL SINITL ; reinit the usart CALL MILP DB 'There are ',0 POP D LXI H,BVECT DAD D MOV A,M INX H MOV H,M MOV L,A PCHL BVECT: DW BITS5 DW BITS6 DW BITS7 DW BITS8 BITS5: CALL MILP ; display '5' DB '5 bits/char',0 RET BITS6: CALL MILP ; display '6' DB '6 bits/char',0 RET BITS7: CALL MILP ; display '7' DB '7 bits/char',0 RET BITS8: CALL MILP ; display '8' DB '8 bits/char',0 RET ; ; set length command table ; BITTBL: DB '5'+80H ;"set bits 5" DW BIT5 DB '6'+80H ;"set bits 6" DW BIT6 DB '7'+80H ;"set bits 7" DW BIT7 DB '8'+80H ;"set bits 8" DW BIT8 DB 0 ;<<== end of bpc table ; ; ; build the default initialization from ram so as to be cloneable ; SINITL: IN CPORT ; reset the mode registers LDA DFTSTP ; get default stop bits MOV B,A LDA DFTPAR ; get default parity ORA B MOV B,A LDA DFTBITS ; get default character length ORA B ORI 00000010B ; force divide by 16 - use internal baud gen OUT MODE1 ; set the register LDA DFTBAUD ; get the default baud rate ORI 00110000B ; force internal clocks OUT MODE2 ; set the register MVI A,00100111B ; force dtr, cts, async, txe, rxe, no loopbak OUT CPORT RET ; ; ; smartmodem dialing routine ... by a "cast of thousands" ; DIAL: LHLD DIALPT ;fetch pointer CPI 254 ;start dial? JZ STDIAL1 ;jump if so CPI 255 ;end dial? JZ ENDIAL1 ;jump if so ; ; not start or end sequence, must be a digit to be sent to the modem ; MOV M,A ;put char in buffer INX H ;advance pointer SHLD DIALPT ;stuff pntr RET ;all done ; ; here on a start-dial sequence ; STDIAL1: LXI H,DIALBF ;set up buffer pointer SHLD DIALPT RET ; ; here on an end-dial sequence ; ENDIAL1: MVI M,CR ;stuff end-of-line into buffer INX H ;followed by terminator MVI M,0 LDA TPULSE ;get overlay'S TOUCH-TONE FLAG STA SMDIAL+3 ;put into string LXI H,SMDIAL ;point to dialing string CALL SMSEND ;send it WAITSM: MVI C,INMDM CALL MEX ;catch any output from the modem JNC WAITSM ;loop until no more characters ; ; the following loop waits for a result from the modem. ; RESULT: MVI A,60 ; dont hang longer than a minute MOV C,A SMWLP: PUSH B MVI B,1 ;check for a char, up to 1 sec wait MVI C,TMDINP ;do timed input CALL MEX POP B JNC SMTEST ;jump if modem had a char PUSH B ;no, test for control-c from console MVI C,CHEKCC CALL MEX POP B JNZ SMNEXT ;if not, jump CALL SMDMOFF ;yes, shut down the modem MVI A,3 ;return abort code RET SMNEXT: DCR C ;no JNZ SMWLP ;continue ; ; no modem response within the time specified in set delay command ; SMTIMO: CALL SMDMOFF MVI A,2 ;return timeout code RET ; ; modem gave us a result, check it ; SMTEST: ANI 7FH ;ignore any parity CALL SMANAL ;test the result JC RESULT ;go try again if unknown response MOV A,B ;a=result PUSH PSW ;save it SMTLP: MVI C,INMDM ;eat any additional chars from smartmodem CALL MEX JNC SMTLP ;until 100ms of quiet time POP PSW ;return the code RET ; ; analyze character returned from modem ; SMANAL: MVI B,0 ;prep connect code CPI 'C' ;"connect"? RZ CPI '1' ;numeric version of "connect" RZ CPI '5' ;numeric version of "connect 1200" RZ INR B ;prep busy code b=1 CPI 'B' RZ INR B ;prep no connect msg b=2 CPI 'N' ;n=no connect RZ CPI '3' ;numeric version of "no connect" RZ MVI B,4 ;prep modem error CPI 'E' ;e=error RZ CPI '4' ;numeric version of "error" RZ ; ; unknown response, return carry to caller. but first, ; flush the unknown response line from the modem. ; WTLF: CPI LF ;linefeed? STC RZ ;end if so MVI C,INMDM ;no. get next char CALL MEX JNC WTLF ;unless busy, loop RET ; ; send string to the external modem ; SMSEND: MVI C,SNDRDY ;wait for modem ready CALL MEX JNZ SMSEND MOV A,M ;fetch next character INX H ORA A ;end? RZ ;done if so MOV B,A ;no, position for sending MVI C,SNDCHR ;nope, send the character CALL MEX JMP SMSEND ; ; disconnect smodem - if DTR didnt, this will... ; SMDMOFF: MVI B,CR MVI C,SNDCHR CALL MEX MVI B,10 ;one second wait for hayes, etc CALL MTIME JMP DISCON ;make sure it is off ; ; general utility routines ; MILP: MVI C,ILP ;in-line print JMP MEX RET ; MTIME: MVI C,TIMER ; mex timer JMP MEX RET ; CRLF: CALL MILP ; print carriage return, line feed DB CR,LF,0 RET DONEW: PUSH H ; save the new command string fro a sec LXI H,ATNSTR CALL SMSEND ; wake up the modem with 'AT' POP H JMP SINIT ; now send the new parameter ATNSTR: DB 'AT',0 ; ;========================================================================== ; data area ;========================================================================== ; ; default uart parameters ; DFTSTP: DB 01000000B ; default stop bits - 1 DFTPAR: DB 00000000B ; default parity - none DFTBITS: DB 00001100B ; default character length - 8 bits DFTBAUD: DB 00000000B ; default baud rate scratch area ; SMDIAL: DB 'ATDT ' ; smartmodem dial prefix DIALBF: DS 52 ; 2* 24 char max, + cr + null + slop DIALPT: DS 2 ; dial position pointer DIALWD: DB 01000000B ; pulse/tone dial word DIGIT DB 0 ; save dialed digit SPEED: DB 5 ; default baud rate ; 0=110,1=300,3=600,5=1200,6=2400 ; 7=4800,8=9600,9=19200 MONFLG: DB 0FFH ; 0: monitor off - 0ffh: monitor on ANSFLG: DB 0 ; 0: originate - 0ffh: ans ; SMATN: DB '+++',0 ; smartmodem online 'ATTENTION' SMDISC: DB 'ATH',CR,0 ; smartmodem disconnect SMINIT: DB 'ATM1 ' ; speaker S0NIT: DB 'S0=0 ' ; answer ring counter S7NIT: DB 'S7=30' ; carrier wait delay seconds XNIT: DB 'X1' ; result code mode S11NIT: DB 'S11=40 ' ; interdigit delay in ms DB CR,0 ; modem init string ; ;****************************************************************************** ; END ; ;******************************************************************************