-- BruceToBinary.mesa -- Created by Barth -- Last edited by Barth, December 6, 1981 5:48 PM -- Last edited by Chi Yung, January 5, 1982 2:11 PM -- Last edited by Chi Yung Fu, January 28, 1982 10:27 AM -- Last edited by Chi Yung Fu, March 26, 1982 3:02 PM -- Last edited by Chi Yung Fu, April 30, 1982 2:39 PM -- Last edited by Chi Yung Fu, August 9, 1983 11:21 AM -- Last edited by Chi Yung Fu, September 1, 1983 11:20 AM -- Last edited by J.White, 24-Apr-85 17:58:32 DIRECTORY Ascii, BruceDefs, MachineParseDefs, vmD: FROM "VirtualMgrDefs"; BruceToBinary: PROGRAM IMPORTS MachineParseDefs EXPORTS BruceDefs = BEGIN OPEN MachineParseDefs; MinProfiledTemp:CARDINAL ← 0; MaxProfiledTemp:CARDINAL ← 12000; MaxTempRangeScale:CARDINAL ← 15000; --This change is implemented on July 31, 1982 --This MaxTempRangeScale is for the last column in the coefficient table. --The Max entry there is 14990. MinGasFlowConversion: CARDINAL ← 0; MaxGasFlowConversion: CARDINAL ← 9999; TempScaledFactor: CARDINAL ← 1; GasScaledFactor: CARDINAL ← 2; AsciiToBinary: PUBLIC PROCEDURE [vmp:vmD.VirtualMessagePtr, brp:BruceDefs.RecipePtr]= BEGIN ph:ParseHandle ← @pd; pd:ParseData; fields: ARRAY [0 .. 6) OF FieldRec ← [["Interval"L, ParseInterval], ["AlarmMask/AbortDestination"L, ParseAlarm], ["TemperatureSetpoint"L, ParseTempTable], ["GasSetpoint"L, ParseGasTable], ["BoatSpeed"L, ParseBoatControl], ["Coefficient"L, ParseCoefficient]]; pd.breakSet ← ":."L; pd.blankSet ← " "L; ph.message ← vmp; pd.userData ← brp; ParseMessage[ph, DESCRIPTOR[fields]]; END; -- of AsciiToBinary ParseMult: PROCEDURE[ph:ParseHandle] RETURNS[m:CARDINAL]= BEGIN m ← ParseDecimal[ph]*10; CheckChar[ph, '.]; m ← m + ParseDecimal[ph]; END; -- of ParseMult ParseTemp: PUBLIC PROCEDURE[ph:ParseHandle, MinProfiledTemp:CARDINAL, MaxProfiledTemp:CARDINAL] RETURNS[t,tNumberOfDigits:CARDINAL]= BEGIN [t,tNumberOfDigits] ← ParseScaledNumber[ph, TempScaledFactor, MinProfiledTemp, MaxProfiledTemp]; ParseToNonWhite[ph]; CheckChar[ph, Ascii.ControlD]; ParseToNonWhite[ph]; CheckChar[ph, 'C]; END; -- of ParseTemp ParseGas: PUBLIC PROCEDURE[ph:ParseHandle, MinGasFlowConversion: CARDINAL, MaxGasFlowConversion: CARDINAL] RETURNS[g,gNumberOfDigits:CARDINAL]= BEGIN curPos: vmD.CharIndex; curPos ← ph.currentChar; [g,gNumberOfDigits] ← ParseScaledNumber[ph, GasScaledFactor, MinGasFlowConversion, MaxGasFlowConversion*50]; ParseToNonWhite[ph]; IF ParseCharIfCharIs[ph, 'L] = FALSE THEN BEGIN IF ParseCharIfCharIs[ph, 'C] = FALSE THEN ERROR ParseFault ["The character here should be either l or cc.", ph.currentChar, ph.currentChar+1] ELSE CheckChar[ph,'C]; THROUGH[1..GasScaledFactor] DO g ← g/10; ENDLOOP; g ← g*2; -- because of the way the Gas flow calibration table is set up END ELSE BEGIN ph.currentChar ← curPos; [g,gNumberOfDigits] ← ParseScaledNumber[ph, GasScaledFactor, MinGasFlowConversion,MaxGasFlowConversion]; ParseToNonWhite[ph]; CheckChar[ph,'L]; END; ParseToNonWhite[ph]; CheckChar[ph, '/]; ParseToNonWhite[ph]; CheckChar[ph, 'M]; END; -- of ParseGas ParseInterval: FieldParseProc= BEGIN i:BruceDefs.IntervalIndex; rp:BruceDefs.RecipePtr ← ph.userData; WHILE ParseToLeadingChar[ph] DO i ← ParseDecimal[ph,0,30]; [rp.interval[i].hours, rp.interval[i].minutes, rp.interval[i].seconds] ← ParseTime[ph]; rp.interval[i].controlAlg ← ParseNibble[ph,0,10]; -- the upper bound value,10, allow us to enter the code a beside 0, 4 and 8. rp.interval[i].tempAlarm ← ParseNibble[ph,10,13]; rp.interval[i].gasTempControl ← rp.interval[i].gasTempControl MOD 10 + 10*ParseDecimal[ph,0,8]; rp.interval[i].gasAlarm ← ParseNibble[ph,10,13]; rp.interval[i].gasTempControl ← (rp.interval[i].gasTempControl/10)*10 + ParseDecimal[ph,0,8]; rp.interval[i].controlCoeff ← ParseNibble[ph,10,13]; rp.interval[i].abortGroup ← ParseNibble[ph,10,13]; FOR j: CARDINAL DECREASING IN [1..8] DO rp.interval[i].function1[j] ← ParseBinary[ph]; ENDLOOP; FOR j: CARDINAL DECREASING IN [1..4] DO rp.interval[i].function2[j] ← ParseBinary[ph]; ENDLOOP; FOR j: CARDINAL DECREASING IN [1..6] DO rp.interval[i].function3[j] ← ParseBinary[ph]; ENDLOOP; ENDLOOP; END; -- of ParseInterval ParseAlarm: FieldParseProc= BEGIN i:BruceDefs.AlarmIndex; rp:BruceDefs.RecipePtr ← ph.userData; WHILE ParseToLeadingChar[ph] DO i ← ParseNibble[ph,10,13,FALSE] - 9; FOR j:CARDINAL DECREASING IN [7..16] DO rp.alarm[i].binaryMask[j] ← ParseBinary[ph]; ENDLOOP; FOR j: CARDINAL DECREASING IN [3..8] DO rp.alarm[i].tempMask[j] ← ParseBinary[ph]; ENDLOOP; FOR j: CARDINAL DECREASING IN [2..8] DO rp.alarm[i].gasMask[j] ← ParseBinary[ph]; ENDLOOP; FOR j: CARDINAL DECREASING IN [6..8] DO rp.alarm[i].softMask[j] ← ParseBinary[ph]; ENDLOOP; rp.alarm[i].destInterval ← ParseDecimal[ph,0,30]; ENDLOOP; END; -- of ParseAlarm ParseTempTable: FieldParseProc= BEGIN i:BruceDefs.TempRowIndex; rp:BruceDefs.RecipePtr ← ph.userData; WHILE ParseToLeadingChar[ph] DO i ← ParseNibble[ph,1,12,FALSE]; IF i>8 THEN BEGIN IF i<10 THEN ParseFault["Illegal temperature row",ph.currentChar-1, ph.currentChar]; rp.abortMultipliers.temp[i - 9] ← ParseScaledNumber[ph, 1, 0, 99].n; -- The scale factor is 1. The lower bound is 0 and upper bound is 9.9. -- [i - 9] because a=10. So when i = a we actually have i = 10 but the -- j in the rp.abortMultipliers.temp[j] can only take on the value 1,2 or -- 3 because of the constraint of the BruceDefs.mesa. Therefore we -- substract 9 to get back to 1, 2, or 3. -- TO DEACTIVATE THE ABORT.MULTIPLIERS, DELETE THE -9 FROM [i - 9 ], THIS -- WILL READ THE NUMBER FROM THE TEMP TABLE BUT DUMP IT AWAY. END; IF i=10 THEN FOR j:BruceDefs.TempColIndex IN BruceDefs.TempColIndex DO rp.alert.temp[j] ← ParseScaledNumber[ph, TempScaledFactor,0, 500].n; -- The lower bound is 0C and upper bound is 50C. -- TO DEACTIVATE THE ALERT ROW ( ROW A ), JUST CHANGE THE FOLLOWING -- STATEMENT FROM i<10 TO i<11 , THIS WILL DUMP THE A ROW AWAY SINCE THE -- rp.temp IS DEFINED FOR ONLY 8 ROWS. ENDLOOP; IF i<10 THEN FOR j:BruceDefs.TempColIndex IN BruceDefs.TempColIndex DO rp.temp[i][j] ← ParseScaledNumber[ph, TempScaledFactor,MinProfiledTemp, MaxProfiledTemp].n; ENDLOOP; ENDLOOP; END; -- of ParseTempTable ParseGasTable: FieldParseProc= BEGIN i:BruceDefs.GasRowIndex; rp:BruceDefs.RecipePtr ← ph.userData; WHILE ParseToLeadingChar[ph] DO i ← ParseNibble[ph,1,12,FALSE]; IF i>8 THEN BEGIN IF i<10 THEN ParseFault["Illegal gas row",ph.currentChar-1, ph.currentChar]; rp.abortMultipliers.gas[i - 9] ← ParseScaledNumber[ph, 1, 0, 99].n; -- The scale factor is 1. The lower bound is 0 and upper bound is 9.9. -- [i - 9] because a=10. So when i = a we actually have i = 10 but the -- j in the rp.abortMultipliers.temp[j] can only take on the value 1,2 or -- 3 because of the constraint of the BruceDefs.mesa. Therefore we -- substract 9 to get back to 1, 2, or 3. END; IF i=10 THEN FOR j:BruceDefs.GasColIndex IN BruceDefs.GasColIndex DO rp.alert.gas[j] ← ParseScaledNumber[ph, GasScaledFactor,0, 500].n; -- The lower bound is 0% and upper bound is 5%. ENDLOOP; IF i<10 THEN FOR j:BruceDefs.GasColIndex IN BruceDefs.GasColIndex DO rp.gas[i][j] ← ParseScaledNumber[ph, GasScaledFactor,MinGasFlowConversion, MaxGasFlowConversion].n; ENDLOOP; ENDLOOP; END; -- of ParseGasTable ParseBoatControl: FieldParseProc= BEGIN ParseSubTable:PROCEDURE[ph:ParseHandle, br: POINTER TO BruceDefs.BoatRows]= BEGIN s:STRING ← [6]; FOR i:BruceDefs.BoatRowIndex IN BruceDefs.BoatRowIndex DO IF ~ParseToLeadingChar[ph] THEN ERROR ParseFault["Data for Boat Speed Missing", ph.currentChar-1, ph.currentChar]; THROUGH [1..IF i=1 THEN 3 ELSE 1] DO ParseWord[ph,s] ENDLOOP; FOR j:BruceDefs.BoatSegmentIndex IN BruceDefs.BoatSegmentIndex DO br[i][j].speed ← ParseDecimal[ph,0,99]; br[i][j].distance ← ParseDecimal[ph,0,99]; ENDLOOP; ENDLOOP; END; -- of ParseSubTable rp:BruceDefs.RecipePtr ← ph.userData; ParseSubTable[ph, @rp.boat.in]; ParseSubTable[ph, @rp.boat.out]; ParseToEndOfField[ph]; END; -- of ParseBoatControl ParseCoefficient: FieldParseProc= BEGIN b,c:CHARACTER; rp:BruceDefs.RecipePtr ← ph.userData; FOR i:BruceDefs.FactorIndex IN BruceDefs.FactorIndex DO IF ~ParseToLeadingChar[ph] THEN ERROR ParseFault["Data for Coefficient Missing", ph.currentChar-1, ph.currentChar]; b ← ParseChar[ph]; IF i # b - '@ THEN SELECT i FROM = 1 => ERROR ParseFault["Row A of Coefficient Table is missing", ph.currentChar - 2, ph.currentChar]; = 2 => ERROR ParseFault["Row B of Coefficient Table is missing", ph.currentChar - 2, ph.currentChar]; = 3 => ERROR ParseFault["Row C of Coefficient Table is missing", ph.currentChar - 2, ph.currentChar]; = 4 => ERROR ParseFault["Row D of Coefficient Table is missing", ph.currentChar - 2, ph.currentChar]; ENDCASE; FOR j:BruceDefs.ZoneIndex IN BruceDefs.ZoneIndex DO IF ~ParseToLeadingChar[ph] THEN ERROR ParseFault ["Part of the Data for the Coefficient Table is missing", ph.currentChar-1, ph.currentChar]; c ← ParseChar[ph]; IF j # c - '0 THEN SELECT j FROM = 1 => ERROR ParseFault["Zone 1 of Coefficient Table is missing", ph.currentChar - 1, ph.currentChar]; = 2 => ERROR ParseFault["Zone 2 of Coefficient Table is missing", ph.currentChar - 1, ph.currentChar]; = 3 => ERROR ParseFault["Zone 3 of Coefficient Table is missing", ph.currentChar - 1, ph.currentChar]; ENDCASE; rp.control.factorArray[i].calibration[j] ← ParseDecimal[ph]; rp.control.factorArray[i].latency[j] ← ParseDecimal[ph]; rp.control.factorArray[i].outerLoopRate[j] ← ParseDecimal[ph]; rp.control.factorArray[i].rate[j] ← ParseDecimal[ph]; rp.control.factorArray[i].reset[j] ← ParseDecimal[ph]; rp.control.factorArray[i].proportionalBand[j] ← ParseDecimal[ph]; IF j=FIRST[BruceDefs.ZoneIndex] THEN rp.tempRange[i] ← ParseScaledNumber[ph, TempScaledFactor, MinProfiledTemp, MaxTempRangeScale].n; ENDLOOP; ENDLOOP; IF ~ParseToLeadingChar[ph] THEN ERROR ParseFault["WierdIndex is missing from the Coefficient Table", ph.currentChar-5, ph.currentChar]; FOR i:BruceDefs.WierdIndex IN BruceDefs.WierdIndex DO rp.control.wierdStuff[i] ← ParseDecimal[ph]; ENDLOOP; ParseToEndOfField[ph]; END; -- of ParseCoefficient END.