; P T I M E v1.1 ; Program to set/read the time on ; the PROMETHEUS modem via command line. ; Allows one to use this modem as a time piece. ; Can also be used in an RCP/M environment ; and will return to the online mode... ; Assemble with M80 ; For CP/M 2.2 and above, uses function 10... ; The PASSWORD is located at the very end of this file... ; Re-configure the information at HANG-UP MODEM, for your computer. ; Some slight adjustments in timing may be needed ; for a particular system? ;Command formats: ; A>TIME S ;Allows setting the time (Only after proper password). ;When password is entered, it is echoed exactly as typed, ;this routine uses CP/M function 10 to allow editing. ;NOTE: The following routine is optional by setting the ;equate 'HOOK'. If you want to retain this option, then ;change the R to any other character you prefer... ; A>TIME R ;Displays the current time and WILL NOT return to the ;on line mode, does not assume modem is off hook... ; A>TIME ;Displays current time and RETURNS to the on-line mode, ;assumes modem is off-hook... ;When settimg the time... ; MM = Month number ; DD = Day number ; hh = hour (in 12-hour format...1:00 not 13:00) ; mm = minute ; x = either "P" for PM, or "A" for AM. ; i.e. 4/1/12/00A OR a ;Any puntcuation character may be used to separate ;the values. Although the '/' is easy to remember. ; USE: ; M80 =PTIME ; L80 PTIME,PTIME/N/E ; (Z80 CPU's only too) ; (unless re-written) ;Written by: ; Ray Kester ; AUG 08, 84 ; SEP 26, 84 ;::::::::::::::::::::: ;## Modifications ## ;::::::::::::::::::::: ;If any mods are made to this program, I would appreciate ;knowing the whereabouts of them. Please leave a message ;or uploaded copy to: ; GENERATION-5 RBBS/RCP/M ; 301-495-2932 ; Silver Spring, MD ; v1.0 ; Simple time setting routine for the modem. [RDK] ; v1.1 ; Modified to use for setting the time remotely or ; locally. Typing 'S' after the program name allows ; setting the time, but only after the correct ; password is given. If 'R' is given the program ; will display the time and NOT return to the on- ; line mode, otherwise the time is displayed. ;--> If using BYExxx, the S2 register must be changed ; so a ^P is used as the escape character. This is ; trapped inside of BYExxx...[RDK] ; Switches should be: ; 1 2 3 4 5 6 7 8 9 0 D = dn ; U U U U D D D D D D U = up ; ||============> ^ (see note below) ; || (Or the same as your BYExxx) ; \/ ; NOTE: This program requires that 'echo' be on in the modem... .Z80 ASEG ORG 100H YES EQU 0FFH NO EQU 00H ;###### U S E R M O D S ###### ;# # ;# CPU speed in MHz. # ;# # MHZ EQU 05 ;# # ;# Number of tries before # ;# aborting... # ;# # RETRY EQU 04 ;# # ;# This value is the loop value # ;# (in time) it takes the modem # ;# to respond from the escape # ;# sequence to the modem. The # ;# current value (08) is used # ;# for the default set in REG12 # ;# [See label 'EXCUSE'] # ;# # DEAD EQU 8 ;# # ;# Set this to the current year # ;# Reverse the dec./year 84=48 # ;# # YEAR EQU '48' ;# # ;# Set this to YES is you want # ;# the ability to check the # ;# time WITHOUT returning to # ;# the online mode... # ;# # HOOK EQU YES ;# # ;# This is the character to use # ;# if the above is set to YES. # ;# This way it keeps'm gueesing # ;# # ASKM EQU 'R' ;# # ;########## END MODS ########## VERS EQU 11 ;Will be displayed as x.x BELL EQU 07 ;Bell CR EQU 0DH ;Return LF EQU 0AH ;Line Feed NULL EQU 0 CONIN EQU 01 ;Read character from console CONOUT EQU 02 ;Send character to console STRING EQU 10 ;CP/M read console string BDOS EQU 05H FCB EQU 5CH ;File control block ;#------------------------------------------------------# ;# Escape code used to get into command mode on modem. # ;# When modifying for BYExxx use the DECIMAL value # ;# NOTE that this value (^P) is filtered by BYE before # ;# your system sees it, so remote users cannot use it. # ;# -> [ATS2=16]. # ;# # CNTP EQU 'P'-40H ;^P =16 decimal/10 Hex # ;#------------------------------------------------------# ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; S T A R T O F P R O G R A M ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;Set up the SP... START: LD (STACK),SP LD SP,STACK ;Print sign-on... CALL ILPRT DB CR,LF DB 'PTIME v',VERS/10 MOD 10+'0' DB '.',VERS MOD 10+'0' DB ', hold...',0 LD A,(FCB+1) ;Get byte if any CP 'S' JP Z,SET ;Set the time IF HOOK CP ASKM JP Z,MREAD ;Do the modified read time ENDIF ;HOOK JP READ ;Go show time ;::::::::::::::::::::::::::::: ;## S U B R O U T I N E S ## ;::::::::::::::::::::::::::::: ;Send characters to CRT at SP... ILPRT: EX (SP),HL ;Swap HL=>SP PUSH BC ;Save BC PLOP: LD A,(HL) ;Get byte @HL CALL TYPE ;Print character INC HL ;Bump the pointer LD A,(HL) ;Get another byte OR A ;Zero? JP NZ,PLOP ;No?, then loop POP BC ;Else, get back BC EX (SP),HL ;Put new stack location in RET ;Send single character to CRT... TYPE: PUSH AF ;The rest is obvious PUSH HL PUSH BC PUSH DE LD C,CONOUT LD E,A CALL BDOS POP DE POP BC POP HL POP AF RET ;Set the time on the modem, only after the proper ;password is given.. SET: CALL ILPRT DB 8,8,8,8,8,8,8 ;Backup over 'hold..' so it's pretty? DB 'Password => ',0 ;Can be patched at the END LD C,STRING ;Use CP/M func. 10 LD DE,BUFF ;Buffer area CALL BDOS ;Allows editing LD A,LF ;Move down a line CALL TYPE ; for the next question ;Compare the passwords... LD HL,PASS ;Point to the stored password LD DE,BUFF+2 ;Point to the entered ones LD A,(BUFF+1) ;Get byte count LD B,A ;Swap CLOP: LD A,(DE) ;Get byte @DE CP (HL) ;Compare to one @HL JP NZ,NOGOJOE ;No match?, the bye bye INC HL ;Else, bump it up INC DE ; " " " DJNZ CLOP ;Go til B=0 ;Password matched... CALL ILPRT DB CR DB 'HELP message? (Y/N) ',0 LD C,CONIN CALL BDOS AND 5FH CP 'Y' JP NZ,PHELP ;Print instructions... CALL ILPRT DB CR DB 'Enter the new time using: MM/DD/hh/mmx' DB CR,LF,LF DB 'MM = Month number' DB CR,LF DB 'DD = Day number' DB CR,LF DB 'hh = hour (in 12-hour format. 1:00 not 13:00)' DB CR,LF DB 'mm = minute' DB CR,LF DB 'x = either "P" for PM, or "A" for AM.' DB CR,LF DB 'i.e. 9/24/12/00a' DB CR,LF,LF DB 0 PHELP: CALL ILPRT DB CR DB 'Enter new Date & Time format => ',0 LD C,STRING ;Use CP/M function 10 (allows editing) LD DE,BUFF ;Point to buffer area PUSH DE ;Save buffer adr. CALL BDOS ;Get string POP HL ;Get adr. in HL INC HL ;Point to bytes received LD E,(HL) ;Get them LD D,0 ;Zero D ADD HL,DE ;Add together INC HL ;Point to last unused location LD (HL),NULL ;Mark the end CALL ILPRT DB CR,LF,LF DB 'Hold...',0 CALL EXCUSE ;Interrupt modem LD HL,TIME ;Point to command CALL OUTP ;Send it CALL DELAY ;Let the dust settle LD HL,BUFF+2 ;Point to what the user requested CALL OUTP ;Send new time format LD A,CR ;Load this CALL MODOUT ; and proceed with command LD B,3 ;Delay this many times PHLP: CALL DELAY DJNZ PHLP ;Give the last command a chance to settle LD A,'*' ;Mark this routine exit JP READ ;Show new time ;Reset the error count... FIX: XOR A ;Zero A LD (VAL),A ;Reset count RET ;Send a string to the modem. Check for improperly echoed characters... OUTP: LD (SAVEIT),HL ;Just in case of an error CALL MODIN ;Clear any garbage characters CALL MODIN MOD0: CALL MODOST ;Get modem output status JR Z,MOD0 ;Loop if something there LD A,(HL) ;Else, get a byte @HL CALL MODOUT ;Send byte LD DE,2000*MHZ ;Time for echo to get here MOD1: DEC DE BIT 7,D JR NZ,MOD2 ;We timed out... CALL MODIST ;Get input status JR Z,MOD1 CALL MODIN ;Get the echoed byte CP (HL) ;Same as one sent? JR NZ,MOD2 ;Branch if screw-up INC HL ;Else, bump the pointer XOR A ;Load delimiter CP (HL) ;Same? JP Z,FIX ;Do this first JR MOD0 ;Else loop ;Found an error... MOD2: LD A,CR ;Clear modem's CALL MODOUT ; problem... LD A,(VAL) ;Get count INC A ;Count=count+1 LD (VAL),A ;Save it again CP RETRY ;Equal to retry? JP Z,NONO ;Yep, then leave LD B,2 ;Loop this many times MOD3: CALL DELAY ;Give time for modem to reset DJNZ MOD3 ;Loop til B=0 LD HL,(SAVEIT) ;Else get back the beginning JR OUTP ;Do it again ;Exceeded RETRY value... NONO: CALL ILPRT DB CR,BELL DB 'ERROR-> Can''t complete task...Aborting!' DB CR,LF,LF,0 JP ZERO ;Short delay based on constant... DELAY: PUSH AF PUSH HL PUSH BC PUSH DE LD DE,5000*MHZ ;Load constant STALL: DEC DE ;BC=BC-1 BIT 7,D ;Check MSB JP P,STALL ;If positive, loop POP DE POP BC POP HL POP AF RET ;Modified read of time, do not return to online mode... MREAD: CALL PREAD ;Read time on modem and send data JP QUIT ;Quit program, no on-line mode ;Read present time on modem... READ: CP '*' ;Which routine are we coming from JR Z,FTSR CALL READA ;Get data, using the interrupt JP PREQ ;Now leave using online mode FTSR: CALL PREAD ;Get data, already interrupted JP PREQ ;Quit program, return online status ;Send info to modem and get current date & time... READA: CALL EXCUSE ;Interrupt modem PREAD: LD HL,RTIME ;Message to send to modem CALL OUTP ;Send it CALL DELAY CALL MODIN ;Get garbage CALL MODIN LD HL,NDATE ;Point to area to place in RAG1: CALL MODIST ;Else, check status JR Z,RAG1 ;Nothing, then loop CALL MODIN ;Get byte from modem CP 20H JR Z,RAG2 ;Break between date/time CP CR ;We don't want any JR Z,RAG1 ; ...CR's CP LF JR Z,RAG1 ; ...LF's LD (HL),A INC HL JR RAG1 ;Loop until we find the end RAG2: LD HL,NTIME ;Point to another save area RAGA: CALL MODIST ;Else, check status JR Z,RAGA ;Nothing, then loop CALL MODIN ;Get byte from modem CP CR ;We don't want any JR Z,RAGA ; ...CR's CP LF JR Z,RAGA ; ...LF's CP 'A' ;We want to know the JR Z,RAGB ; end of the CP 'P' ; string too JR Z,RAGB LD (HL),A INC HL JR RAGA ;Loop until we find the end RAGB: LD (HL),A INC HL LD (HL),'M' ;And then this RET ;Interrupt modem (use escape codes)... ;Have to send it blind... EXCUSE: LD HL,ESCAPE ;Point to string CALL BLIND ;Send it LD B,DEAD ;Constant to change at beginning ; [if needed] EXLP: CALL DELAY ;Give time for modem DJNZ EXLP ; to respond RET ;Same effect as OUTP, except this one does not check echoed ;characters... BLIND: CALL MODOST ;Check output status JR Z,BLIND ;Loop til ready LD A,(HL) ;Get a byte CALL MODOUT ;Send it CALL DELAY INC HL ;Bump pointer LD A,(HL) ;Get another byte OR A ;The end? JR NZ,BLIND ;Keep looping RET ;A possible creep tried to hose you up. ;So we are gonna hose him up! (HANG-UP) NOGOJOE: CALL ILPRT DB CR,BELL DB 'Sorry, but you seem to have your head' DB CR,LF DB 'where the sun don''t shine... BYE! ...',0 ;Just do whatever it takes to shut DTR off... LD C,SPORT ;Get port to send LD HL,VALUES ;Set-up pointer LD B,(HL) ;Get byte count INTL: INC HL ;Bump it LD A,(HL) ;Get byte OUT (C),A ;Send it DJNZ INTL ;Til B=0 JR ZERO ;Abort big time ;The end of the program. We will still have some input ;from the modem, so loop till most of it is gone... PREQ: LD B,8 ;Delay some time PREL: CALL DELAY DJNZ PREL LD HL,ONLINE ;Go back to online CALL BLIND ; status after we're done CALL MODIN ;Get any strays ;Show the time and date then quit the program... QUIT: ;This area will be over-written with the real stuff... CALL ILPRT DB CR DB 'Date: ' NDATE: DB '00/00/' DW YEAR DB ' Time: ' NTIME: DB '00:00:00 xx',0 ZERO: CALL MODIN ;Get any strays CALL MODIN ;Get any strays CALL ILPRT DB CR,LF,LF,0 LD SP,(STACK) RET ;Soft return ; ######################################################## ; # This is the area for setting up the PORT that needs # ; # the info to hang up... # ; ######################################################## ; # H A N G - U P M O D E M # ; ######################################################## ; # # ;Stuff follows for the Z80-SIO... # REG5 EQU 5 ; # DTROFF EQU 0 ; # ; # # VALUES: ; # DB VALEND-VALUES ;Byte count # DB REG5 ;Set up for reg. 5 # DB DTROFF ;Turn DTR off (hang-up) # VALEND: ; # ; # # ; ######################################################## TBIT EQU 04H ;Tx buffer empty mask RBIT EQU 01H ;Rx character available mask DPORT EQU 04H ;System DATA port SPORT EQU DPORT+2 ;System STATUS port ; ############################################### ; # M O D E M P O R T R O U T I N E S # ; ############################################### ; Modem port INPUT status.... MODIST: IN A,(SPORT) ;Get status AND RBIT ;Mask Data available? (01) CP NULL ;Set flags RET Z ;Return if no OR 0FFH ;Else, FF if yes RET ; Modem port OUTPUT status... MODOST: IN A,(SPORT) ;Get status AND TBIT ;Mask Tx buffer empty (04) CP NULL ;Set flags RET Z ;Return if No OR 0FFH RET ; Get byte at modem data port... MODIN: IN A,(DPORT) AND 7FH ;Mask parity RET ; Send byte to modem port... MODOUT: OUT (DPORT),A RET ;################################ ; Default strings... TIME: DB 'AT@T=',0 ;Set time RTIME: DB 'AT@T',CR,0 ;Read time ONLINE: DB 'ATO',CR,0 ;Online (terminal mode) ESCAPE: DB CNTP,CNTP,CNTP,0 ;Escape sequence used to get to ; command state in modem. ;:::::::::::::::::::::::::::::: ;## D A T A S T O R A G E ## ;:::::::::::::::::::::::::::::: VAL: DB 0 ;Error count SAVEIT: DS 2 ;Error save place ;Buffer for CP/M 2.2 function 10... BUFFLEN EQU 15 ;Max length of PASSWORD or TIME string BUFF: DB BUFFLEN ;Number of bytes allowed BUFGOT: DB 0 ;Actual number of characters typed (BUFF+1) DS BUFFLEN+1 ;Actual buffer ;Stack stuff... DS 12 ;6 level stack STACK: DS 2 ;Stack resting place ; ###################################################### ; H E R E I S T H E P A S S W O R D ; ###################################################### ; Note that it can be patched by using DDT. ; Just look for the end of the .COM file when loading... PASS: ;BUFFLEN above, is the MAXIMUM length of the PASSWORD, unless ;you change it to a larger number... ; ||||||||||||||| DB 'YURWORD' ; ^^^^^^^^^^^^^^^ END