# include constant definition if not defined ifnotdef (PP) include/ prmdef.rat endifdef ################################################################################ # This module contains several higher level subroutines that combine and #augment some of the simpler instructions inherent to the prom programmer. # # byte function memchk(count,data,sum) # subroutine cmpram(begin,offset,count,data,lunout,ists) # integer function lodmem(left,right,coment,lunin,count,data) # subroutine lstmem(begin,count,data,lunout,ists) # ################################################################################ # byte function memchk(count,data,sum) # ################################################################################ # This function calculates the checksum of the data array DATA. DATA is a #random length string of ascii hex bytes. It stores data from COUNT memory #locations, where count is an ASCII hex number. This routine returns the hex #checksum in SUM which is a 4 byte array. If the function cannot convert COUNT #or any of the data in the DATA array to binary integer form, it will return #false. If no errors occur, the function will return true. ################################################################################ byte count(4), data(ARB), temp(3), sum(4) # byte hexbin # # temp(3)=EOS # isum=0 # holds current sum if (~hexbin(count,icnt)) # convert hex to integer return(.false.) # error if cannot lim=icnt*2 # for (I=1; I<=lim; I=I+2) { # loop over number of data bytes temp(1)=data(I) # temp(2)=data(I+1) # if (~hexbin(temp,ival)) # convert data to binary integer return(.false.) # error isum=isum+ival # add current value to sum } # call binhex(isum,sum) # convert sum back to hex # return(.true.) # end # # subroutine cmpram(begin,offset,count,data,lunout,ists) # ################################################################################ # This function uses a space efficient algorithm to compare COUNT #number of PP RAM bytes starting at address BEGIN with the data stored in #the array DATA(1), DATA(2), DATA(3), etc. Two parameters are used to specify #the address relative to the start of the PROM versus the address relative to #the start of MEMORY WHERE THE PROM IS LOCATED. The routine assumes that BEGIN #is a relative address, and the absolute PROM address is calculated # by: BEGIN-OFFSET. DATA must contain the equivalent of COUNT number of bytes #of ascii hex data. Since in ascii code, each nibble of binary memory is #represented as two ascii bytes, COUNT*2=length(DATA). # # Then causes the PP to output the contents of RAM (not PROM) and #the function compares the data with the ascii hex data passed in the #byte vector DATA. The function returns status in the integer status #parameter ISTS. ISTS can return SUCCES, FAIL, HEXERR, PPERR or RCVERR. # # This routine alters the block limits: BEGDEV, BEGRAM and COUNT. #On completion, both BEGDEV and BEGRAM are reset to 0, and COUNT is set #to the value passed in COUNT. # # The routine detects any errors and writes the errors to logical unit #LUNOUT if there are any. Also, if there are any errors, the function returns #false, else the function returns true. ################################################################################ integer prmpnt, prmcnt, curin # byte hexbin, begin(4), count(4), data(arb) # byte adrs(4), cnt(4), compar, offset(4) # byte hexadd, hexsub, atemp(6) # include/ prmcom.rat # # call copy(begin,atemp,5) # make temporary copy of begin address # convert relative BEGIN to absolute BEGIN address # convert absolute BEGIN to integer # convert COUNT to integer if (~hexsub(atemp,offset,begin)|~hexbin(begin,prmpnt)|~hexbin(count,prmcnt)) { ists=HEXERR # conversion error return # } # call begram('0000',ists) # reset beginning of RAM to 0 to avoid confusion if (ists~=SUCCES) # errr in reset begin of RAM return # # down to work... iercnt=0 # count # of DATA & PROM discrepancies curin=RAMBUFLEN+1 # pointer overflow forces data read into RAMBUF, # this is a byte pointer for (I=1; I<=prmcnt; I=I+1) { # advances by relative pointer to RAMBUF # 2 bytes in RAMBUF correspond to 1 byte of PROM if (curin>RAMBUFLEN) { # no more data in ram input buffer curin=1 # reset pointer to RAMBUF if (prmcnt-I>=HRAMBUFLEN) # more than one full buffer to read inputl=HRAMBUFLEN # so read entire buffer else # inputl=prmcnt-I+1 # else this many remaining to read and compare call binhex((I-1+prmpnt),adrs) # convert PROM pointer value to HEX call begdev(adrs,ists) # set pointer to start ofdevice call binhex(inputl,cnt) # convert # of bytes to HEX call blksiz(cnt,ists1) # set number of points to load if (ists~=SUCCES|ists1~=SUCCES) # error return # then return call load(ists) # load data points call odata(cnt,rambuf,ists) # read CNT bytes of PP RAM starting at ADRS if (ists~=SUCCES) # error on reading data return # then return } # index=2*I-1 # byte pointer to DATA vector if (~compar(rambuf(curin),data(index),2)) { # data not same!! iercnt=iercnt+1 # bump error count call binhex((I-1+prmpnt),adrs) # RAM address that disagrees if (~hexadd(adrs,offset,atemp)) { # reconvert to relative address ists=HEXERR # error, porbably integer overflow return # } # write(lunout,100) iercnt, (atemp(J),J=1,4), data(index),data(index+1),rambuf(curin),rambuf(curin+1) 100 format(' *error* [',i4,'] addrs: ',4a1,' expected: ',2a1,' actual:',2a1) } # curin=curin+2 # bump pointer to RAMBUF comparison buffer } # # call begdev('0000',ists) # reset begin device to 0 call blksiz(prmcnt,ists1) # reset number of points if (ists~=SUCCES|ists1~=SUCCES) { } # error in reset begin device else # if (iercnt>0) # if memory & PROM not same ists=FAIL # else # ists=SUCCES # # return # end # # subroutine lstmem(begin,count,data,lunout,ists) # ################################################################################ # This subroutine writes the contents of the vector DATA to the logical #unit number LUNOUT. DATA is assumed to store ascii hex data, with the high #order ascii byte in odd numbered locations in the vector. # BEGIN is the address that corresponds to the first byte of memory to be #listed. This address does NOT necessarily have to be relative to the start #of the PROM, instead, it may be with respect to the entire memory. If, for #example a PROM resides in a block of memory starting at F800, then in order #to get an accurate address listing, set BEGIN=F800. COUNT is the number #of bytes to write out. Both COUNT and BEGIN must be in ascii hex format, #4 or less bytes long, and if more than 4, then the string must be terminated #with a null byte. The input vector, DATA must contain 2*COUNT number of ascii #characters, because each memory location is represented as 2 ASCII hex #characters. # The status parameter ISTS will return either SUCCES or HEXERR. # # NOTE!!!! # # This routine does perform 16 bit addition on the variable IBEG. # ################################################################################ byte begin(4), count(4), data(ARB), hexbin # byte adrs(4) # include/ prmcom.rat # # if (~hexbin(begin,ibeg)|~hexbin(count,icnt)) { # convert hex address + count values to binary ists=HEXERR # return # } # # for (I=1; I<=icnt; I=I+ndout) { # output one line of data nadd=I-1 # this avoids some problems with 16 bit math call binhex(ibeg+nadd,adrs) # calculate address of first data byte written # on this line of output if (icnt-I>=NDOUT) # put NDOUT data bytes on each output line lim=NDOUT # more than NDOUT bytes left to write out else # lim=icnt-I+1 # this is only a partial line linpnt=0 # byte pointer to output string to be built for (J=1; J<=lim; J=J+1) { # store bytes in output line buffer K=2*(J+I-1) # this is complex, but gets the job done, if you # need help, ask and i'll explain linbuf(linpnt+1)=data(K-1) # fill output line buffer linbuf(linpnt+2)=data(K) # with hi then lo ascii hex bytes linbuf(linpnt+3)=SPACE # one space between each data byte linpnt=linpnt+3 # bump line buffer pointer } # write(lunout,100) (adrs(K),K=1,4),(linbuf(J),J=1,linpnt) # write the line 100 format(1x,4a1,1x,120a1) # } # ists=SUCCES # return # end # # integer function lodmem(left,right,coment,lunin,count,data) # ################################################################################ # This function reads ASCII hex data (byte pairs) from the input logical #unit number, LUNIN, and loads it into the byte array DATA. # This routine only scans the input record from columns LEFT to RIGHT, #where both are integers. The maximum input record is LINMAX-1 bytes, so to #scan the whole line set LEFT<=1 and RIGHT>=LINMAX. If the comment delimiter #character COMENT is located any wheres on the line, the remainder of that line #is ignored. If there is no command delimiter character, then set COMENT=EOS. # This routine will ignore any spaces or commas in the input line. Further #the routine will correctly handle horizontal tabs. # Any characters other than spaces, tabs, commas or legal hexidecimal #characters inside of columns LEFT and right and not to the right of a comment #delimiter, will cause the routine to return an error. Hex characters may #be in either upper or lower case. # The ascii hex byte string COUNT should indicate the number of data bytes #that are to be read. To read to the end of the file, specify COUNT equal to the #one half the maximum number of ascii bytes that can be stored in the input #DATA vector. This will protect from reading data into memory not allocated to #the input DATA buffer. In this case the routine will only read as many bytes #as there are in the file. On a successful read operation, the value of the #function returns the number of bytes of memory (not ascii characters) that #were read. Again, the number of ascii bytes read equals twice the function #value return. # DATA is the byte array, and it is assumed to be long enough to hold all #of the data read in. # # function value | description # -----------------|--------------------------------- # >=0 | number of bytes of memory read # HEXERR | illegal hexidecimal value # ################################################################################ byte coment, count(4), data(ARB), bite, hexbin # byte lhex # integer left, right, lunin, tabstp # integer column, getl # include/ prmcom.rat # # # if (~hexbin(count,icnt)) # convert hex to binary return(HEXERR) # if (icnt==0) # if don't ask for any return(0) # don't get any nbytes=0 # records # of bytes input so far # repeat { # len=getl(linbuf,LINMAX,lunin) # if (len<0) # end of file return(nbytes) # return no. of bytes read successfully else # if (len==0) # if blank line next # ignore it, get next line column=1 # initialize column pointer # check each byte in input line for (linpnt=1; linpnt<=len&linbuf(linpnt)~=coment; linpnt=linpnt+1) { bite=linbuf(linpnt) # if (bite==TAB) { # byte is a tab, so tab to next tab stop # calculate the column of tab stop for (tabstp=9;column>=tabstp;tabstp=tabstp+8) { } column=tabstp # set column same as next tab stop } # else # if (column>right) # ignore remainder of line break # else # if (column='0'&bite<='9')|(bite>='A'&bite<='F'))# return(.true.) # if (bite>='a'&bite<='f') { # bite=bite+'A'-'a' # offset of upper-lower case return(.true.) # } # return(.false.) # end #