' HPUSB v0.41 11/23/10 ' Code is for modified gcbasic (0.9 10/11/2010) and gpasm from gptools 0.13.7 ' Compiler mods ensure proper CALL/RCALL generation.. should compile with stock ' GCB if 1024 const in OptimiseCalls subroutine is reduced to 50 (not optimal). ' ' This code implements a VDRIVE disk controller for a HP21xx minicomputer. ' For use with VDOS or UDOS, or can be used as a stand-alone PT emulator. ' ' Work in progress. History... ' Version 0.0 11/1/10 started coding ' 11/4/10 most of the low-level stuff is in place, VDRIVE ' works in debug mode via the serial port. SPI I/O ' appears to work (LED's light) but not fully tested yet. ' Stream stuff tested up to the point of loading buffer. ' 11/6/10 most of the disk command stuff is in place.. starting ' testing.. machine boots but loader shows checksum error ' VDIR works but triggers an "unknown error" on the LCD ' lots of debugging to do but it's trying to work! ' Still have to add manual switch/attachment code. ' Version 0.1 11/7/10 Re-coded compound bit conditions and string compares ' Added code to reject false commands from glitches ' Manual file attach code in place. Boots w/o cs error ' (buffer fill was setting false error on last block) ' Working on VDOS operation - discovering spec bugs :-) ' Most transfers have to be 2-way - put data on buss ' then assert the clock pulse (original intention was ' to require a separate transfer for receive data but ' that's not how the 8052-based firmware and VDOS ended ' up being written, and why STC,C fetch didn't work). ' Seems to work at 32mhz, calling it a 0.1 version. ' Version 0.2 11/7/10 Enhancements... mod'd serial VDRIVE prompt to select ' ECS IPH at startup, added raw mode (char 254), only ' interprets Esc 254 255 when at empty prompt, should ' ignore chars if manipulating files from a PC client. ' Modified manual attach so it prompts to overwrite ' if a write file exists. ' 11/8/10 Added debug menu and serial attach menu - debug menu ' has options for checking hardware (plus the prompt), ' serial menu has options for attaching files and prompt. ' Modified manual attach so if confirmed then it switches ' to PTR emulator mode, ignoring whatever is currently on ' the high bits unless they change. VDsync and file open ' commands are never ignored. ' Implemented the read/write not open error codes. ' Version 0.21 11/9/10 Fixed bug in debug menu command state display. ' Version 0.3 11/13/10 Modified serial read attach to open in PTR mode, ' simplified MyPeek and MyPoke subs, added subs for ' getting command states and the ability to invert the ' polarity of command and/or flag signals along with ' serial and LCD setup to change, made so get error ' command does not update LCD, added EngagePTRmode sub ' and made so initial boot and manual attaches call it. ' Version 0.31 11/14/10 Added setup options for command and flag delays... ' ran into a few intermittant issues using the ' microcircuit interface, some related to the VDOS bug ' but also maybe because flag pulse too short (or long). ' Added flag clocks to startup but effect unknown. ' Version 0.32 11/17/10 Modified VD clear and sync code, changed to "wait" ' send/receive in all subs that send VDRIVE commands. ' Version 0.4 11/21/10 Modified VDsend,VDsendWait,VDreceive,VDreceiveWait, ' SelectSCS,VDclear to increase speed. Mod'd DeleteFile ' and FillReadBuffer for better error detection. Added ' define for VDclear wait time. Mod'd VDprompt for "fast" ' receive, now always emits [ready][cr] if no data even ' in raw mode, afterwards parses 253=get more data, ' 1=don't interpret special chars (in case data vals). ' Note..raw mode not tested, for possible future use. ' Rearranged menu items in serial menu so prompt is "A". ' Mod'd DC_clearVD to wait longer for clear data. ' Increased read/write buffer sizes, moved flag clock ' in some of the DC_targets to increase HP multitasking. ' Mod'd DC_punchwrite so LED's will show punch data. ' Version 0.41 11/23/10 Made VDOS VCLEAR wait time configurable. ' Fixed GetFilenameFromHP to permit empty string. ' ' The source code for the program is written by Terry Newton, it is provided ' as-is and without warranty of any kind. Under no circumstances shall the ' author be held liable for damages resulting from the use of the software. ' The source code itself is public domain and may be used for any purpose. ' The hex file that results from compiling this program includes libraries ' from the Great Cow Basic compiler that are Copyright Hugh Considine and ' Stefano Bonomi under the terms of the Lesser GNU Public License v2.1 or ' later. Source code is available from: http://gcbasic.sourceforge.net/ ' #chip 18F2525, 8 #config OSC = INT, BODEN = OFF, WDT = OFF, MCLRE = ON, LVP = OFF #define signonstring "** HPUSB 0.41 **" #define DEFAULTBOOT "HPBOOT" #define FLUSHTIMEOUTVALUE 5000 #define QUADCLOCK 1 '0 = 8mhz clock, 1 = 32mhz clock #define DEBUGMSG 0 '1 for debugging messages to ser port #define SERPOL 1 '1 for direct connect, 0 for MAX232 etc #define USART_BLOCKING true #script if QUADCLOCK = 1 then 'if PLL enabled USART_BAUD_RATE = 2400 ' use 2400 to mean 9600 baud CLEAR_MS = 8 ' wait for VDclear, use 8 for 2ms CLEAR_VDOS = 100 ' wait for VDOS VCLEAR word, 100 = 25ms end if if QUADCLOCK = 0 then 'if PLL not enabled USART_BAUD_RATE = 9600 'for normal 8mhz clock CLEAR_MS = 2 CLEAR_VDOS = 25 end if #endscript 'needed for 2-wire LCD routines... #define LCD_IO 2 #define LCD_NO_RW #define LCD_DB portb.6 #define LCD_CB portb.5 'pin assignments... #define flag1out porta.0 #define flag2out porta.1 #define command1in porta.2 #define command2in porta.3 #define switchAin porta.4 #define switchBin porta.5 #define switchCin porta.7 #define switchDin porta.6 #define LED0 portb.0 #define LED1 portb.1 #define LED2 portb.2 #define LED3 portb.3 #define LED4 portb.4 #define IOenable portb.7 #define readyLED portc.0 #define busyLED portc.1 #define VDenable portc.2 #define SPIclock portc.3 #define SPIdatain portc.4 #define SPIdataout portc.5 #define serialout portc.6 #define serialin portc.7 'stream buffers #define readbufferstart 0x200 #define readbuffersize 1536 #define readbuffersizehigh 6 'readbuffersize/256 #define readbuffersizelow 0 'readbuffersize AND 255 #define writebufferstart 0x800 #define writebuffersize 1280 'end at 0xCFF #define writebuffersizehigh 5 'writebuffersize/256 #define writebuffersizelow 0 'writebuffersize AND 255 'error codes #define error_nodisk 1 #define error_commandfailed 2 #define error_invalidfilename 3 #define error_fileopen 4 #define error_diskfull 5 #define error_inputnotopen 6 #define error_outputnotopen 7 #define error_eof 8 #define error_zerosize 9 #define error_other 255 'disk commands #define command_readVD b'10100000' #define command_writeVD b'10100010' #define command_syncVD b'10100100' #define command_clearVD b'10100110' #define command_openreadfile b'10110000' #define command_readfromfile b'10110010' #define command_readasPTR b'10110100' #define command_openwritefile b'10111000' #define command_writetofile b'10111010' #define command_closefile b'10111100' #define command_geterror b'10111110' 'variables... gobs of ram not worried about consolidating 'only "global" word and bit variables listed here, internal 'sub variables automatically init'd if not listed '(all vars are global whether in a sub or not) Dim mainpolarity as byte Dim punchpolarity as byte Dim readbufferptr as word Dim writebufferptr as word Dim fwbpointer as word Dim bufferaddress as word Dim readfilename as string Dim writefilename as string Dim subfilename as string Dim buffer as string Dim HPin as word Dim HPout as word Dim HPpunchin as byte Dim VDclearcount as word Dim VDerror as byte Dim nullvar as byte 'the bitbucket Dim wordtemp as word Dim tempword as word Dim xfertempword as word Dim gobalerror as byte Dim readfileopenflag as bit 'flags Dim writefileopenflag as bit Dim readfilezeroflag as bit Dim gotmaincommand as bit Dim gotpunchcommand as bit Dim PTRmodeflag as bit 'when set then reads with high command = 0 Dim PTRignorecommand 'or high command = PTRignorecommand read as PTR Dim endoffileflag as bit Dim readfilesize0 'read file size lsb to msb Dim readfilesize1 Dim readfilesize2 Dim readfilesize3 Dim readfileptr0 'read file pointer lsb to msb Dim readfileptr1 Dim readfileptr2 Dim readfileptr3 Dim flushtimeoutcounter as word Dim gptemp as byte Dim LEDmode as byte Dim readfnsave as string Dim writefnsave as string Dim switchApressed as bit Dim switchBpressed as bit Dim debugmodeonstartup as byte Dim fchar as byte Dim selection as byte Dim commandflagsetup as byte 'flag/command bits... #define invertmaincommand commandflagsetup.0 #define invertmainflag commandflagsetup.1 #define invertpunchcommand commandflagsetup.2 #define invertpunchflag commandflagsetup.3 Dim flagdelaybits as byte #define delaymainflag flagdelaybits.0 #define delaypunchflag flagdelaybits.1 Dim commanddelaysetting as byte 'initialize stuff... IntOff 'no interrupts Set IRCF2 on Set IRCF1 on Set IRCF0 on 'max frequency #ifdef QUADCLOCK 1 Set PLLEN on 'enable PLL for 32mhz #endif Set RXDTP SERPOL 'set polarity of serial port Set TXCKP SERPOL 'pin directions... Dir flag1out out Dir flag2out out Dir command1in in Dir command2in in Dir switchAin in Dir switchBin in Dir switchCin in Dir switchDin in Dir serialin in Dir serialout out Dir LED0 out Dir LED1 out Dir LED2 out Dir LED3 out Dir LED4 out Dir readyLED out Dir busyLED out Dir IOenable out Dir VDenable out Dir SPIclock out Dir SPIdataout out Dir SPIdatain in Dir LCD_DB out Dir LCD_CB out 'default pin states... Set VDenable 0 Set IOenable 1 Set SPIclock 0 Set SPIdataout 0 Set LCD_DB 0 Set LCD_CB 0 Set readyLED 0 Set busyLED 1 Set LED0 0 Set LED1 0 Set LED2 0 Set LED3 0 Set LED4 0 'read setup from eeprom EPread 0, mainpolarity EPread 1, punchpolarity EPread 2, LEDmode EPread 3, debugmodeonstartup EPread 4, commandflagsetup EPread 5, commanddelaysetting EPread 6, flagdelaybits LEDmode = LEDmode And b'00000111' 'reduce to 0-7 debugmodeonstartup = debugmodeonstartup And 1 'reduce to 0 or 1 If commandflagsetup = 255 Then commandflagsetup = 0 'default to normal commandflagsetup = commandflagsetup And b'00001111' 'reduce to 0-15 'main command invert = bit 0 'main flag invert = bit 1 'punch command invert = bit 2 'punch flag invert = bit 3 commanddelaysetting = commanddelaysetting And 3 '0-3 '0 = none (no extra delay) '1 = fast (delay 5 us) '2 = medium (delay 10 us) '3 = slow (delay 25 us) (default) flagdelaybits = flagdelaybits And 3 'default to slow 'set default flag outs If mainpolarity = 0 Then If invertmainflag Then Set flag1out 0 'normal invflag set out to 1 Else Set flag1out 1 'normal normal set out to 0 End If Else If invertmainflag Then Set flag1out 0 'invert invflag set out to 1 Else Set flag1out 1 'invert normal set out to 0 End If End If If punchpolarity = 0 Then If invertpunchflag Then Set flag2out 0 Else Set flag2out 1 End If Else If invertpunchflag Then Set flag2out 0 Else Set flag2out 1 End If End If InitSPI 'set up hardware SPI registers 'delay 250ms to make sure I/O chips are out of reset #ifdef QUADCLOCK 1 Wait 1 s 'when PLL is used all delays have to be quadrupled #endif #ifdef QUADCLOCK 0 Wait 250 ms #endif InitIOchips 'set up I/O chip addressing and port directions TestLEDport 'flash LED's to indicate I/O is up and running 'jump here if a command line gets stuck restartcontroller: Set readfileopenflag 0 Set writefileopenflag 0 Set endoffileflag 1 Set PTRmodeflag 0 HPin = [word]0 HPout = [word]0 readfilename(0) = 0 writefilename(0) = 0 globalerror = 0 #ifdef QUADCLOCK 1 Wait 1 s #endif #ifdef QUADCLOCK 0 Wait 250 ms #endif ClockMainFlag 'sometimes needed to clear I/O boards ClockPunchFlag '-------- detect serial debug mode ------------------- Set PLLEN off 'have to switch to normal clock to use LCD InitLCD 'this is added by GCB at startup but doesn't "take" If debugmodeonstartup <> 0 Then If Not serialin Then CLS Print signonstring Locate 1,0 Print "Debug mode" #ifdef QUADCLOCK 1 Set PLLEN on 'run serial stuff at quad speed so baud will be right #endif SerialDebug docrlf HSerPrint "Starting control software" docrlf Wait 200 ms Set PLLEN off 'setup stuff runs at normal speed so LCD will work End If End If '-------- startup stuff ------------------------------ CLS Print signonstring Locate 1,0 Print "D for setup" Wait 1 s If switchDin Then Goto waitforcommandsclear setuppolarity: DoSetup CLS Print signonstring 'wait for HP command lines to clear waitforcommandsclear: GetMainCommandState GetPunchCommandState If gotmaincommand Then Goto showwaitmessage If gotpunchcommand Then Goto showwaitmessage Goto commandlinesclear showwaitmessage: Locate 1,0 Print "Waiting on HP " waitforclearcommands: If Not switchDin Then Goto setuppolarity GetMainCommandState GetPunchCommandState If gotmaincommand Then Goto waitforclearcommands If gotpunchcommand Then Goto waitforclearcommands 'weed out transients GetMainCommandState GetPunchCommandState If gotmaincommand Then Goto waitforclearcommands If gotpunchcommand Then Goto waitforclearcommands commandlinesclear: Locate 1,0 Print "Syncing VDRIVE " VDsync VDerrorTrap readfilename = DEFAULTBOOT If readfilename(0) <> 0 Then Locate 1,0 Print "SF " Locate 1,3 Print readfilename #ifdef QUADCLOCK 1 Set PLLEN on #endif OpenReadFile EngagePTRmode End If '======= main processing loops ======================= 'show error condition or file attachments on the LCD showfileassignments: Set PLLEN off CLS If globalerror = error_nodisk Then Print "No disk" Else If globalerror = error_invalidfilename Then Print "Bad Filename" Else If globalerror = error_fileopen Then Print "IntFile open" Else If globalerror = error_other Then Print "Unknown error" Else Print "RF:" Print readfilename Locate 1,0 Print "WF:" Print writefilename If globalerror <> 0 Then If globalerror = 5 Or globalerror = 7 Then Locate 1,15 Else Locate 0,15 End If Print globalerror End If End If End If End If End If '--- inner loop -------------------------------------- getmoreinput: #ifdef QUADCLOCK 1 Set PLLEN on #endif 'light data LED's according to setup If LEDmode <> 0 Then gptemp = 0 If LEDmode.0 Then 'show command LEDbyte = HPin_h gptemp = 1 End If If LEDmode.1 Then 'show read transfer If HPin_h = command_readfromfile Or HPin_h = 0 Then LEDbyte = [byte]HPout gptemp = 1 End If End If If LEDmode.2 Then 'show write transfer If HPin_h = command_writetofile Then LEDbyte = [byte]HPin gptemp = 1 End If End If If GPtemp <> 0 Then WriteLEDbyte LEDbyte 'only show if triggered End If 'wait for HP - this might need tweeking depending on HP-side SW/speed If commanddelaysetting = 1 Then #ifdef QUADCLOCK 1 Wait 20 us #endif #ifdef QUADCLOCK 0 Wait 5 us #endif Else If commanddelaysetting = 2 Then #ifdef QUADCLOCK 1 Wait 40 us #endif #ifdef QUADCLOCK 0 Wait 10 us #endif Else If commanddelaysetting = 3 Then #ifdef QUADCLOCK 1 Wait 200 us #endif #ifdef QUADCLOCK 0 Wait 50 us #endif End If End If End If 'light "fast" LED's to show status 'readyLED lights when waiting for a HP command 'busyLED lights when processing a command or otherwise busy 'LED0 lights when serial port is active 'LED1 lights when a read file is open 'LED2 lights when a write file is open 'LED3 is a debugging LED, lights after receiving a disk command 'LED4 lights when global error isn't 0 (eof or other error) Set LED3 0 'waiting for a command Set readyLED 1 Set busyLED 0 UpdateStatusLeds 'update LED1 LED2 and LED4 'wait for command line or switch activity WaitForInput Set readyLED 0 Set busyLED 1 If gotpunchcommand Then 'process punch DC_punchwrite Goto getmoreinput End If If gotmaincommand Then 'process disk commands ReceiveMainWord HPin Set LED3 1 If PTRmodeflag Then If HPin_h = PTRignorecommand Then DC_PTread Goto getmoreinput End If End If Set PTRmodeflag 0 'got something different so back to normal processing 'identify command, perform action, branch to get another command or show LCD If HPin_h = command_readVD Then DC_readVD : Goto getmoreinput If HPin_h = command_writeVD Then DC_writeVD : Goto getmoreinput If HPin_h = command_syncVD Then DC_syncVD : Goto getmoreinput If HPin_h = command_clearVD Then DC_clearVD : Goto getmoreinput If HPin_h = command_openreadfile Then DC_openreadfile : Goto showfileassignments If HPin_h = command_readfromfile Then DC_readfromfile : Goto getmoreinput If HPin_h = command_readasPTR Then DC_readasPTR : Goto getmoreinput If HPin_h = command_openwritefile Then DC_openwritefile : Goto showfileassignments If HPin_h = command_writetofile Then DC_writetofile : Goto getmoreinput If HPin_h = command_closefile Then DC_closefile : Goto showfileassignments If HPin_h = command_geterror Then DC_geterror : Goto getmoreinput If HPin_h = 0 Then DC_PTread : Goto getmoreinput 'command not recognized ClockMainFlag globalerror = error_other 'check for stuck command line, probably as a result of shutting 'down with 12V I/O card, interpreted as all bits high 'if main or punch command logically asserted then restart GetMainCommandState If gotmaincommand Then Goto restartcontroller GetPunchCommandState If gotpunchcommand Then Goto restartcontroller Goto showfileassignments 'show the error End If 'here if a switch was pressed... 'switch A sets read file 'switch B sets write file 'switch C displays error condition on LCD 'switch D runs serial menu if connected Set PLLEN off Set switchApressed 0 Set switchBpressed 0 If Not switchAin Then Set switchApressed 1 : Goto domanualattach If Not switchBin Then Set switchBpressed 1 : Goto domanualattach If Not switchDin Then Goto doserialmenu Goto delayandshowassignments domanualattach: ManualFileAttach delayandshowassignments: Wait 200 ms Goto showfileassignments doserialmenu: If Not serialin Then CLS Print "Serial menu" SerialMenu docrlf HSerPrint "Resuming run mode" docrlf Wait 200 ms End If Goto showfileassignments '======== end of main processing loops =============== '-------- utility subs ------------------------------- 'this sets readfilezeroflag if readfilesize0-3 all zero Sub DetectZeroSize Set readfilezeroflag 1 If readfilesize0 <> 0 Then Set readfilezeroflag 0 If readfilesize1 <> 0 Then Set readfilezeroflag 0 If readfilesize2 <> 0 Then Set readfilezeroflag 0 If readfilesize3 <> 0 Then Set readfilezeroflag 0 End Sub 'this sets endoffileflag if readfileptr0-3 = readfilesize0-3 Sub DetectEOF Set endoffileflag 1 If readfileptr0 <> readfilesize0 Then Set endoffileflag 0 If readfileptr1 <> readfilesize1 Then Set endoffileflag 0 If readfileptr2 <> readfilesize2 Then Set endoffileflag 0 If readfileptr3 <> readfilesize3 Then Set endoffileflag 0 End Sub 'this increments readfileptr and sets endoffileflag when at end 'must start out with endoffileflag clear and readfileptr0-3 all zero Sub IncrementReadFilePointer If Not endoffileflag Then readfileptr0 = readfileptr0 + 1 If readfileptr0 = 0 Then readfileptr1 = readfileptr1 + 1 If readfileptr1 = 0 Then readfileptr2 = readfileptr2 + 1 If readfileptr2 = 0 Then readfileptr3 = readfileptr3 + 1 End If End If End If DetectEOF End If End Sub Sub MyPeek(subramaddress as word, subramdata as byte) fsr0l = subramaddress fsr0h = subramaddress_h subramdata = indf0 End Sub Sub MyPoke(subramaddress as word, subramdata as byte) fsr0l = subramaddress fsr0h = subramaddress_h indf0 = subramdata End Sub 'call this after calling something that might set VDerror 'to hard-lock if VDerror is non-zero - mainly for startup stuff, 'for normal operations better to time out and detect the error 'condition more gracefully without locking up the HP transfer Sub VDerrorTrap If VDerror <> 0 Then Set PLLEN 0 CLS Print "VDRIVE Error" Print VDerror Locate 1,0 Print "System Halted" baderrorlockup: Goto baderrorlockup End If End Sub 'set up main and punch polarity, LED functions Sub DoSetup CLS Print "Setup polarity" setup0: Wait 100 ms If Not switchDin Then Goto setup0 setup1: Locate 1,0 Print "Main: " If mainpolarity = 0 Then Print "normal " Else Print "inverted " End If Wait 100 ms setup2: If Not switchAin Then Goto setupmain If switchBin Then Goto setup2 setup3: Wait 100 ms If Not switchBin Then Goto setup3 setup4: Locate 1,0 Print "Punch: " If punchpolarity = 0 Then Print "normal " Else Print "inverted " End If Wait 100 ms setup5: If Not switchAin Then goto setuppunch If switchBin Then goto setup5 setup6: Wait 100 ms If Not switchBin Then Goto setup6 Goto setupLEDtransfer setupmain: If Not switchAin Then Goto setupmain If mainpolarity = 0 Then mainpolarity = 1 Else mainpolarity = 0 End If Goto setup1 setuppunch: If Not switchAin Then Goto setuppunch If punchpolarity = 0 Then punchpolarity = 1 Else punchpolarity = 0 End If Goto setup4 setupLEDtransfer: CLS Print "Setup LEDs C R W" setup10: Locate 1,0 If LEDmode.0 Then Print "On " Else Print "Off" End If Locate 1,6 If LEDmode.1 Then Print "On " Else Print "Off" End If Locate 1,12 If LEDmode.2 Then Print "On " Else Print "Off" End If setup11: If Not switchBin Then Goto setup20 If switchAin Then Goto setup11 setup12: Wait 100 ms If Not switchAin Then Goto setup12 LEDmode = LEDmode + 1 LEDmode = LEDmode And b'00000111' Goto setup10 setup20: If Not switchBin Then Goto setup20 CLS Print "Serial debug" Locate 1,0 Print "at startup:" setup21: Locate 1,12 If debugmodeonstartup <> 0 Then Print "Yes" Else Print "No " End If setup22: Wait 100 ms If Not switchBin Then Goto setup30 If switchAin Then Goto setup22 setup23: If Not switchAin Then Goto setup23 If debugmodeonstartup = 0 Then debugmodeonstartup = 1 Else debugmodeonstartup = 0 End If Goto setup21 setup30: If Not switchBin Then Goto setup30 CLS Print "Main control" setup31: Wait 100 ms Locate 1,0 temp = commandflagsetup And b'00000011' If temp = 0 Then Print "normal " Else If temp = 1 Then Print "command flipped " Else If temp = 2 Then Print "flag flipped " Else Print "cmd/flag flipped" End If End If End If setup32: If Not switchBin Then Goto setup40 If switchAin Then Goto setup32 Wait 100 ms setup33: If Not switchAin Then Goto setup33 temp = commandflagsetup And b'00000011' temp = temp + 1 temp = temp And b'00000011' commandflagsetup = commandflagsetup And b'00001100' commandflagsetup = commandflagsetup Or temp Goto setup31 setup40: If Not switchBin Then Goto setup40 CLS Print "Punch control" setup41: Wait 100 ms Locate 1,0 temp = commandflagsetup And b'00001100' If temp = 0 Then Print "normal " Else If temp = 4 Then Print "command flipped " Else If temp = 8 Then Print "flag flipped " Else Print "cmd/flag flipped" End If End If End If setup42: If Not switchBin Then Goto setup50 If switchAin Then Goto setup42 Wait 100 ms setup43: If Not switchAin Then Goto setup43 temp = commandflagsetup And b'00001100' temp = temp + 4 temp = temp And b'00001100' commandflagsetup = commandflagsetup And b'00000011' commandflagsetup = commandflagsetup Or temp Goto setup41 setup50: If Not switchBin Then Goto setup50 CLS Print "Command delay" setup51: Wait 100 ms Locate 1,0 If commanddelaysetting = 0 Then Print "no extra delay" Else If commanddelaysetting = 1 Then Print "fast (5us) " Else If commanddelaysetting = 2 Then Print "medium (10us) " Else Print "slow (50us) " End If End If End If setup52: Wait 100 ms If Not switchBin Then Goto setup60 If switchAin Then Goto setup52 commanddelaysetting = commanddelaysetting + 1 commanddelaysetting = commanddelaysetting And 3 Goto setup51 setup60: If Not switchBin Then Goto setup60 CLS Print "Flag Times (M,P)" setup61: Wait 200 ms Locate 1,0 If delaymainflag Then Print "Slow " Else Print "Fast " End If If delaypunchflag Then Print "Slow " Else Print "Fast " End If setup62: Wait 100 ms If Not switchBin Then Goto setup99 If switchAin Then Goto setup62 flagdelaybits = flagdelaybits + 1 flagdelaybits = flagdelaybits And 3 Goto setup61 setup99: wait 100 ms If Not switchBin Then Goto setup99 'save settings to eeprom EPwrite 0, mainpolarity EPwrite 1, punchpolarity EPwrite 2, LEDmode EPwrite 3, debugmodeonstartup EPwrite 4, commandflagsetup EPwrite 5, commanddelaysetting EPwrite 6, flagdelaybits End Sub Sub ManualFileAttach 'A switch selects read filename 'B switch selects write filename 'C switch confirms selection 'D switch restores previous assignments 'bits switchApressed and switchBpressed set by caller 'one or other should be set 'after confirming, file is not opened/closed/reopened unless name changed #ifdef QUADCLOCK 1 Set PLLEN on 'always do VDRIVE ops at specified speed for timing! #endif FlushWriteBuffer 'if a write file is open then save it readfnsave = readfilename 'save filenames to restore if cancelled writefnsave = writefilename If switchApressed Then readfilename(0) = 0 If switchBpressed Then writefilename(0) = 0 Set PLLEN off 'make sure all switches released mfarelease: If Not switchAin Then Goto mfarelease If Not switchBin Then Goto mfarelease If Not switchCin Then Goto mfarelease If Not switchDin Then Goto mfarelease Wait 100 ms 'for switch to stop bouncing CLS 'erase error messages Print "RF:" Print readfilename Locate 1,0 Print "WF:" Print writefilename fileswitchloop: Wait 100 ms If Not switchAin Then CycleReadFilename ShowReadFilename End If If Not switchBin Then CycleWriteFilename ShowWriteFilename End If If Not switchCin Then Goto openselectedfiles If Not switchDin Then Goto abandonchanges Goto fileswitchloop '----- openselectedfiles: #ifdef QUADCLOCK 1 Set PLLEN on #endif EngagePTRmode 'ignore command if it repeats to read in PTR mode If readfilename(0) = 0 And readfnsave(0) = 0 Then Goto checkwfchange If readfilename(0) = readfnsave(0) Then If readfilename(1) = readfnsave(1) Then Goto checkwfchange End If End If 'read file changed, open/close it #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " Calling OpenReadFile " : Wait 100 ms #endif OpenReadFile checkwfchange: If writefilename(0) = 0 And writefnsave(0) = 0 Then Goto attachexit If writefilename(0) = writefnsave(0) Then If writefilename(1) = writefnsave(1) Then Goto attachexit End If End If 'write file changed, open/cancel it 'check to see if write file exists If writefilename(0) <> 0 Then subfilename = writefilename globalerror = 0 CheckFileWithDir VDclear If globalerror = 0 Then 'file exists, prompt to overwrite Set PLLEN off Wait 100 ms CLS Print "File " Print writefilename Print " exists" 'should fit, only 1 char filenames here Locate 1,0 Print "C to overwrite" 'make sure previous confirm is released waitforOWrelease: wait 50 ms if Not switchCin Then Goto waitforOWrelease waitforOWconfirm: Wait 100 ms If Not switchCin Then Goto overwriteconfirmed If Not switchAin Then Goto overwritenotconfirmed If Not switchBin Then Goto overwritenotconfirmed If Not switchDin Then Goto overwritenotconfirmed Goto waitforOWconfirm overwriteconfirmed: CLS Print "Deleting file " Print writefilename Locate 1,0 Print "to overwrite" Wait 1 s #ifdef QUADCLOCK 1 Set PLLEN on #endif DeleteFile 'filename in subfilename If globalerror <> 0 Then Set PLLEN off Wait 100 ms CLS Print "Error deleting" Locate 1,0 Print "file (cleared)" Wait 1 s Goto abandonchanges End If Goto endoverwriteconfirmstuff overwritenotconfirmed: CLS Print "Appending to" Locate 1,0 Print "file " Print writefilename Wait 1 s endoverwriteconfirmstuff: #ifdef QUADCLOCK 1 Set PLLEN on #endif End If End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " Calling OpenWriteFile " : Wait 100 ms #endif OpenWriteFile Goto attachexit '----- abandonchanges: globalerror = 0 'clear global error readfilename = readfnsave writefilename = writefnsave '----- attachexit: Set PLLEN off End Sub Sub CycleReadFilename subfilename = readfilename CycleFilename readfilename = subfilename End Sub Sub CycleWriteFilename subfilename = writefilename CycleFilename writefilename = subfilename End Sub Sub CycleFilename 'make sure single char or empty If subfilename(0) <> 0 Then If subfilename(0) > 1 Then subfilename(0) = 0 Else If subfilename(1) < 65 Then subfilename(0) = 0 Else If subfilename(1) > 91 Then subfilename(0) = 0 End If End If End If End If 'any non-single-letter filename cleared If subfilename(0) = 0 Then subfilename = "A" Else If subfilename = "Z" Then subfilename(0) = 0 Else gptemp = subfilename(1) gptemp = gptemp + 1 subfilename(1) = gptemp End If End If Wait 100 ms End Sub Sub ShowReadFilename Locate 0,3 Print " " Locate 0,3 Print readfilename End Sub Sub ShowWriteFilename Locate 1,3 Print " " Locate 1,3 Print writefilename End Sub Sub UpdateStatusLeds 'updates the states of LED1 LED2 and LED4 If globalerror <> 0 Then Set LED4 1 Else Set LED4 0 End If If readfileopenflag Then Set LED1 1 Else Set LED1 0 End If If writefileopenflag Then Set LED2 1 Else Set LED2 0 End If End Sub Sub EngagePTRmode 'any time the manual attach function is used it is 'assumed that the user wants to access the file in PTR mode 'read interface to see what's on the high bits ReceiveMainWord tempword PTRignorecommand = tempword_h 'ignore whatever was sent last Set PTRmodeflag 1 'be a PTR emulator until told different 'this could have side effects... so don't ignore certain commands... 'never ignore commands that trigger extra transfers... If PTRignorecommand = command_openreadfile Then Set PTRmodeflag 0 If PTRignorecommand = command_openwritefile Then Set PTRmodeflag 0 If PTRignorecommand = command_syncVD Then Set PTRmodeflag 0 If PTRignorecommand = 0 Then Set PTRmodeflag 0 'let 0 be processed normally End Sub '-------- hardware SPI drivers ----------------------- 'initialize hardware SPI port Sub InitSPI SSPSTAT = b'01000000' 'bit 7 SMP input sample = middle 'bit 6 CKE clock out after setting data bit Set SSPCON1.5 0 'clear enable bit SSPCON1 = b'00100000' 'bit 5 SSPEN on 'bit 4 CKP clock pol idle = 0 'bits 0-3 master mode clock = osc/4 End Sub Sub DisableSPI Set SSPCON1.5 0 End Sub 'delay for SPI transfers Sub SPIdelay Wait 10 us End Sub 'send one byte via hardware SPI Sub SPIsend(SPIdata) SSPBUF = SPIdata SPIdelay End Sub 'receive one byte via hardware SPI Sub SPIreceive(SPIdata) SSPBUF = 0 'start receive waitforSPIbyte: If Not BF Then Goto waitforSPIbyte SPIdata = SSPBUF SPIdelay End Sub '-------- MCP23S17 drivers --------------------------- 'initialize chips - tell them to use hardware addressing 'then set the direction bits on each of the chips Sub InitIOchips Set IOenable 0 SPIsend b'01000000' 'address 0 write SPIsend 0x0A 'IOCON reg SPIsend b'00001000' 'set HAEN bit Set IOenable 1 SPIdelay 'chip 0 already set to inputs after reset Set IOenable 0 SPIsend b'01000010' 'select chip 1 (outputs) SPIsend 0x00 'IODIRA reg SPIsend 0x00 'set to outputs SPIsend 0x00 'set IODIRB to outputs Set IOenable 1 SPIdelay Set IOenable 0 SPIsend b'01000100' 'select chip 2 (A=ins, B=outs) SPIsend 0x01 'IODIRB reg SPIsend 0x00 'set to outputs Set IOenable 1 End Sub 'read a word from IO chip 0 'parm = return word from HP main outs Sub ReadChipWord(IOword as word) Set IOenable 0 SPIsend b'01000001' SPIsend 0x12 'start with GPIOA SPIreceive [byte]IOword SPIreceive IOword_h Set IOenable 1 End Sub 'write a word to IO chip 1 'parm = word to write to HP main ins Sub WriteChipWord(IOword as word) Set IOenable 0 SPIsend b'01000010' SPIsend 0x12 'start with GPIOA SPIsend [byte]IOword SPIsend IOword_h Set IOenable 1 End Sub 'read a byte from IO chip 0 'parm = return byte from HP main outs Sub ReadChipByte(IObyte) Set IOenable 0 SPIsend b'01000001' SPIsend 0x12 'GPIOA SPIreceive IObyte Set IOenable 1 End Sub 'write a byte to IO chip 1 'parm = word to write to HP main ins Sub WriteChipByte(IObyte) Set IOenable 0 SPIsend b'01000010' SPIsend 0x12 SPIsend IObyte Set IOenable 1 End Sub 'read a byte from IO chip 2 port A 'parm = byte from HP punch outs Sub ReadPunchChipByte(IObyte) Set IOenable 0 SPIsend b'01000101' SPIsend 0x12 SPIreceive IObyte Set IOenable 1 End Sub 'write a byte to IO chip 2 port B 'parm = byte to send to LED's Sub WriteLEDbyte(IObyte) Set IOenable 0 SPIsend b'01000100' SPIsend 0x13 'GPIOB SPIsend IObyte Set IOenable 1 End Sub 'test SPI by flashing the LED's Sub TestLEDport testtemp = 1 For testloop = 0 To 6 WriteLEDbyte testtemp Rotate testtemp left simple #ifdef QUADCLOCK 1 Wait 100 ms #endif #ifdef QUADCLOCK 0 Wait 25 ms #endif Next testloop WriteLEDbyte 0 End Sub '-------- low level VDRIVE drivers ------------------- ' VDRIVE uses a 11 bit send 1 bit read format, not a good ' match for byte-oriented hardware SPI so bit-banged '0.4 speedup... modified VDsend/VDreceive to try once, 'modified Wait forms to wait forever (no timeout) 'removed delay from clear - prompt needs to do that but slows 'other things down. Leaving parms the same in case timeout added 'back to the VDsendWait and VDreceiveWait 'send one byte to the VDRIVE mod 0.4 'parm1=byte to send, parm2=busy 'if VDRIVE is busy then parm2 is set to 1, 'set to 0 if accepted Sub VDsend(VDbyte,VDbusy) DisableSPI 'turn off hardware SPI Set SPIdataout 0 Set SPIclock 1 'at least 2 clocks with VDenable low Set SPIclock 0 Set SPIclock 1 Set SPIclock 0 Set VDenable 1 Set SPIdataout 1 Set SPIclock 1 'clock out 1 Set SPIclock 0 Set SPIdataout 0 Set SPIclock 1 'clock out 0 for write Set SPIclock 0 Set SPIclock 1 'clock out 0 for data reg Set SPIclock 0 VDtemp1 = VDbyte 'temp byte to shift out For VDtemp2 = 0 To 7 If VDtemp1.7 Then Set SPIdataout 1 Else Set SPIdataout 0 End If Set SPIclock 1 Set SPIclock 0 Rotate VDtemp1 left Next VDtemp2 If SPIdatain Then VDbusy = 1 Else VDbusy = 0 End If Set SPIclock 1 Set SPIclock 0 Set VDenable 0 Set SPIdataout 0 Set SPIclock 1 Set SPIclock 0 InitSPI 'restore HW SPI End Sub 'receive one byte from the VDRIVE mod 0.4 'parm1=byte to receive, parm2=busy 'if VDRIVE has no data ready then parm2 is set to 1, 'set to 0 if data valid Sub VDreceive(VDbyte,VDbusy) DisableSPI Set SPIdataout 0 Set SPIclock 1 'at least 2 clocks with VDenable low Set SPIclock 0 Set SPIclock 1 Set SPIclock 0 Set VDenable 1 Set SPIdataout 1 Set SPIclock 1 'clock out 1 Set SPIclock 0 Set SPIclock 1 'clock out 1 for read Set SPIclock 0 Set SPIdataout 0 Set SPIclock 1 'clock out 0 for data reg Set SPIclock 0 VDbyte = 0 For VDtemp2 = 0 To 7 Rotate VDbyte left If SPIdatain Then Set VDbyte.0 1 Else Set VDbyte.0 0 End If Set SPIclock 1 Set SPIclock 0 Next VDtemp2 If SPIdatain Then VDbusy = 1 Else VDbusy = 0 End If Set SPIclock 1 Set SPIclock 0 Set VDenable 0 Set SPIclock 1 Set SPIclock 0 InitSPI End Sub 'this calls VDsend but waits mod 0.4 Sub VDsendWait(VDbyte1,VDbusy1) VDsendWaitrepeat: VDsend VDbyte1,VDbusy1 If VDbusy1 <> 0 Then Goto VDsendWaitrepeat End Sub 'this calls VDreceive but waits mod 0.4 Sub VDreceiveWait(VDbyte1,VDbusy1) VDreceiveWaitrepeat: VDreceive VDbyte1,VDbusy1 If VDbusy1 <> 0 Then Goto VDreceiveWaitrepeat '0.4 End Sub 'this clears any response data from the VDRIVE mod 0.4 'reads data until it returns no more data 'if no end after 32767 reads it gives up and sets VDerror to 255 Sub VDclear VDclear0: VDerror = 0 VDclearcount = [word]32767 VDclear1: VDreceive nullvar, VDsubtemp If VDsubtemp = 0 Then VDclearcount = VDclearcount - [word]1 If VDclearcount <> 0 Then Goto VDclear1 VDerror = 255 End If 'wait a bit to make sure it's really clear Wait CLEAR_MS ms VDreceive nullvar,VDsubtemp If VDsubtemp = 0 Then Goto VDclear0 'not clear, try again End Sub 'this syncs the VDRIVE Sub VDsync VDsyncerrorcount = 0 VDsyncRepeat: VDclear If VDerror <> 0 Then VDsyncerrorcount = VDsyncerrorcount + 1 If VDsyncerrorcount >= 100 Then Goto VDsyncexit VDsendWait 69,nullvar VDsendWait 13,nullvar VDreceiveWait VDsynctemp,nullvar If VDsynctemp <> 69 Then Goto VDsyncRepeat VDreceiveWait VDsynctemp,nullvar If VDsynctemp <> 13 Then Goto VDsyncRepeat VDsendWait 101,nullvar VDsendWait 13,nullvar VDreceiveWait VDsynctemp,nullvar If VDsynctemp <> 101 Then Goto VDsyncRepeat VDreceiveWait VDsynctemp,nullvar If VDsynctemp <> 13 Then Goto VDsyncRepeat VDclear VDsyncexit: End Sub 'this sends a string to the VDRIVE 'put string to send in buffer 'VDerror set to 1 if string not accepted Sub VDsendString VDerror = 0 VDsslen = buffer(0) If VDsslen > 0 Then For VDssloop = 1 To VDsslen If VDerror = 0 Then VDsstemp = buffer(VDssloop) VDsendWait VDsstemp,VDerror End If Next VDssloop End If End Sub 'this syncs vdrive and selects the short command set 'call before beginning all internal disk sequences Sub SelectSCS 'mod 0.4 VDsync buffer = "SCS" VDsendString VDsendWait 13,nullvar VDreceiveWait nullvar,nullvar VDreceiveWait nullvar,nullvar VDsendWait 0x91,nullvar VDsendWait 13,nullvar VDreceiveWait nullvar,nullvar VDreceiveWait nullvar,nullvar End Sub Sub DeleteFile 'mod 0.4 'subfilename = filename to delete If subfilename(0) <> 0 Then globalerror = 0 SelectSCS VDsendWait 0x07, nullvar 'send delete file command VDsendWait 32, nullvar 'a space buffer = subfilename VDsendString 'send filename to delete VDsendWait 13, nullvar 'cr to terminate command VDreceiveWait bytefromVD1, nullvar 'wait for response VDreceiveWait bytefromVD2, nullvar If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then 'something went wrong globalerror = error_other If bytefromVD1 = 78 And bytefromVD2 = 68 Then globalerror = error_nodisk If bytefromVD1 = 67 And bytefromVD2 = 70 Then globalerror = error_commandfailed If bytefromVD1 = 79 And bytefromVD2 = 70 Then globalerror = error_fileopen If bytefromVD1 = 70 And bytefromVD2 = 78 Then globalerror = error_invalidfilename End If VDclear Else globalerror = error_other 'programmer error End If End Sub '-------- HP transfer drivers ------------------------ 'delay for line settling Sub SettleDelay #ifdef QUADCLOCK 1 Wait 4 us #endif #ifdef QUADCLOCK 0 Wait 1 us #endif End Sub 'added these since some boards have different command polarity 'main and punch polarity bytes determine overall inversion 'invertmaincommand and invertpunchcommand bits invert command signal 'output in gotmaincommand and gotpunchcommand bits Sub GetMainCommandState Set gotmaincommand 0 If mainpolarity = 0 Then If command1in Then Set gotmaincommand 1 End If Else If Not command1in Then Set gotmaincommand 1 End If End If 'invert state if main command is inverted If invertmaincommand Then If gotmaincommand Then Set gotmaincommand 0 Else Set gotmaincommand 1 End If End If End Sub Sub GetPunchCommandState Set gotpunchcommand 0 If punchpolarity = 0 Then If command2in Then Set gotpunchcommand 1 End If Else If Not command2in Then Set gotpunchcommand 1 End If End If 'invert state if punch command is inverted If invertpunchcommand Then If gotpunchcommand Then Set gotpunchcommand 0 Else Set gotpunchcommand 1 End If End If End Sub 'wait for command or switch input 'flushes write buffer if no activity after a period '(FlushWriteBuffer has no effect if write file not open) 'sets gotmaincommand or gotpunchcommand flags if command detected Sub WaitForInput flushtimeoutcounter = [word]FLUSHTIMEOUTVALUE flushinnercounter = 0 waitforinputloop: Set gotmaincommand 0 Set gotpunchcommand 0 flushinnercounter = flushinnercounter + 1 If flushinnercounter = 0 Then If flushtimeoutcounter <> [word]0 Then flushtimeoutcounter = flushtimeoutcounter - [word]1 If flushtimeoutcounter = [word]0 Then FlushWriteBuffer End If End If End If If Not switchAin Then Goto gotcommandorswitchinput If Not switchBin Then Goto gotcommandorswitchinput If Not switchCin Then Goto gotcommandorswitchinput If Not switchDin Then Goto gotcommandorswitchinput GetMainCommandState GetPunchCommandState If gotmaincommand Then Goto gotcommandorswitchinput If gotpunchcommand Then Goto gotcommandorswitchinput Goto waitforinputloop gotcommandorswitchinput: 'ignore very short transients #ifdef QUADCLOCK 1 asm nop asm nop asm nop asm nop asm nop asm nop asm nop asm nop #endif asm nop asm nop asm nop 'check again If gotmaincommand Then 'if command received GetMainCommandState If Not gotmaincommand Then Goto waitforinputloop End If If gotpunchcommand Then GetPunchCommandState If Not gotpunchcommand Then Goto waitforinputloop End If End Sub 'wait for main command - ignore punch and switches 'use this from subroutines to parse required data Sub WaitForMainCommand waitformaincommandloop: GetMainCommandState If Not gotmaincommand Then Goto waitformaincommandloop 'ignore very short transients #ifdef QUADCLOCK 1 asm nop asm nop asm nop asm nop asm nop asm nop asm nop asm nop #endif asm nop asm nop asm nop 'check again GetMainCommandState If Not gotmaincommand Then Goto waitformaincommandloop End Sub 'send a flag pulse to the HP main port 'note all outs invert because of ULN2003's so sets are opposite Sub ClockMainFlag SettleDelay If mainpolarity = 0 Then If invertmainflag Then Set flag1out 1 Else Set flag1out 0 End If Else If invertmainflag Then Set flag1out 0 Else Set flag1out 1 End If End If If delaymainflag Then #ifdef QUADCLOCK 1 Wait 6 us #endif #ifdef QUADCLOCK 0 Wait 1 us #endif Else #ifdef QUADCLOCK 1 Wait 4 us #endif #ifdef QUADCLOCK 0 Asm nop #endif End If If mainpolarity = 0 Then If invertmainflag Then Set flag1out 0 Else Set flag1out 1 End If Else If invertmainflag Then Set flag1out 1 Else Set flag1out 0 End If End If SettleDelay End Sub 'send a flag pulse to the HP punch port Sub ClockPunchFlag SettleDelay If punchpolarity = 0 Then If invertpunchflag Then Set flag2out 1 Else Set flag2out 0 End If Else If invertpunchflag Then Set flag2out 0 Else Set flag2out 1 End If End If If delaypunchflag Then #ifdef QUADCLOCK 1 Wait 6 us #endif #ifdef QUADCLOCK 0 Wait 1 us #endif Else #ifdef QUADCLOCK 1 Wait 4 us #endif #ifdef QUADCLOCK 0 Asm nop #endif End If If punchpolarity = 0 Then If invertpunchflag Then Set flag2out 0 Else Set flag2out 1 End If Else If invertpunchflag Then Set flag2out 1 Else Set flag2out 0 End If End If SettleDelay End Sub ''clear outs to HP in ''call before doing byte transfers to ensure high is clear 'Sub ClearMainOuts 'WriteChipWord [word]0 'End Sub 'transfer word from HP main outs 'parm = word from HP Sub ReceiveMainWord(xferword as word) ReadChipWord xferword If mainpolarity <> 0 Then xferword = Not xferword End Sub 'transfer word to HP main ins 'parm = word to send to HP Sub SendMainWord(xferword as word) xfertempword = xferword 'preserve orig parameter If mainpolarity = 0 Then xfertemp = Not xfertemp WriteChipWord xfertempword End Sub 'transfer byte from HP main outs 'parm = byte from HP Sub ReceiveMainByte(xferbyte) ReadChipByte xferbyte If mainpolarity <> 0 then xferbyte = Not xferbyte End Sub ''transfer byte to HP main ins ''parm = byte to send to HP 'Sub SendMainByte(xferbyte) 'xfertemp = xferbyte 'if mainpolarity = 0 Then xferbyte = Not xferbyte 'WriteChipByte xfertemp 'End Sub 'transfer byte from HP punch outs 'parm = byte from HP punch port Sub ReceivePunchByte(xferbyte) ReadPunchChipByte xferbyte if punchpolarity <> 0 then xferbyte = Not xferbyte End Sub '-------- stream subroutines ------------------------- 'get filename from HP for file open commands 'filename returned in string subfilename 'max filename length = 12 chars, terminate by CR 'any extra chars sent by HP are ignored 'note - does a flag to get each byte, does not 'flag the last byte - driver code must do that Sub GetFilenameFromHP 'mod 0.41 gfncount = 0 'length subfilename(0) = 0 'start empty gfnloop: ClockMainFlag WaitForMainCommand ReceiveMainByte gfnbyte If gfncount < 12 And gfnbyte <> 13 Then gfncount = gfncount + 1 subfilename(gfncount) = gfnbyte subfilename(0) = gfncount End If If gfnbyte <> 13 Then Goto gfnloop End Sub 'fills read buffer with bytes from an open read file 'readfilename = file to read from 'readfileptr0-3 = offset to read from 'if error occurs during read then sets globalerror to an error code, 'clears filename, clears readfileopenflag and sets endoffileflag 'if globalerror set from something else preserve unless new error Sub FillReadBuffer 'mod 0.4 #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " FillReadBuffer " : Wait 100 ms #endif If readfileopenflag Then If Not endoffileflag Then 'assume readfilename is valid but possible user removed disk etc SelectSCS VDsendWait 0x0E,nullvar 'OPR open for read VDsendWait 32,nullvar buffer = readfilename VDsendString 'send filename VDsendWait 13,nullvar VDreceiveWait bytefromVD1,VDerror 'wait for file access VDreceiveWait bytefromVD2,nullvar If VDerror <> 0 Then bytefromVD2 = 0 'timeout, force other error If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then 'some error occurred globalerror = error_other If bytefromVD1 = 78 And bytefromVD2 = 68 Then globalerror = error_nodisk If bytefromVD1 = 67 And bytefromVD2 = 70 Then globalerror = error_commandfailed If bytefromVD1 = 79 And bytefromVD2 = 70 Then globalerror = error_fileopen If bytefromVD1 = 70 And bytefromVD2 = 78 Then globalerror = error_invalidfilename Set readfileopenflag 0 'invalidate read file Else 'file opened successfully, fill buffer from current file position VDsendWait 0x28,nullvar 'SEK seek to location VDsendWait 32,nullvar VDsendWait readfileptr3,nullvar VDsendWait readfileptr2,nullvar VDsendWait readfileptr1,nullvar VDsendWait readfileptr0,nullvar VDsendWait 13,nullvar VDreceiveWait bytefromVD1,VDerror VDreceiveWait bytefromVD2,nullvar If VDerror <> 0 Then bytefromVD1 = 0 If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then 'seek error globalerror = error_other Set readfileopenflag 0 'but still need to close the file Else VDsendWait 0x0B,nullvar 'RDF read from file VDsendWait 32,nullvar VDsendWait 0,nullvar 'msb VDsendWait 0,nullvar VDsendWait readbuffersizehigh,nullvar VDsendWait readbuffersizelow,nullvar VDsendWait 13,VDerror readbufferptr = [word]0 bufferaddress = readbufferptr + [word]readbufferstart readbufferloop: If VDerror = 0 Then 'if it goes down don't take forever VDreceiveWait bytefromVD,VDerror MyPoke bufferaddress, bytefromVD End If readbufferptr = readbufferptr + [word]1 bufferaddress = bufferaddress + [word]1 If readbufferptr <> [word]readbuffersize Then Goto readbufferloop 'buffer filled, set buffer pointer to 0, ready to read readbufferptr = [word]0 'make sure nothing went wrong (enabled 0.4) VDreceiveWait bytefromVD1,nullvar VDreceiveWait bytefromVD2,nullvar If VDerror <> 0 Then bytefromVD1 = 0 If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then 'not >[cr] If bytefromVD1 <> 67 Or bytefromVD2 <> 70 Then 'and not CF (eof) globalerror = error_other 'something unusual happened Set readfileopenflag 0 End If End If End If VDclear 'clear buffer of errors etc VDsendWait 0x0A,nullvar 'CLF close file VDsendWait 32,nullvar buffer = readfilename VDsendString VDsendWait 13,nullvar VDreceiveWait bytefromVD,VDerror If VDerror <> 0 Then bytefromVD = 0 If bytefromVD <> 62 Then globalerror = error_other Set readfileopenflag 0 End If End If VDclear 'clear any remaining responses If Not readfileopenflag Then 'some error occured readfilename(0) = 0 'invalidate current file Set endoffileflag 1 'set EOF flag End If End If End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " FillReadBuffer end, globalerror = " Wait 100 ms : HSerPrint globalerror : HSerSend 32 : Wait 100 ms #endif End Sub 'flushes write buffer to open write file 'does nothing if no write file is open or nothing to write 'writefilename = file to append to 'writebufferptr = how many bytes to write, zeros after flush 'if error occurs during write then invalidate writefilename, 'clear writefileopenflag and sets globalerror to an error code Sub FlushWriteBuffer #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " FlushWriteBuffer " : Wait 100 ms #endif If writefileopenflag Then If writebufferptr > 0 Then SelectSCS VDsendWait 0x09,nullvar VDsendWait 32,nullvar buffer = writefilename VDsendString VDsendWait 13,nullvar VDreceiveWait bytefromVD1,VDerror VDreceiveWait bytefromVD2,nullvar If VDerror <> 0 Then bytefromVD2 = 0 'timeout, force other error If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then 'some error occurred globalerror = error_other If bytefromVD1 = 78 And bytefromVD2 = 68 Then globalerror = error_nodisk If bytefromVD1 = 67 And bytefromVD2 = 70 Then globalerror = error_commandfailed If bytefromVD1 = 79 And bytefromVD2 = 70 Then globalerror = error_fileopen If bytefromVD1 = 70 And bytefromVD2 = 78 Then globalerror = error_invalidfilename If bytefromVD1 = 68 And bytefromVD2 = 70 Then globalerror = error_diskfull Set writefileopenflag 0 'invalidate write file Else VDsendWait 0x08,nullvar 'WRF write to file VDsendWait 32,nullvar VDsendWait 0,nullvar VDsendWait 0,nullvar VDsendWait writebufferptr_h,nullvar fwbtemp = [byte]writebufferptr VDsendWait fwbtemp,nullvar VDsendWait 13,VDerror fwbpointer = [word]0 fwbsendloop: If VDerror = 0 Then bufferaddress = fwbpointer + [word]writebufferstart MyPeek bufferaddress, fwbbyte VDsendWait fwbbyte,VDerror End If fwbpointer = fwbpointer + [word]1 If fwbpointer <> writebufferptr Then Goto fwbsendloop 'buffer flushed, reset pointer writebufferptr = [word]0 'make sure it went ok VDreceiveWait bytefromVD1,nullvar VDreceiveWait bytefromVD2,nullvar If VDerror <> 0 Then bytefromVD1 = 0 If bytefromVD1 <> 62 Or bytefromVD2 <> 13 Then globalerror = error_other Set writefileopenflag 0 End If VDclear 'clear buffer of errors etc VDsendWait 0x0A,nullvar 'CLF close file VDsendWait 32,nullvar buffer = writefilename VDsendString VDsendWait 13,nullvar VDreceiveWait bytefromVD,VDerror If VDerror <> 0 Then bytefromVD = 0 If bytefromVD <> 62 Then globalerror = error_other Set writefileopenflag 0 End If End If VDClear If Not writefileopenflag Then writefilename(0) = 0 End If End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " FlushWriteBuffer end, globalerror = " Wait 100 ms : HSerPrint globalerror : HSerSend 32 : Wait 100 ms #endif End Sub 'check file using DIR command 'subfilename = filename to check 'globalerror set to error code if file doesn't exist or other error 'if no error occurs existing value preserved 'terminates with next 4 bytes = filesize to check for directory 'and save when opening read files Sub CheckFileWithDir SelectSCS 'sync and select short command set VDsendWait 0x01,nullvar 'dir command VDsendWait 32,nullvar buffer = subfilename VDsendString VDsendWait 13,nullvar VDreceiveWait bytefromVD,nullvar If bytefromVD <> 13 Then If bytefromVD = 78 Then globalerror = error_nodisk Else globalerror = error_other End If Else bytefromVD1 = 0 bytefromVD2 = 0 orffindspace: bytefromVD1 = bytefromVD2 bytefromVD2 = bytefromVD VDreceiveWait bytefromVD,nullvar If bytefromVD <> 32 And bytefromVD <> 13 Then Goto orffindspace If bytefromVD = 13 Then 'an error occured globalerror = error_other If bytefromVD1 = 67 And bytefromVD2 = 70 Then globalerror = error_commandfailed If bytefromVD1 = 70 And bytefromVD2 = 79 Then globalerror = error_fileopen If bytefromVD1 = 70 And bytefromVD2 = 78 Then globalerror = error_invalidfilename End If End If End Sub 'open a file on the VDRIVE for reading 'readfilename = filename to open 'if filename is empty then clears readfileopenflag, sets endoffileflag 'if open is successful sets readfileopenflag, clears endoffileflag, 'zeros globalerror and fills read buffer with the first part of the file 'if not successful clears readfileopenflag, sets endoffileflag, 'clears readfilename, and sets globalerror to an error code Sub OpenReadFile #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " OpenReadFile " : Wait 100 ms #endif globalerror = 0 Set readfileopenflag 0 Set endoffileflag 1 If readfilename(0) <> 0 Then 'if file specified subfilename = readfilename CheckFileWithDir If globalerror = 0 Then 'something was found, next 4 bytes = filesize VDreceiveWait readfilesize0,nullvar VDreceiveWait readfilesize1,nullvar VDreceiveWait readfilesize2,nullvar VDreceiveWait readfilesize3,nullvar VDreceiveWait bytefromVD,nullvar If bytefromVD <> 13 Then globalerror = error_other Else DetectZeroSize If readfilezeroflag Then globalerror = error_zerosize Else readfileptr0 = 0 'start at offset zero readfileptr1 = 0 readfileptr2 = 0 readfileptr3 = 0 Set readfileopenflag 1 Set endoffileflag 0 FillReadBuffer 'open file, fill buffer then close file End If End If End If If globalerror <> 0 Then readfilename(0) = 0 'clear filename as no file was opened Set readfileopenflag 0 Set endoffileflag 1 End If VDclear 'clear any remaining responses End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint "OpenReadFile end, globalerror = " Wait 100 ms : HSerPrint globalerror : HSerSend 32 : Wait 100 ms #endif End Sub 'open a file on the VDRIVE for writing 'writefilename = filename to open 'if filename is empty then abandons, clears writefileopenflag 'if open is successful sets writefileopenflag, zeros gobalerror, 'and sets up empty write buffer (note - appends if file exists) 'if not successful clears writefileopenflag, clears writefilename 'and sets globalerror to an error code Sub OpenWriteFile #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " OpenWriteFile " : Wait 100 ms #endif globalerror = 0 Set writefileopenflag 0 If writefilename(0) <> 0 Then subfilename = writefilename CheckFileWithDir 'if command failed error then not an error, just means doesn't exist If globalerror = error_commandfailed Then globalerror = 0 VDclear 'clear response from VDRIVE If globalerror <> 0 Then writefilename(0) = 0 'invalidate filename if actual error Else Set writefileopenflag 1 'open succeeded writebufferptr = [word]0 'initialize write buffer 'nothing actually written to the file until byte(s) written 'and FlushWriteBuffer called End If End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " OpenWriteFile end, globalerror = " Wait 100 ms : HSerPrint globalerror : HSerSend 32 : Wait 100 ms #endif End Sub 'close an open write file 'if a file is open then write remaining bytes in buffer if any, 'clear writefileopenflag and empty writefilename Sub CloseWriteFile #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " CloseWriteFile " : Wait 100 ms #endif globalerror = 0 If writefileopenflag Then FlushWriteBuffer Set writefileopenflag 0 writefilename(0) = 0 End If #ifdef DEBUGMSG 1 Wait 100 ms : HSerPrint " CloseWriteFile end, globalerror = " Wait 100 ms : HSerPrint globalerror : HSerSend 32 : Wait 100 ms #endif End Sub Sub GetNextReadByte(bufferbyte) bufferbyte = 0 'return zero if eof or file not open If readfileopenflag Then If Not endoffileflag Then bufferaddress = readbufferptr + [word]readbufferstart MyPeek bufferaddress,bufferbyte readbufferptr = readbufferptr + [word]1 IncrementReadFilePointer 'sends endoffileflag if at end If endoffileflag Then globalerror = error_eof Else If readbufferptr = [word]readbuffersize Then FillReadBuffer End If End If Else globalerror = error_inputnotopen End If End Sub Sub StoreNextWriteByte(bufferbyte) If writefileopenflag Then bufferaddress = writebufferptr + [word]writebufferstart MyPoke bufferaddress,bufferbyte writebufferptr = writebufferptr + [word]1 If writebufferptr = [word]writebuffersize Then FlushWriteBuffer Else globalerror = error_outputnotopen End If End Sub '-------- disk command targets ----------------------- 'all flag generation is done by these or the subs they call 'so after returning can wait for the next command high '(if not already high and the HP is waiting for service) 'Command received from HP in HPin word 'read a byte from the VDRIVE Sub DC_readVD VDreceive DCtempbyte,subtemp HPout = 0 If subtemp <> 0 Then HPout_h = 128 Else HPout = [byte]DCtempbyte End If SendMainWord HPout ClockMainFlag End Sub 'write a byte to the VDRIVE 'byte to write in low byte of HPin Sub DC_writeVD DCtempbyte = [byte]HPin VDsendWait DCtempbyte,nullvar ClockMainFlag End Sub Sub DC_syncVD VDsync ClockMainFlag End Sub Sub DC_clearVD 'mod 0.41 slow down for VDOS DCclearloop: VDclear Wait CLEAR_VDOS ms VDreceive nullvar, subtemp If subtemp = 0 Then Goto DCclearloop ClockMainFlag End Sub Sub DC_openreadfile 'mod 0.4 GetFilenameFromHP ClockMainFlag readfilename = subfilename OpenReadFile End Sub Sub DC_readfromfile GetNextReadByte DCtempbyte HPout_h = 0 HPout = [byte]DCtempbyte SendMainWord HPout ClockMainFlag End Sub Sub DC_readasPTR Set PTRmodeflag 1 PTRignorecommand = HPin_h ClockMainFlag End Sub Sub DC_openwritefile 'mod 0.4 GetFilenameFromHP ClockMainFlag writefilename = subfilename OpenWriteFile End Sub Sub DC_writetofile 'mod 0.4 DCtempbyte = [byte]HPin ClockMainFlag StoreNextWriteByte DCtempbyte End Sub Sub DC_closefile 'mod 0.4 ClockMainFlag CloseWriteFile End Sub Sub DC_geterror HPout_h = 0 HPout = [byte]globalerror SendMainWord HPout ClockMainFlag End Sub Sub DC_PTread GetNextReadByte DCtempbyte HPout_h = 0 HPout = [byte]DCtempbyte SendMainWord HPout ClockMainFlag End Sub 'received a punch command line Sub DC_punchwrite 'mod 0.4 ReceivePunchByte DCtempbyte ClockPunchFlag HPin = [byte]DCtempbyte 'so data will show on LED's HPin_h = command_writetofile StoreNextWriteByte DCtempbyte End Sub '-------- Serial debug / menu stuff ------------------ Sub docrlf HSerSend 13 HSerSend 10 End Sub Sub VDprompt 'mod 0.4 'right after prompt interprets special chars... '1 - continue with raw data '27 - exit prompt '253 - wait for more data '254 - enter raw mode - no prompts or line end conversion '255 - restore normal mode - prompts, converts line ends Dim ecsinitialized as bit Dim rawcharmode as bit Dim charafterprompt as bit Set rawcharmode 0 Wait 100 ms 'delay to stabilize, esp at 32mhz (actually 25ms) docrlf 'make sure synced with terminal Wait 100 ms 'probably don't need this one HSerPrint "VDRIVE prompt - " HSerPrint "send Esc at prompt to exit" : docrlf HSerPrint "Useful commands: FWV, DIR, RD file, " HSerPrint "DLF file, MKD dir, DLD dir, CD dir|..|/" : docrlf Set ecsinitialized 0 'let it print stuff before initializing '--- print loop ------------- printVDentry: set temp = 0 printVDloop: lasttemp = temp VDreceive temp, busy printVDmore: If busy = 0 Then If Not rawcharmode Then If temp <> 10 Then HSerSend temp If temp = 13 Then HSerSend 10 If temp = 10 And lasttemp <> 13 Then HSerSend 13:HSerSend 10 'for unix files Else 'in raw mode HSerSend temp 'send back raw output End If Goto printVDloop Else 'check to make sure just isn't taking awhile 'in raw mode want to also ignore pauses as much as possible 'since there's no way to force a response wait... also need to define 'a after-prompt command to return to waiting if more data expected '(raw mode is untested, just want to give it at least a chance of working) readytimeout = 100 If Not ecsinitialized Then readytimeout = 10 checkformoreoutput: #ifdef QUADCLOCK 1 Wait 20 ms #endif #ifdef QUADCLOCK 0 Wait 5 ms #endif VDreceive temp, busy If busy = 0 Then Goto printVDmore readytimeout = readytimeout - 1 If readytimeout <> 0 Then Goto checkformoreoutput If Not ecsinitialized Then VDsync VDerrorTrap buffer = "ECS": VDsendString: VDsendWait 13,nullvar: VDclear buffer = "IPA": VDsendString: VDsendWait 13,nullvar Set ecsinitialized 1 Goto printVDloop 'print more stuff (the prompt) End If End If HSerPrint "[ready]" docrlf '--- input loop ------------- Set charafterprompt 1 getserialcharloop: HSerReceive temp If Not rawcharmode Then If temp = 10 Then Goto getserialcharloop 'ignore line feeds End If If charafterprompt Then Set charafterprompt 0 If temp = 1 Then Goto getserialcharloop If temp = 27 Then Goto exitprompt If temp = 253 Then Goto printVDentry If temp = 254 Then Set rawcharmode 1 : Goto getserialcharloop If temp = 255 Then Set rawcharmode 0 : Goto getserialcharloop End If busy = 0 If Not rawcharmode Then HSerSend temp VDsend temp, busy If temp = 13 Then HSerSend 10 If busy = 0 Then Goto printVDentry End If Else VDsendWait temp, busy If busy = 0 Then HSerSend temp If temp = 13 Then Goto printVDentry 'print if any output End If End If If busy <> 0 Then HSerPrint "[busy]":docrlf:Goto printVDentry Goto getserialcharloop exitprompt: End Sub Sub SerialDebug Wait 100 ms Set LED0 1 docrlf HSerPrint "Debug menu" : docrlf HSerPrint "==========" : docrlf displayportdata: docrlf HSerPrint "Main polarity: " If mainpolarity = 0 Then HSerPrint "normal " Else HSerPrint "inverted " End If HSerPrint "Punch polarity: " If punchpolarity = 0 Then HSerPrint "normal " Else HSerPrint "inverted " End If docrlf HSerPrint "Main control: " temp = commandflagsetup And b'00000011' If temp = 0 Then HSerPrint "same polarity " Else If temp = 1 Then HSerPrint "command flipped " Else If temp = 2 Then HSerPrint "flag flipped " Else HSerPrint "cmd/flag flipped " End If End If End If HSerPrint "Punch control: " temp = commandflagsetup And b'00001100' If temp = 0 Then HSerPrint "same polarity " Else If temp = 4 Then HSerPrint "command flipped " Else If temp = 8 Then HSerPrint "flag flipped " Else HSerPrint "cmd/flag flipped " End If End If End If docrlf HSerPrint "Main command: " GetMainCommandState If gotmaincommand Then HSerPrint "asserted " Else HSerPrint "clear " End If HSerPrint "Punch command: " GetPunchCommandState If gotpunchcommand Then HSerPrint "asserted " Else HSerPrint "clear " End If docrlf HSerPrint "Main data in: " ReceiveMainWord tempword PrintBits tempword_h gptemp = [byte]tempword PrintBits gptemp HSerPrint " Punch data in: " ReceivePunchByte gptemp PrintBits gptemp debugmenu: docrlf HSerPrint "A) VDRIVE prompt" : docrlf HSerPrint "B) Clock and redisplay" : docrlf HSerPrint "C) Flip main polarity" : docrlf HSerPrint "D) Flip punch polarity" : docrlf HSerPrint "E) Save polarity setup" : docrlf HSerPrint "F) Set main port output" : docrlf HSerPrint "G) Set data LEDs" : docrlf HSerPrint "H) Change main control setup" : docrlf HSerPrint "I) Change punch control setup" : docrlf HSerPrint "Esc) resume startup" : docrlf HSerPrint "Select:" getdebugselection: GetSelection If selection = 65 Then ShowSel:VDprompt:Goto debugmenu If selection = 66 Then ShowSel ClockMainFlag ClockPunchFlag Goto displayportdata End If If selection = 67 Then ShowSel If mainpolarity = 0 Then mainpolarity = 1 Else mainpolarity = 0 End If Goto displayportdata End If If selection = 68 Then ShowSel If punchpolarity = 0 Then punchpolarity = 1 Else punchpolarity = 0 End If Goto displayportdata End If If selection = 69 Then ShowSel HSerPrint "Saving setup" : docrlf EPwrite 0, mainpolarity EPwrite 1, punchpolarity EPwrite 4, commandflagsetup Goto debugmenu End If If selection = 70 Then ShowSel HSerPrint "Type main output bits(16): " Get8Bits gptemp1 Get8Bits gptemp2 tempword = [byte]gptemp2 tempword_h = gptemp1 SendMainWord tempword docrlf Goto debugmenu End If If selection = 71 Then ShowSel HSerPrint "Type LED bits(8): " Get8Bits gptemp WriteLEDbyte gptemp docrlf Goto debugmenu End If If selection = 72 Then temp = commandflagsetup And b'00000011' temp = temp + 1 temp = temp And b'00000011' commandflagsetup = commandflagsetup And b'00001100' commandflagsetup = commandflagsetup Or temp Goto displayportdata End If If selection = 73 Then temp = commandflagsetup And b'00001100' temp = temp + 4 temp = temp And b'00001100' commandflagsetup = commandflagsetup And b'00000011' commandflagsetup = commandflagsetup Or temp Goto displayportdata End If If selection <> 27 Then Goto getdebugselection Set LED0 0 End Sub Sub GetSelection HSerReceive selection If selection > 96 And selection < 123 Then selection = selection - 32 'uc End Sub Sub ShowSel HSerSend selection docrlf End Sub Sub PrintBits(tempbits) For tempcount = 0 To 7 If tempbits.7 Then HSerSend 49 Else HSerSend 48 End If Rotate tempbits Left Next tempcount End Sub Sub Get8Bits(tempbits) tempbits = 0 For tempcount = 0 To 7 getserialbit: HSerReceive tempchar If tempchar <> 48 And tempchar <> 49 Then Goto getserialbit HSerSend tempchar Rotate tempbits Left If tempchar = 49 Then Set tempbits.0 1 Else Set tempbits.0 0 End If Next tempcount End Sub Sub SerialMenu 'mod 0.4 #ifdef QUADCLOCK 1 Set PLLEN on #endif FlushWriteBuffer 'in case unwritten data Wait 100 ms Set LED0 1 docrlf HSerPrint "Serial file menu" : docrlf HSerPrint "================" : docrlf printattachments: docrlf UpdateStatusLeds HSerPrint "Read file: " If readfilename(0) <> 0 Then HSerPrint readfilename Else HSerPrint "[not open]" End If docrlf HSerPrint "Write file: " If writefilename(0) <> 0 Then HSerPrint writefilename Else HSerPrint "[not open]" End If docrlf HSerPrint "Global error: " HSerPrint globalerror docrlf HSerPrint "A) VDRIVE prompt" : docrlf HSerPrint "B) Open read file" : docrlf HSerPrint "C) Open write file" : docrlf HSerPrint "D) Close write file" : docrlf HSerPrint "E) Clear globalerror" : docrlf HSerPrint "Esc) Resume operation" : docrlf HSerPrint "Select: " getserialmenuselection: GetSelection If selection = 65 Then ShowSel:VDprompt:Goto printattachments If selection = 69 Then ShowSel:globalerror = 0:Goto printattachments If selection = 68 Then ShowSel:CloseWriteFile:Goto printattachments If selection = 66 Then ShowSel HSerPrint "Enter read filename: " GetSubFilename 'gets a filename into subfilename (last char in fchar) If fchar = 27 Then Goto printattachments '(escape pressed) readfilename = subfilename OpenReadFile EngagePTRmode If PTRmodeflag Then HSerPrint "(will read in PTR mode, ignoring high byte " HSerPrint PTRignorecommand HSerPrint ")" : docrlf End If Goto printattachments End If If selection = 67 Then ShowSel HSerPrint "Enter write filename: " GetSubFilename If fchar = 27 Then Goto printattachments globalerror = 0 writefilename = subfilename If subfilename(0) <> 0 Then CheckFileWithDir 'does a DIR on subfilename to see if it exists VDclear 'clear response If globalerror = 0 Then 'file exists, prompt to overwrite HSerPrint "File " HSerPrint writefilename HSerPrint " exists, overwrite? (Y/N) " serialwriteconfirm: GetSelection If selection <> 89 And selection <> 78 Then Goto serialwriteconfirm ShowSel If selection = 89 Then HSerPrint "Deleting file... " DeleteFile 'filename in subfilename If globalerror <> 0 Then HSerPrint "an error occured" : docrlf Goto printattachments Else HSerPrint "done" : docrlf End If Else HSerPrint "New data will append to file" : docrlf End If End If End If OpenWriteFile Goto printattachments End If If selection <> 27 Then Goto getserialmenuselection Set LED0 0 End Sub Sub GetSubFilename charcount = 0 subfilename(0) = 0 getsubfilenameloop: HSerReceive fchar If fchar = 27 Then subfilename(0) = 0 : Goto exitgetsubfilename If fchar = 13 Then Goto exitgetsubfilename charcount = charcount + 1 If charcount > 12 Then HSerPrint " too long, rejected" fchar = 27 subfilename(0) = 0 Goto exitgetsubfilename End If HSerSend fchar subfilename(0) = charcount subfilename(charcount) = fchar Goto getsubfilenameloop exitgetsubfilename: docrlf End Sub 'end of HPUSB firmware