INTEL HEX DEVICE DRIVER FOR PTDOS MARTIN EBERHARD 6 OCTOBER 2011 CONTENTS SECTION 1............................INTEL DEVICE DRIVER DESCRIPTION SECTION 2..HOW TO LOAD INTEL ONTO A PTOS DISKETTE FOR THE FIRST TIME SECTION 3..............USING INTEL TO SEND A HEX FILE TO YOUR SOL-20 SECTION 4..............USING INTEL TO ARCHIVE PTDOS A FILE ON THE PC APPENDIX 1......................................CONTENTS OF MINHX.EN APPENDIX 2.................................MINHX SOURCE CODE LISTING SECTION 1. INTEL DEVICE DRIVER DESCRIPTION Processor Technology's PTDOS did not come with a serial port file transfer program. This makes moving files onto and off of a Sol-20 with PTDOS difficult. To solve this problem, I have written a PTDOS device driver called INTEL. INTEL allows you to use the PTDOS COPY command to read an Intel Hex-formatted file through the Sol-20 serial port, and write it as a binary file onto a PTDOS diskette. You do this by simply typing COPY INTEL,. INTEL also allows you to write any file from a PTDOS diskette to the Sol-20 serial port in Intel Hex format, by typing COPY ,INTEL. INTEL loads at address D000h and uses memory up to about D260h, so you must have at least 1K of available memory in this range - above PTDOS, above SOLOS, and above the Sol-20's video memory. This device driver loads from disk when invoked, and gets discarded when an operation is complete. SECTION 2. HOW TO LOAD INTEL ONTO A PTDOS DISKETTE FOR THE FIRST TIME General Problem: I and others have archived many PTDOS files in Intel Hex format, some of which is posted on the web. If you have my INTEL device driver on your PTDOS diskette, you can use it to load any of these files onto your PTDOS diskette. But until you load INTEL (which is also available in Intel Hex format), you have no easy way to load an Intel Hex file onto your PTDOS Disk. It's a chicken-and-egg problem. This is solved by first manually loading a very simple Intel Hex loader onto the Sol-20, and then using it to pull in INTEL. Here is how you get going: 1. Set the Sol-20 serial port for 1200 baud. (This is a good baud rate for connecting the Sol-20 to a Diablo 1610 printer, for example.) Set the Sol-20 DIP switches as follows: S4-1 off (odd parity) S4-2 off (7 data bits) S4-3 on (7 data bits) S4-4 on (1 stop bit) S4-5 on (include parity bit) S4-6 off (full duplex) S3-6 on, all other S3 switches off (1200 baud) 2. If your PC does not have an RS-232 serial port, you will need to get a USB-to-RS-232 dongle - there are several available. Any one of them should work fine, probably appearing as COM3 or COM5 on the PC, once installed. 3. Connect your PC's serial port to the Sol 20. You will need a "standard" 9-pin to 25-pin cable and a null modem (which switches pins 2 and 3) - or you can fabricate your own 9-pin to 25-pin cable that has pins 2 and 3 swapped. Note that the INTEL device driver does not perform any handshaking - so the only other pin that needs to be connected is the Sol-20's pin 7, ground. 4. Find a Terminal program for your PC, such as HyperTerm (which comes standard with Windows XP) or RealTerm (which works well). Install this program, and set it up for the correct COM port for your serial port, with 1200 baud, 7 bits, odd parity. (Note: you could set everything up for 8-bits, no parity, and it would work fine. But using parity will help you catch any communication errors when sending files from the Sol-20 to the PC.) 5. Power up the Sol-20 computer and the Helios disk drive. You should see a SOLOS prompt (>) on the Sol-20 console. Make sure the LOCAL key is off, and the CAPS LOCK key is on. (Note: if the Sol-20 LOCAL key is on, then the serial port is disabled.) On the Sol-20, type SET I=1 6. Use the terminal program to send the file MINHX.EN to the Sol-20. (The contents of MINHX.EN are in Appendix 1, and the source code for this super-simple Intel Hex loader program is in Appendix 2.) When MINHX.EN is done loading, you should see another SOLOS prompt on the SOL-20. 7. On the Sol-20, start the simple hex loader by typing EX CAB4 8. Use the PC terminal program to send the file INTEL.HEX to the Sol-20. If you see a question mark on the Sol-20 console, then you had an error - check all the setup and try again. If you get the Sol-20 prompt (>) with no question mark, then the transfer was a success and the INTEL device driver is loaded in a RAM buffer starting at address 0000h. 9. Boot PTDOS - on the Sol-20 by typing BO 10. DO NOT run any other PTDOS programs or commands! If you do, you will probably overwrite the INTEL image in RAM. 11. At the Helios prompt (*), type WRITE INTEL,!100,0,245,< You should now see a file called INTEL in the Helios directory. 12. At this point, I recommend making a backup of the Intel file on another diskette (in drive 1) by typing COPY INTEL,INTEL/1. (You cannot copy a device driver with type 'D' easily - PTDOS will try to invoke the device driver rather than simply copying it.) 13. Now, make INTEL into a device driver, by typing RETYPE INTEL,D 14. And finally, set protection attributes for the new device driver by typing REATR INTEL,KN 15. You now have an Intel Hex device driver on your PTDOS disk. You might want to RETYPE and REATR the backup copy as well, by typing RETYPE INTEL/1,D REATR INTEL/1,KN SECTION 3. USING INTEL TO SEND A HEX FILE TO YOUR SOL-20 1. Connect the PC to the Sol-20 and set up the PC's terminal program as above. MAKE SURE the Local key on the Sol-20 keyboard is off! (This key disables the Sol-20 serial port...) 2. Use the PTDOS COPY command to receive and decode the file, and write it to your PTDOS diskette. For example, to load the assembler ASSM from the archived version ASSM.HEX that you have on your PC, type at the PTDOS prompt: COPY INTEL,ASSM 3. When the INTEL driver tells you to do so, tell your PC terminal program to send the file INTEL.HEX to its serial port. File transfer will take a few minutes at 1200 baud, so be patient. Any checksum errors will be reported on the Sol-20 console. 4. When the INTEL driver receives an Intel Hex end-of-file record, it will print the total number of records received (in hexidecimal) on the console, and return control to PTDOS. 5. If you like, you can check the record count against the number of records in the Intel Hex file that you sent, to see if any records were missed. Take a look at the hex file on the PC, using a simple text editor: * Each line that starts with a colon is a record. * The first two characters after the colon are the data byte-count for that record. Commonly, this number is 10 (hexidecimal), which makes counting the records easy. * The next four characters are the address for the record. My archived PTDOS files always start at address 0000h and are sequential to the end. * The very last record is ":0000000000", which is the end-of-file record. * Look at the address field of the record just before the end-of-file record. If you take the first three digits of the address (throwing away the 0 at the end), and add 2 to the value, you should have the record count for this file. (This extra 2 records are the first record (which has address 0000), and the end-of-file record.) If this number does not match the record count printed by INTEL, then you probably dropped a record during the transfer, and the file on your PTDOS disk is corrupt. (This should never happen. If it does, look carefully at your connections, and at how the PC terminal program is configured.) 6. PTDOS archive files that I created have some comments at the beginning (before the first record) which can be viewed with a simple editor on the PC. In these comments, you will find the file name, file type, and the protection attributes for this particular file. You now need to set the file type and protection attributes for the file that you just loaded. * Since ASSM should be an executable image (TYPE = I), you need set its type, using the PTDOS RETYPE command: RETYPE ASSM,I * Now you can set the protection attributes for ASSM: REATR ASSM,KWN You should now have an executable ASSM on your PTDOS diskette. Try it by typing ASSM SECTION 4. USING INTEL TO ARCHIVE A PTDOS FILE ON THE PC 1. Connect the PC to the Sol-20 as above. Also set up the PC's terminal program as above. MAKE SURE the Local key on the Sol-20 keyboard is off! (This key disables the Sol-20 serial port...) 2. If the file that you want to send is type D (a device driver), then you will need to change its type temporarily. For example, the PTDOS file SOL3 is a device driver, type D. If you tried to copy this file, PTDOS would invoke the SOL3 device driver and try to read a file from it, rather than simply copying the device driver itself. To change the file type of SOL3, type RETYPE SOL3,X SOL3 is no longer a device driver, it is now type X.) You might need to change your file's protection attributes (with REATR) before you can change its type. 3. Set your PC terminal program to capture data from its serial port into a file on the PC - you would name the file SOL3.HEX in this example. 4. Use the PTDOS COPY command and the INTEL device driver to send the file to the PC: COPY SOL3,INTEL 5. When the copy is done, the INTEL driver will print the record count and return control to PTDOS. At this point, tell the PC terminal program to stop capturing data and close the SOL3.HEX file. 6. Take a look at the PC terminal program's status to see if any parity errors were detected. (There should have been none.) 7. Fix the file type on PTDOS, if you changed it in step 2: RETYPE SOL3,D 8. Use a simple editor on the PC to edit the new hex file. Add a couple of lines at the beginning that tell at least: * The PTDOS file name * The PTDOS file type * The PTDOS block size * The PTDOS file protection attributes All of these data about SOL3 can be found with the PTDOS FILES command: FILES SOL3 Note: DO NOT use any colons (:) in your comments! These will look like record-starts and will confuse the INTEL device driver. (All other characters are ok.) APPENDIX 1 CONTENTS OF MINHX.EN EN CAB4 C3 BF CA 06 3F B7 C2 19 C0 B1 C8 CD EE CA C2 BF CA 11 04 00 4C 65 68 CD DD CA C2 C8 CA 59 CD DD CA FA B7 CA 70 23 C3 D2 CA CD EE CA 07 07 07 07 47 CD EE CA 80 47 8A 57 1D C9 3E 01 CD 22 C0 E6 7F CA EE CA D6 30 FE 0A D8 C8 D6 07 C9 E0/ SET I=0 APPENDIX 2 MINHX SOURCE CODE LISTING ;=============================================================== ; MINHX: MINIMAL INTEL HEX LOADER FOR SOLOS/CUTER ; ; BY MARTIN EBERHARD ; ; VERS DATE NOTE ; 1.01 3JUN2011 CREATED ; 1.02 3JUN2001 SQUEEZE ; ;=============================================================== ;*************************************************************** ; OPERATION ; ; THIS PROGRAM IS A MINIMAL INTEL HEX LOADER THAT IS INTENDED ; TO BE ENTERED IN HEX ON THE SOLOS CONSOLE, AND USED JUST ONCE ; TO LOAD (AND SAVE TO TAPE OR DISK) A BETTER AND MORE ROBUST ; INTEL HEX LOADER. ; ; THIS PROGRAM WILL LOAD AN INTEL HEX FILE FROM THE SERIAL PORT ; INTO MEMORY AT THE ADDRESSES SPECIFIED IN THE INTEL HEX FILE. ; ; THIS PROGRAM LOADS AND RUNS IN SOLOS'S USER AREA, 'USARE' - ; LOAD AND EXECUTE AT CAB4. ; ; EXECUTION TERMINATES WITH A RETURN TO SOLOS FOR EITHER OF THE ; FOLLOWING CONDITIONS: ; * ANY RECORD WITH 0 DATA BYTES - TREATED AS END-OF-FILE, ; NO MESSAGE PRINTED ; * CHECKSUM ERROR - A '?' WILL BE PRINTED ON THE CONSOLE ; BEFORE RETURNING TO SOLOS. ; ; TO ABORT A LOAD, RESET SOLOS WITH 'UPPERCASE'-'REPEAT' ; ;*************************************************************** ; PROGRAM NOTES ; ; THIS PROGRAM IS WRITTEN TO BE ASSEMBLED BY CP/M'S ASM.COM. ; ; THIS PROGRAM ASSUMES SOLOS (OR CUTER) IS INSTALLED AT ITS ; NORMAL LOCATION, C000. ; ; THE COMPLETE PROGRAM HAS BEEN CRAFTED TO BE AS SMALL AS ; POSSIBLE, WHILE STILL DOING A PASSABLE JOB OF CHECKING FOR ; ERRORS. ; ; THIS PROGRAM RUNS IN THE 'USER AREA' OF THE 1K RAM BUFFER ; ADJACENT TO SOLOS/CUTER (CALLED 'USARE' IN SOLOS SOURCE CODE). ; THIS AREA BEGINS AT 0CAB4H AND ENDS AT THE END OF RAM, CBFF. ; HOWEVER, SOLOS'S STACK BEGINS AT 0CBFF, AND GROWS TOWARD 0 - ; SO IF THE LOADER IS TO LARGE, SOLOS'S STACK WILL OVERWRITE IT. ; NOTE: SOLOS NEEDS ABOUT 22 BYTES OF STACK SPACE. SO THE LAST ; ADDRESS MUST BE BEFORE CBEA - NOT A PROBLEM HERE. ; ;*************************************************************** ; INTEL HEX RECORD FORMAT ; ; AFTER THE INITIAL COLON, EACH CHARACTER IS A HEX DIGIT. ; ; :CCAAAATTdataSS ; ; : = (ASCII COLON) START-OF-RECORD INDICATOR ; CC = THE TOTAL NUMBER OF DATA BYTES, IN HEX ; AAAA = THE MEMORY LOAD ADDRESS FOR THE FIRST DATA BYTE ; SUBSEQUENT BYTES ARE WRITTEN TO SEQUENTIAL ADRESSES ; TT = RECORD TYPE. THE FOLLOWING TYPES ARE SUPPORTED: ; 00 = NORMAL DATA RECORD ; 01 = END-OF-FILE. EOF RECORD MAY CONTAIN DATA. ; data = CC DATA BYTES (2 HEX DIGITS EACH) ; SS = RECORD CHECKSUM. WHEN ALL HEX BYTES OF THE RECORD ARE ; ADDED TOGETHER (INCLUDING THE SS CHECKSUM BYTE) THE ; RESULT SHOULD BE 0. ANYTHING ELSE IS A CHECKSUM ERROR. ; ; NOTE: THE RECORD ':0000000000', WHICH IS A 0-BYTE NORMAL DATA ; RECORD, IS OFTEN USED AS AN END-OF-FILE RECORD. THIS PROGRAM ; TREATS *ALL* 0-BYTE RECORDS (REGARDLESS OF RECORD TYPE) AS EOF ; RECORDS. ANY OTHER RECORD (WITH CORRECT CHECKSUM) WILL BE ; TREATED AS A DATA RECORD. ; ; NOTE: ANY CHARACTERS THAT OCCUR BEFORE THE INITIAL COLON (OF ; ANY RECORD) WILL BE IGNORED. THIS ALLOWS FOR CARRIAGE RETURNS ; AND LINE FEEDS TO MAKE THE HEX FILE PRETTY, AS WELL AS ANY ; COMMENTS, PROVIDED THE COMMENTS DO NOT INCLUDE ANY COLONS. ;*************************************************************** SOLOS EQU 0C000H ;SOLOS/CUTER BASE ADDRESS USARE EQU 0AB4H ;USER AREA IN RAM, OFFSET FROM SOLOS ; CUTER/SOLOS ENTRY POINTS, OFFSET FROM SOLOS BASE ADDRESS SOUT EQU 19H ;WRITE CHR IN B TO CURRENT PSEUDO PORT AINP EQU 22H ;READ FROM PSEUDO PORT IN A INTO A ; CUTER/SOLOS PSEUDO PORT DEFINITIONS. CHANGE CODE AT 'GETHX' ; TO LOAD FROM A DIFFERENT PORT. KBDPP EQU 0 ;KEYBOARD PSEUDO PORT SERPP EQU 1 ;SERIAL PSEUDO PORT PARPP EQU 2 ;PARALLEL PSEUDO PORT USRPP EQU 3 ;USER-WRITTEN ROUTINE PSEUDO PORT ;*************************************************************** ; BEGINNING OF CODE EXECUTION * ; * ; REGISTER USAGE DURING HEX LOAD: * ; B: SCRATCH * ; C: RECORD BYTE COUNT * ; D: RECORD CHECKSUM * ; E: LOOP COUNT * ; HL: MEMORY ADDRESS * ;*************************************************************** ORG SOLOS+USARE HEXLD: JMP GETCO ;SO THAT START ADDR=LOAD ADDR ; CHECK RECORD CHECKSUM IN A CHKSM: MVI B,'?' ;IF WE NEED AN ERROR MESSAGE ORA A ;TEST CHECKSUM JNZ SOLOS+SOUT ;PRINT ?, RETURN VIA SOLOS ; ALL DONE WITH THIS RECORD. CHECK C=0 FOR 0-BYTE RECORD ; (WHICH IS TREATED AS EOF) ORA C ;WAS LAST RECORD 0 BYTES? RZ ;YES: DONE ; WAIT FOR RECORD START: EAT ALL CHRS UNTIL WE GET A COLON GETCO: CALL GETHX ;Z SET IF RESULT IS COLON JNZ GETCO ; LOOP TO SHIFT THE FOLLOWING VALUES INTO REGISTERS: ; C = RECORD BYTE COUNT ; H = ADDRESS HIGH BYTE ; L = ADDRESS LOW BYTE ; B = RECORD TYPE (WILL GET CHUCKED) ; D = CHECKSUM OF THE ABOVE 4 VALUES LXI D,4 ;D=RESET CKSUM, E=LOOP 4 TIMES CATLP: MOV C,H ;SHIFT THROUGH REGS SO THAT MOV H,L ;...EVERYTHING'S IN PLACE AFTER MOV L,B ;...4 PASSES THROUGH THE LOOP CALL GETBY ;DATA IN B, CHECKSUM IN A & D JNZ CATLP ; LOOP TO GET DATA INTO MEMORY AT HL, ; AND GET CHECKSUM IN A WHEN THE LOOP ENDS MOV E,C ;LOOP COUNT = RECORD LENGTH+1 BYTLP: CALL GETBY ;DATA IN B, CHECKSUM IN A & D JM CHKSM ;DONE ONCE WE HAVE CHECKSUM MOV M,B ;MOVE DATA INTO MEMORY INX H JMP BYTLP ;*************************************************************** ; SUBROUTINE TO GET 2 HEX DIGITS FROM THE SPECIFIED PSEUDOPORT, ; COMBINE THEM INTO A BYTE, AND ADD RESULT TO CHECKSUM. ; ; TO KEEP THIS CODE SHORT, DON'T ACTUALLY TEST FOR ASCII ; CHARACTER ERRORS - LET THE CHECKSUM CATCH THESE ERRORS. WHEN ; WE COMBINE NIBBLES, WE USE 'ADD' INSTEAD OF 'ORA' SO THAT WE ; ARE A LITTLE MORE LIKELY TO CATCH AN ERROR WITH THE CHECKSUM. ; ON ENTRY: ; D = CHCKSUM SO FAR ; E = LOOP COUNT ; ON EXIT: ; B=BYTE OF DATA ; A=D=NEW CHECKSUM VALUE ; E HAS BEEN DECREMENTED ; Z FLAG SET IF E=0, M FLAG SET IF E<0 ; ALL OTHER REGISTERS PRESERVED ;*************************************************************** GETBY: CALL GETHX ;GET HIGH NIBBLE RLC ;SHIFT HIGH NIBBLE IN PLACE RLC RLC RLC MOV B,A CALL GETHX ;GET LOW NIBBLE ADD B ;COMBINE NIBBLES, CATCH ERRORS MOV B,A ;SAVE RESULT FOR RETURN ADC D ;COMPUTE CHECKSUM, CATCH ERRORS MOV D,A DCR E ;BUMP LOOP COUNT, TEST RET ;*************************************************************** ; SUBROUTINE TO GET ONE CHR FROM SPECIFIED PSEUDOPORT AND ; CONVERT IT TO A HEX DIGIT, TESTING FOR COLON ALONG THE WAY. ; ; IGNORE NULLS, STRIP PARITY ; ON EXIT: ; Z SET IF CHR WAS A COLON, A=0AH IF SO ; NEW NIBBLE IS IN A <3:0>, A>0FH FOR MOST WRONG CHRS ; ALL OTHER REGISTERS PRESERVED ;*************************************************************** GETHX: MVI A,SERPP ;SERIAL PSEUDOPORT CALL SOLOS+AINP ;A=0 AND Z SET IF NO CHR ANI 7FH ;STRIP PARITY, TEST NULL, NO CHR JZ GETHX ;SPIN UNTIL CHARACTER SUI '0' ;REMOVE ASCII BIAS CPI 10 ;0-9? RC ;YES: WE'RE DONE, Z CLEARED RZ ;COLON IS ASCII '9' + 1, Z SET SUI 'A'-'9'-1 ;SUBTRACT GAP TO ASCII A, CLR Z RET ;RETURN WITH CHR IN A, Z CLEAR END