QBasic/QuickBASIC Program Downloader
================================================================
' Author: Jorge Codina 12 November 1994
'
' heroload.bas
' Qbasic program to transfer a machine lang file to the HERO via the
' PC's Printer Port and the HERO's Expansion Board
'
' The Cable is a standard PC Printer Coble with the 36 Pin Centronics
' Connector removed.
' The wiring is as follows:
' 25 Pin D-Shell Hero Expansion Board
' 2 DI0
' 3 DI1
' 4 DI2
' 5 DI3
' 6 DI4
' 7 DI5
' 8 DI6
' 9 DI7
' 17 INT
' 18-25 GND
'
' To run this program:
' 1) enter the program "hcode7.txt" into the HERO via the HEX
' Keypad or cassette
' 2) Attach the cable to a printer port and the HERO, Change the
' DataPort address below if necessary
' 3) Start the HERO load program by entering AD 00 60 on the HEX
' Keypad
' 4) execute Qbasic /RUN heroload
' 5) Enter the filename to load
' 6) When done the HERO will return to the Executive and say "READY"
'
' The program writes a file to the HERO in a predefine format
' All Address and Data bytes are represented by 2 hex characters
' first two bytes are the starting program address
' the last two byte are "S9"
' eventually this program and the HERO load code will be re-written
' to accept true S-Record format
'
' After each byte is written on the DataPort
' control pin three (D25 pin 17) is set LOW
' to signal an interupt to on the HERO
'
' StatusPort is not used in this program
'
' DataPort = &H3BD First Printer Port, Mono adaper card, not present
' DataPort = &H378 Second Printer Port, LPT1 on my system
CONST DataPort = &H278 'Thrid Printer Port, LPT2 on my system
CONST StatusPort = DataPort + 1
CONST ControlPort = DataPort + 2
CONST TRUE = 1
CONST FALSE = 0
CONST IntOff = &H0
CONST IntOn = &HFF
DIM WorkByte AS STRING * 1
DIM ByteNo AS INTEGER
DIM ProcessCount AS INTEGER
DIM SkipFlag AS INTEGER
OUT ControlPort, IntOff 'set interupt high
INPUT "Enter file to send to HERO: ", HeroProgram$
IF HeroProgram$ = "" THEN END
OPEN HeroProgram$ FOR RANDOM AS #1 LEN = 1
ByteNo = 0
ProcessCount = 0
'
'Main Loop
'
DO
SkipFlag = FALSE
ByteNo = ByteNo + 1
ProcessCount = ProcessCount + 1
GET #1, ByteNo, WorkByte
'
' Skip Comments
'
IF (ASC(WorkByte)) = 59 THEN 'it is a semi-colon ;
GOSUB SkipCommentLine
END IF
'
' Check for "S" (record header)
'
IF (ASC(WorkByte)) = 83 THEN 'it is an "S"
GOSUB HeaderProcess
END IF
'
' skip anything not between 0-9 and A-F
'
WByte = ASC(WorkByte)
IF WByte < 48 OR WByte > 70 THEN
SkipFlag = TRUE
ProcessCount = ProcessCount - 1
END IF
IF WByte > 57 AND WByte < 65 THEN
SkipFlag = TRUE
ProcessCount = ProcessCount - 1
END IF
'
IF SkipFlag = FALSE THEN
IF (ProcessCount MOD 2) = 0 THEN
SecondByte$ = WorkByte
GOSUB SetHex
ELSE
FirstByte$ = WorkByte
END IF
END IF
LOOP UNTIL (EOF(1))
END
'
' SkipCommentLine
'
' Skip over the rest of the line
' Returns when it hits a Line Feed (Ascii 10)
' Line feed is the character left in WorkByte
'
SkipCommentLine:
DO
ByteNo = ByteNo + 1
GET #1, ByteNo, WorkByte
LOOP UNTIL (ASC(WorkByte)) = 10
RETURN
'
' SetHex
'
' FirstByte$ and SecondByte$ both contain ascii characters between 0-9
' or A-F. FirstByte is HighOrder and must be multiplied by 10h.
' SecondByte is LowOrder. Together they make up one byte to be sent
' to the HERO.
'
SetHex:
SELECT CASE SecondByte$
CASE "0"
SecondByte = &H0
CASE "1"
SecondByte = &H1
CASE "2"
SecondByte = &H2
CASE "3"
SecondByte = &H3
CASE "4"
SecondByte = &H4
CASE "5"
SecondByte = &H5
CASE "6"
SecondByte = &H6
CASE "7"
SecondByte = &H7
CASE "8"
SecondByte = &H8
CASE "9"
SecondByte = &H9
CASE "A"
SecondByte = &HA
CASE "B"
SecondByte = &HB
CASE "C"
SecondByte = &HC
CASE "D"
SecondByte = &HD
CASE "E"
SecondByte = &HE
CASE "F"
SecondByte = &HF
END SELECT
SELECT CASE FirstByte$
CASE "0"
FirstByte = &H0
CASE "1"
FirstByte = &H10
CASE "2"
FirstByte = &H20
CASE "3"
FirstByte = &H30
CASE "4"
FirstByte = &H40
CASE "5"
FirstByte = &H50
CASE "6"
FirstByte = &H60
CASE "7"
FirstByte = &H70
CASE "8"
FirstByte = &H80
CASE "9"
FirstByte = &H90
CASE "A"
FirstByte = &HA0
CASE "B"
FirstByte = &HB0
CASE "C"
FirstByte = &HC0
CASE "D"
FirstByte = &HD0
CASE "E"
FirstByte = &HE0
CASE "F"
FirstByte = &HF0
END SELECT
HexByte = FirstByte + SecondByte
GOSUB WriteOut
RETURN
'
' HeaderProcess
'
' Process S0, S1 and S9 records eventually
' right now just translate the bytes to Hex
'
HeaderProcess:
HexByte = &H53
GOSUB WriteOut
ByteNo = ByteNo + 1
GET #1, ByteNo, WorkByte
WByte$ = WorkByte
SELECT CASE WByte$
CASE "0"
HexByte = &H30
CASE "1"
HexByte = &H31
CASE "9"
HexByte = &H39
END SELECT
GOSUB WriteOut
ByteNo = ByteNo + 1
GET #1, ByteNo, WorkByte
RETURN
'
' WriteOut
'
' Write Byte to DataPort and set the Interupt on the Hero by
' writing FF to the ControlPort
'
WriteOut:
OUT DataPort, HexByte
OUT ControlPort, IntOn 'Write FFh to control forcing pin 3 LOW
OUT ControlPort, IntOff 'set interupt high
RETURN