bricktools/0000755000175000017500000000000011676036336012624 5ustar slavkoslavkobricktools/uSpirit.pas0000644000175000017500000010152411537752657015002 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uSpirit; interface uses rcx_constants, Classes, FantomDefs; const MAX_COMPORT = 8; MAX_USBPORT = MAX_COMPORT+4; type // TBrickType = rtRCX..rtNXT; TDownloadStatusEvent = procedure(Sender : TObject; cur, total : Integer; var Abort : boolean) of object; TGetVarInfoByIDEvent = procedure(Sender : TObject; const ID : integer; var offset, size, vartype : integer) of object; TGetVarInfoByNameEvent = procedure(Sender : TObject; const name : string; var offset, size, vartype : integer) of object; // TPortNum = 1..MAX_USBPORT; NXTLSBlock = record TXCount : byte; RXCount : byte; Data : array[0..15] of Byte; end; NXTMessage = record Inbox : byte; Size : byte; Data : array[0..58] of Byte; end; NXTDataBuffer = record Data : array[0..kNXT_MaxBytes-1] of Byte; end; TNXTFileType = (nftProgram, nftGraphics, nftSound, nftData, nftOther, nftFirmware); TTransmitLevel = (tlNear, tlFar); TLSSource = (lsVariable, lsError, lsConstant); TThresholdValue = 0..1020; TBlinkTimeValue = 1..32767; TTimerNumber = 0..3; // rcx2 has 4, scout only has 3 TCounterNumber = 0..2; // rcx2 has 3 counters, scout only has 2 TTCSource = (tcVariable, tcError1, tcConstant, tcError2, tcRandom); TScoutMotion = (smNone, smForward, smZigZag, smCircleRight, smCircleLeft, smLoopA, smLoopB, smLoopAB); TScoutTouch = (stIgnore, stReverse, stAvoid, stWaitFor, stBrake); TScoutLight = (slIgnore, slSeekLight, slSeekDark, slAvoid, slWaitFor, slBrake); TScoutScale = (ssShort, ssMedium, ssLong); TScoutEffects = (seNone, seBug, seAlarm, seRandom, seScience); TSoundSetNumber = 0..5; TGlobalOutAction = (goaFloat, goaOff, goaOn); TGlobalDirAction = (gdaBackward, gdaSwitch, gdaForward); TMotorsNum = 1..7; TInstalledFirmware = (ifUnknown, ifStandard, ifEnhanced); EEPROMBlock = record Data : array[0..15] of Byte; end; TBrickComm = class private protected fLocalIFW : TInstalledFirmware; fLocalFV : Word; fOffsetDS : integer; fOffsetDVA : integer; fActive : boolean; fAutoClose: boolean; fBrickType: byte; fBST: Cardinal; fBTName: string; fDataLog: TStrings; fFastMode: boolean; fMemData: TStrings; fMemMap: TStrings; fOnDownloadDone: TNotifyEvent; fOnDownloadStart: TNotifyEvent; fOnDownloadStatus: TDownloadStatusEvent; fOnOpenStateChanged: TNotifyEvent; fOnGetVarInfoByID: TGetVarInfoByIDEvent; fOnGetVarInfoByName: TGetVarInfoByNameEvent; fPort: string; fTowerExistsSleep: Word; fUseBT: boolean; fVerbose: boolean; fMotorPower : array[0..2] of byte; fMotorForward : array[0..2] of boolean; fMotorOn : array[0..2] of boolean; fSensorType : array[0..3] of Byte; fSensorMode : array[0..3] of Byte; function GetBrickTypeName: string; virtual; function GetDownloadWaitTime: Integer; virtual; abstract; function GetEEPROM(addr: Byte): Byte; virtual; abstract; function GetEEPROMBlock(idx: Integer): EEPROMBlock; virtual; abstract; function GetIsOpen: boolean; virtual; function GetLinkLog: string; virtual; abstract; function GetLSBlock(port: byte): NXTLSBlock; virtual; abstract; function GetNicePortName: string; virtual; function GetFullPortName: string; virtual; function GetOmitHeader: Boolean; virtual; abstract; function GetPortName: string; virtual; function GetQuiet: Boolean; virtual; abstract; function GetRCXFirmwareChunkSize: Integer; virtual; abstract; function GetRxTimeout: Word; virtual; abstract; function GetUseBT: Boolean; virtual; procedure SetBrickType(const Value: byte); virtual; procedure SetBTName(const Value: string); virtual; procedure SetDownloadWaitTime(const Value: Integer); virtual; abstract; procedure SetEEPROM(addr: Byte; const Value: Byte); virtual; abstract; procedure SetFastMode(const Value: boolean); virtual; procedure SetLSBlock(port: byte; const Value: NXTLSBlock); virtual; abstract; procedure SetOmitHeader(const Value: Boolean); virtual; abstract; procedure SetPort(const Value: string); virtual; procedure SetQuiet(const Value: Boolean); virtual; abstract; procedure SetRCXFirmwareChunkSize(const Value: Integer); virtual; abstract; procedure SetRxTimeout(const Value: Word); virtual; abstract; procedure SetUseBT(const Value: boolean); virtual; procedure SetVerbose(const Value: boolean); virtual; protected procedure DoDownloadDone; procedure DoDownloadStart; procedure DoDownloadStatus(cur, total : Integer; var Abort : boolean); procedure DoOpenStateChanged; procedure DoGetVarInfoByID(const id : integer; var offset, size, vartype : integer); procedure DoGetVarInfoByName(const name : string; var offset, size, vartype : integer); public constructor Create(aType : byte = 0; const aPort : string = ''); virtual; destructor Destroy; override; function Open : boolean; virtual; abstract; function Close : boolean; virtual; // PBrick sound commands function PlayTone(aFreq, aTime : word) : boolean; virtual; abstract; function PlaySystemSound(aSnd : byte) : boolean; virtual; abstract; // PBrick output control commands function MotorsOn(aMotorList : Byte) : boolean; virtual; abstract; function MotorsOff(aMotorList : Byte) : boolean; virtual; abstract; function MotorsFloat(aMotorList : Byte) : boolean; virtual; abstract; function SetFwd(aMotorList : Byte) : boolean; virtual; abstract; function SetRwd(aMotorList : Byte) : boolean; virtual; abstract; function SwitchDirection(aMotorList : Byte) : boolean; virtual; abstract; function SetMotorPower(aMotorList : Byte; aSrc, aNum : integer) : boolean; virtual; abstract; // PBrick input control commands function SetSensorType(aNum, aType : integer) : boolean; virtual; abstract; function SetSensorMode(aNum, aMode, aSlope : integer) : boolean; virtual; abstract; function ClearSensorValue(aNum : integer) : boolean; virtual; abstract; // general function TowerExists : boolean; virtual; abstract; function Ping : boolean; virtual; abstract; function PrepareBrick : boolean; virtual; abstract; function UnlockFirmware : boolean; virtual; abstract; function UnlockBrick : string; virtual; abstract; function DownloadMemoryMap : TStrings; virtual; abstract; function MonitorIR(aSeconds: integer): TStrings; virtual; abstract; function PowerDownTime(aTime : integer) : boolean; virtual; abstract; function BatteryLevel : integer; virtual; abstract; function BrickAlive : boolean; virtual; abstract; function Shutdown : boolean; virtual; abstract; function Sleep(aVal : integer) : boolean; virtual; abstract; function Version(var rom : Cardinal; var ram : Cardinal) : boolean; virtual; abstract; function TransmitPower(aLevel : TTransmitLevel) : boolean; virtual; abstract; function Poll(aSrc, aNum : integer) : variant; virtual; abstract; function StartTask(aTask : integer) : boolean; virtual; abstract; function StopTask(aTask : integer) : boolean; virtual; abstract; function StopAllTasks : boolean; virtual; abstract; function DeleteTask(aTask : integer) : boolean; virtual; abstract; function DeleteAllTasks : boolean; virtual; abstract; function DeleteSub(aSub : integer) : boolean; virtual; abstract; function DeleteAllSubs : boolean; virtual; abstract; function ClearTimer(aNum : integer) : boolean; virtual; abstract; function ClearMemory : boolean; virtual; abstract; function GetOutputStatus(aOut : integer) : integer; virtual; abstract; function GetVariableValue(aVar: integer): variant; virtual; abstract; function GetInputValue(aIn: integer): integer; virtual; abstract; function GetMessageValue(aNum : integer) : integer; virtual; abstract; function GetTimerValue(aNum : integer) : integer; virtual; abstract; function GetCounterValue(aNum : integer) : integer; virtual; abstract; // PBrick arithmetic/logical commands function SetVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function SumVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function SubVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function DivVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function MulVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function SgnVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function AbsVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function AndVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; function OrVar(aVar, aSrc, aNum : integer) : boolean; virtual; abstract; // communication to brick function SendRawCommand(aCmd : string; bRetry : boolean) : string; virtual; abstract; function SendRemoteStr(aEvent : string; aRepeat : integer = 1) : boolean; virtual; abstract; function SendRemote(aEvent : Word; aRepeat : integer = 1) : boolean; virtual; abstract; function SendMessage(aMsg : integer) : boolean; virtual; abstract; // RCX/2 only function SelectProgram(aProg : integer) : boolean; virtual; abstract; function SelectDisplay(aSrc, aNumber : integer) : boolean; virtual; abstract; function SetWatchHHMM(aHrs, aMins : integer) : boolean; virtual; abstract; function SetWatch(aTime : string) : boolean; virtual; abstract; function DownloadFirmware(aFile : string; bFast, bComp, bUnlock : boolean) : boolean; virtual; abstract; function SetDatalog(aSize : integer) : boolean; virtual; abstract; function DatalogNext(aSrc, aNum : integer) : boolean; virtual; abstract; function UploadPartialDatalog(aFrom, aSize : integer) : TStrings; virtual; abstract; function UploadDatalog(bVerbose : boolean) : TStrings; virtual; abstract; // CM only methods function Drive(aLeft, aRight : integer) : boolean; virtual; abstract; function ClearTachoCounter(aMotorList : Byte) : boolean; virtual; abstract; function OnWait(aMotorList : Byte; aNum : integer; aTime : Byte) : boolean; virtual; abstract; function OnWaitDifferent(aMotorList : Byte; aNum0, aNum1, aNum2 : integer; aTime : Byte) : boolean; virtual; abstract; // Scout only methods function ScoutNum(aVal : integer) : boolean; virtual; abstract; function Scout(bPower : boolean = true) : boolean; virtual; abstract; function CalibrateLightSensor : boolean; virtual; abstract; function SetFeedback(src, val : integer) : boolean; virtual; abstract; function SetLightSensorUpperThreshold(src : TLSSource; val : TThresholdValue) : boolean; virtual; abstract; function SetLightSensorLowerThreshold(src : TLSSource; val : TThresholdValue) : boolean; virtual; abstract; function SetLightSensorHysteresis(src : TLSSource; val : TThresholdValue) : boolean; virtual; abstract; function SetLightSensorBlinkTime(src : TLSSource; val : TBlinkTimeValue) : boolean; virtual; abstract; function SetTimerLimit(num : TTimerNumber; src : TTCSource; val : integer) : boolean; virtual; abstract; function SetCounterLimit(num : TCounterNumber; src : TTCSource; val : integer) : boolean; virtual; abstract; function ScoutRules(motion : TScoutMotion; touch : TScoutTouch; light : TScoutLight; time : TScoutScale; fx : TScoutEffects) : boolean; virtual; abstract; function ScoutSound(bSoundEnable : boolean; bSoundOff : boolean; aNum : TSoundSetNumber) : boolean; virtual; abstract; // Scout & Spybot only methods function SendVLL(aSrc, aNum : integer) : boolean; virtual; abstract; function SetLight(bOn : boolean) : boolean; virtual; abstract; // RCX2, Scout, & Spybot methods function PollMemory(address : Integer; size : Integer = 128) : TStrings; virtual; abstract; function SetGlobalOutput(motors : TMotorsNum; action : TGlobalOutAction) : boolean; virtual; abstract; function SetGlobalDirection(motors : TMotorsNum; action : TGlobalDirAction) : boolean; virtual; abstract; function SetMaxPower(motors : TMotorsNum; src, num : integer) : boolean; virtual; abstract; function IncCounter(num : TCounterNumber) : boolean; virtual; abstract; function DecCounter(num : TCounterNumber) : boolean; virtual; abstract; function ClearCounter(num : TCounterNumber) : boolean; virtual; abstract; // RCX2 & spybot only methods function ClearSound : boolean; virtual; abstract; function UnmuteSound : boolean; virtual; abstract; function SendUARTData(start, size : integer) : boolean; virtual; abstract; function SetEvent(enum, snum, etype : integer) : boolean; virtual; abstract; function CalibrateEvent(enum, upper, lower, hysteresis : integer) : boolean; virtual; abstract; function ClearAllEvents : boolean; virtual; abstract; function SetSourceValue(aDestSrc, aDestVal, aOrigSrc: Byte; aOrigVal: Smallint): boolean; virtual; abstract; // RCX2, Spy, & NXT function MuteSound : boolean; virtual; abstract; // RCX2 only methods function ViewSourceValue(prec, src, value : integer) : boolean; virtual; abstract; // Spybot only methods function PollEEPROM(block : Integer = -1) : TStrings; virtual; abstract; // NXT only methods // NXT direct commands function StartProgram(const filename : string) : boolean; virtual; abstract; function StopProgram : boolean; virtual; abstract; function PlaySoundFile(const filename : string; bLoop : boolean) : boolean; virtual; abstract; function GetNXTOutputState(const port : byte; var power : integer; var mode, regmode : byte; var turnratio : integer; var runstate : byte; var tacholimit : cardinal; var tachocount, blocktachocount, rotationcount : longint) : boolean; virtual; abstract; function SetNXTOutputState(const port : byte; const power : integer; const mode, regmode : byte; const turnratio : integer; const runstate : byte; const tacholimit : cardinal) : boolean; virtual; abstract; function GetNXTInputValues(const port : byte; var valid, calibrated : boolean; var stype, smode : byte; var raw, normalized : word; var scaled, calvalue : smallint) : boolean; virtual; abstract; function SetNXTInputMode(const port, stype, smode : byte) : boolean; virtual; abstract; function ResetInputScaledValue(const port : byte) : boolean; virtual; abstract; function ResetOutputPosition(const port : byte; const Relative : boolean) : boolean; virtual; abstract; function MessageWrite(const inbox : byte; const msg : string) : boolean; virtual; abstract; function KeepAlive(var time : cardinal; const chkResponse : boolean = true) : boolean; virtual; abstract; function LSGetStatus(port : byte; var bytesReady : byte) : boolean; virtual; abstract; function GetCurrentProgramName(var name : string) : boolean; virtual; abstract; function GetButtonState(const idx : byte; const reset : boolean; var pressed : boolean; var count : byte) : boolean; virtual; abstract; function MessageRead(const remote, local : byte; const remove : boolean; var Msg : NXTMessage) : boolean; virtual; abstract; function SetPropDebugging(const debugging : boolean; const pauseClump : byte; const pausePC : Word) : boolean; virtual; abstract; function GetPropDebugging(var debugging : boolean; var pauseClump : byte; var pausePC : Word) : boolean; virtual; abstract; function SetVMState(const state : byte) : boolean; virtual; abstract; function SetVMStateEx(var state : byte; var clump : byte; var pc : word) : boolean; virtual; abstract; function GetVMState(var state : byte; var clump : byte; var pc : word) : boolean; virtual; abstract; // NXT system commands function NXTOpenRead(const filename : string; var handle : FantomHandle; var size : cardinal) : boolean; virtual; abstract; function NXTOpenWrite(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; virtual; abstract; function NXTRead(var handle : FantomHandle; var count : word; var buffer : NXTDataBuffer) : boolean; virtual; abstract; function NXTWrite(var handle : FantomHandle; const buffer : NXTDataBuffer; var count : word; const chkResponse : boolean = false) : boolean; virtual; abstract; function NXTCloseFile(var handle : FantomHandle; const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTDeleteFile(var filename : string; const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTFindFirstFile(var filename : string; var IterHandle : FantomHandle; var filesize, availsize : cardinal) : boolean; virtual; abstract; function NXTFindNextFile(var IterHandle : FantomHandle; var filename : string; var filesize, availsize : cardinal) : boolean; virtual; abstract; function NXTFindClose(var IterHandle : FantomHandle) : boolean; virtual; abstract; function NXTGetVersions(var protmin, protmaj, firmmin, firmmaj : byte) : boolean; virtual; abstract; function NXTFirmwareVersion : word; virtual; function NXTInstalledFirmware : TInstalledFirmware; virtual; function NXTOpenWriteLinear(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; virtual; abstract; function NXTOpenReadLinear(const filename : string; var handle : FantomHandle; var size : cardinal) : boolean; virtual; abstract; function NXTOpenWriteData(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; virtual; abstract; function NXTOpenAppendData(const filename : string; var size : cardinal; var handle : FantomHandle) : boolean; virtual; abstract; function NXTCloseModuleHandle(var handle : FantomHandle; const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTBootCommand(const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTSetBrickName(const name : string; const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTGetBrickName : string; function NXTGetDeviceInfo(var name : string; var BTAddress : string; var BTSignal : Cardinal; var memFree : Cardinal) : boolean; virtual; abstract; function NXTFreeMemory : integer; virtual; abstract; function NXTDeleteUserFlash(const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTBTFactoryReset(const chkResponse: boolean = false) : boolean; virtual; abstract; function NXTPollCommandLen(const bufNum : byte; var count : byte) : boolean; virtual; abstract; function NXTPollCommand(const bufNum : byte; var count : byte; var buffer : NXTDataBuffer) : boolean; virtual; abstract; function NXTWriteIOMap(var ModID : Cardinal; const Offset : Word; var count : Word; const buffer : NXTDataBuffer; chkResponse : Boolean = False) : boolean; virtual; abstract; function NXTReadIOMap(var ModID : Cardinal; const Offset : Word; var count : Word; var buffer : NXTDataBuffer) : boolean; virtual; abstract; function NXTFindFirstModule(var ModName : string; var Handle : FantomHandle; var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; virtual; abstract; function NXTFindNextModule(var Handle : FantomHandle; var ModName : string; var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; virtual; abstract; function NXTRenameFile(const old, new : string; const chkResponse: boolean = false) : boolean; virtual; abstract; { kNXT_SCGetBTAddress = $9A; } // wrapper functions function NXTDownloadFile(const filename : string; const filetype : TNXTFileType) : boolean; virtual; abstract; function NXTDownloadStream(aStream : TStream; const dest : string; const filetype : TNXTFileType) : boolean; virtual; abstract; function NXTUploadFile(const filename : string; const dir : string = '') : boolean; virtual; abstract; function NXTUploadFileToStream(const filename : string; aStream : TStream) : boolean; virtual; abstract; function NXTListFiles(const searchPattern : string; Files : TStrings) : boolean; virtual; abstract; function NXTListModules(const searchPattern : string; Modules : TStrings) : boolean; virtual; abstract; function NXTListBricks(Bricks : TStrings) : boolean; virtual; abstract; procedure NXTInitializeResourceNames; virtual; abstract; procedure NXTUpdateResourceNames; virtual; abstract; function NXTDefragmentFlash : Boolean; virtual; // properties property EEPROM[addr : Byte] : Byte read GetEEPROM write SetEEPROM; property EEPROMBlocks[idx : Integer] : EEPROMBlock read GetEEPROMBlock; property NXTLowSpeed[port : byte] : NXTLSBlock read GetLSBlock write SetLSBlock; property IsOpen : boolean read GetIsOpen; property FastMode : boolean read fFastMode write SetFastMode; property UseBluetooth : boolean read GetUseBT write SetUseBT; property BluetoothName : string read fBTName write SetBTName; property BluetoothSearchTimeout : Cardinal read fBST write fBST; property Quiet : Boolean read GetQuiet write SetQuiet; property BrickType : byte read FBrickType write SetBrickType; property Port : string read fPort write SetPort; property PortName : string read GetPortName; property NicePortName : string read GetNicePortName; property FullPortName : string read GetFullPortName; property BrickTypeName : string read GetBrickTypeName; property RxTimeout : Word read GetRxTimeout write SetRxTimeout; property VerboseMode : boolean read fVerbose write SetVerbose; property AutoClose : boolean read fAutoClose write fAutoClose; property DataLog : TStrings read fDataLog; property MemoryMap : TStrings read fMemMap; property MemoryData : TStrings read fMemData; property TowerExistsSleep : Word read fTowerExistsSleep write fTowerExistsSleep; property LinkLog : String read GetLinkLog; property RCXFirmwareChunkSize : Integer read GetRCXFirmwareChunkSize write SetRCXFirmwareChunkSize; property DownloadWaitTime : Integer read GetDownloadWaitTime write SetDownloadWaitTime; property OmitHeader : Boolean read GetOmitHeader write SetOmitHeader; property OnDownloadStart : TNotifyEvent read fOnDownloadStart write fOnDownloadStart; property OnDownloadDone : TNotifyEvent read fOnDownloadDone write fOnDownloadDone; property OnDownloadStatus : TDownloadStatusEvent read fOnDownloadStatus write fOnDownloadStatus; property OnOpenStateChanged : TNotifyEvent read fOnOpenStateChanged write fOnOpenStateChanged; property OnGetVarInfoByID : TGetVarInfoByIDEvent read fOnGetVarInfoByID write fOnGetVarInfoByID; property OnGetVarInfoByName : TGetVarInfoByNameEvent read fOnGetVarInfoByName write fOnGetVarInfoByName; end; function NameToNXTFileType(name : string) : TNXTFileType; function MakeValidNXTFilename(const filename : string) : string; function GetInitFilename: string; function FantomAPIAvailable : boolean; procedure LoadNXTPorts(aStrings : TStrings); function BytesToCardinal(b1 : byte; b2 : byte = 0; b3 : byte = 0; b4 : Byte = 0) : Cardinal; function InstalledFirmwareAsString(const ifw : TInstalledFirmware) : string; implementation uses SysUtils, uGlobals, {$IFNDEF FPC} FANTOM {$ELSE} {$IFDEF Darwin}fantomosx{$ENDIF} {$IFNDEF Darwin} {$IFDEF Unix}fantomfpc{$ENDIF} {$IFDEF Windows}FANTOM{$ENDIF} {$ENDIF} {$ENDIF}; function InstalledFirmwareAsString(const ifw : TInstalledFirmware) : string; const FWSTR : array[TInstalledFirmware] of string = ('unknown', 'standard', 'enhanced'); begin Result := FWSTR[ifw]; end; function BytesToCardinal(b1 : byte; b2 : byte = 0; b3 : byte = 0; b4 : Byte = 0) : Cardinal; begin Result := Cardinal(b1) + (Cardinal(b2) shl 8) + (Cardinal(b3) shl 16) + (Cardinal(b4) shl 24); end; function FantomAPIAvailable : boolean; begin Result := FantomAPILoaded; end; procedure LoadNXTPorts(aStrings : TStrings); var i : integer; SL : TStringList; name : string; begin name := GetInitFilename; if FileExists(name) then begin SL := TStringList.Create; try SL.LoadFromFile(name); for i := 0 to SL.Count - 1 do aStrings.Add(SL.Names[i]); for i := 0 to SL.Count - 1 do aStrings.Add(SL.Values[SL.Names[i]]); finally SL.Free; end; end; end; function NameToNXTFileType(name : string) : TNXTFileType; var ext : string; begin Result := nftOther; ext := AnsiLowercase(ExtractFileExt(name)); if (ext = '.rso') or (ext = '.rmd') then Result := nftSound else if ext = '.rdt' then Result := nftData else if (ext = '.ric') or (ext = '.rbm') then Result := nftGraphics else if (ext = '.rxe') or (ext = '.sys') or (ext = '.rtm') or (ext = '.rpg') then Result := nftProgram end; function MakeValidNXTFilename(const filename : string) : string; begin Result := ExtractFileName(filename); Result := Copy(ChangeFileExt(Result, ''), 1, 15) + ExtractFileExt(Result); end; { TBrickComm } constructor TBrickComm.Create(aType: byte; const aPort: string); var i : integer; begin inherited Create; fActive := False; fFastMode := False; fUseBT := False; fAutoClose := False; fBrickType := aType; fPort := aPort; fTowerExistsSleep := 30; fBST := 30; fBTName := ''; fLocalIFW := ifUnknown; fLocalFV := 0; for i := 0 to 2 do begin fMotorPower[i] := 4; fMotorForward[i] := True; fMotorOn[i] := False; end; for i := 0 to 3 do begin fSensorType[i] := 0; fSensorMode[i] := 0; end; fDatalog := TStringList.Create; fMemMap := TStringList.Create; fMemData := TStringList.Create; end; destructor TBrickComm.Destroy; begin Close; FreeAndNil(fDatalog); FreeAndNil(fMemMap); FreeAndNil(fMemData); inherited Destroy; end; procedure TBrickComm.DoDownloadDone; begin if Assigned(fOnDownloadDone) then fOnDownloadDone(self); end; procedure TBrickComm.DoDownloadStart; begin if Assigned(fOnDownloadStart) then fOnDownloadStart(self); end; procedure TBrickComm.DoDownloadStatus(cur, total: Integer; var Abort: boolean); begin Abort := False; if Assigned(fOnDownloadStatus) then fOnDownloadStatus(Self, cur, total, Abort); end; procedure TBrickComm.DoOpenStateChanged; begin if Assigned(fOnOpenStateChanged) then fOnOpenStateChanged(self); end; procedure TBrickComm.DoGetVarInfoByID(const id: integer; var offset, size, vartype: integer); begin offset := -1; size := -1; vartype := -1; if Assigned(fOnGetVarInfoByID) then fOnGetVarInfoByID(Self, id, offset, size, vartype); end; procedure TBrickComm.DoGetVarInfoByName(const name: string; var offset, size, vartype: integer); begin offset := -1; size := -1; vartype := -1; if Assigned(fOnGetVarInfoByName) then fOnGetVarInfoByName(Self, name, offset, size, vartype); end; function TBrickComm.GetBrickTypeName: string; const BrickNames : array[rtRCX..rtNXT] of String = (K_RCX, K_CYBER, K_SCOUT, K_RCX2, K_SPY, K_SWAN, K_NXT); begin Result := BrickNames[BrickType]; end; function TBrickComm.GetIsOpen: boolean; begin Result := FActive; end; function TBrickComm.GetFullPortName: string; begin Result := PortName; end; function TBrickComm.GetNicePortName: string; begin Result := Copy(PortName, 5, 15); end; function TBrickComm.GetPortName: string; begin Result := fPort; end; function TBrickComm.GetUseBT: Boolean; begin Result := fUseBT; end; procedure TBrickComm.SetBrickType(const Value: byte); begin fBrickType := Value; end; procedure TBrickComm.SetBTName(const Value: string); begin if fBTName <> Value then begin Close; fBTName := Value; end; end; procedure TBrickComm.SetFastMode(const Value: boolean); begin if fFastMode <> Value then begin Close; fFastMode := Value; end; end; procedure TBrickComm.SetPort(const Value: string); begin fPort := Value; end; procedure TBrickComm.SetUseBT(const Value: boolean); begin if fUseBT <> Value then begin Close; fUseBT := Value; end; end; procedure TBrickComm.SetVerbose(const Value: boolean); begin fVerbose := Value; end; function IsLinear(const ext : string) : Boolean; begin Result := (ext = '.rxe') or (ext = '.ric'); end; function DefragFileCompare(List: TStringList; Index1, Index2: Integer): Integer; var f1, f2 : string; size1, size2 : integer; l1, l2 : boolean; begin f1 := List.Names[Index1]; f2 := List.Names[Index2]; size1 := StrToIntDef(List.Values[f1], 0); size2 := StrToIntDef(List.Values[f2], 0); l1 := IsLinear(ExtractFileExt(f1)); l2 := IsLinear(ExtractFileExt(f2)); if (l1 = l2) then begin if size1 = size2 then Result := 0 else if size1 < size2 then Result := 1 else Result := -1; end else if l1 and not l2 then Result := -1 else Result := 1; end; function TBrickComm.NXTDefragmentFlash: Boolean; var origFileList : TStringList; i : integer; filename : string; begin origFileList := TStringList.Create; try Result := NXTListFiles('*.*', origFileList); // if there aren't any files then we are nearly done. if origFileList.Count > 0 then begin // upload all files Result := NXTUploadFile('*.*', UserDataLocalPath); if Result then begin // in theory we have all the files in our list now // let's just quickly make sure. for i := 0 to origFileList.Count - 1 do begin if not FileExists(UserDataLocalPath + origFileList.Names[i]) then begin // do something clever here??? Result := False; Exit; end; end; // ok. Result := ClearMemory; if Result then begin // we are committed now. // figure out the correct order using the file ext // (.rxe or .ric first) and file size (within each category // of file type. origFileList.CustomSort(@DefragFileCompare); // now download these files in order for i := 0 to origFileList.Count - 1 do begin filename := origFileList.Names[i]; Result := NXTDownloadFile(UserDataLocalPath + filename, NameToNXTFileType(filename)); if not Result then begin // do something clever here Exit; end; end; // if we were able to download all the files we uploaded then // it is safe to delete them from the PC for i := 0 to origFileList.Count - 1 do begin // delete files locally Result := SysUtils.DeleteFile(UserDataLocalPath + origFileList.Names[i]); end; end; end; end else begin // even if there aren't any files we clear the flash Result := ClearMemory; end; finally FreeAndNil(origFileList); end; end; function TBrickComm.NXTGetBrickName: string; var btsig, memfree : Cardinal; tmpAddr : string; begin Result := ''; tmpAddr := ''; memfree := 0; btsig := 0; NXTGetDeviceInfo(Result, tmpAddr, btsig, memfree); end; function GetInitFilename: string; begin Result := UserDataLocalPath+'nxt.dat'; end; function TBrickComm.NXTFirmwareVersion: word; var pmin, pmaj, fmin, fmaj : byte; begin Result := fLocalFV; if Result = 0 then begin if NXTGetVersions(pmin, pmaj, fmin, fmaj) then Result := fmaj*100 + fmin; fLocalFV := Result; end; end; function TBrickComm.NXTInstalledFirmware: TInstalledFirmware; var state, clump : byte; pc : word; begin Result := fLocalIFW; if IsOpen and (Result = ifUnknown) then begin // if we can call a direct command that only exists in the enhanced firmware // then we know that it is enhanced. if GetVMState(state, clump, pc) then Result := ifEnhanced else Result := ifStandard; fLocalIFW := Result; end; end; function TBrickComm.Close: boolean; begin Result := True; fLocalFV := 0; fLocalIFW := ifUnknown; end; end. bricktools/FantomDefs.pas0000644000175000017500000000171211537752657015367 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit FantomDefs; interface type {$IFDEF FPC} // for FPC we need a different type for 64 bit vs 32 bit. {$ifdef CPU32} FantomHandle = Cardinal; {$endif} {$ifdef CPU64} FantomHandle = QWord; {$endif} {$ELSE} // delphi FantomHandle = Cardinal; {$ENDIF} implementation end. bricktools/rcx_cmd.pas0000644000175000017500000005420311537752657014763 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit rcx_cmd; interface uses Classes, rcx_constants; const kRCX_Cmd_MaxShortLength = 8; type // rcx fragment type TRcxFragment = (kRCX_TaskFragment, kRCX_SubFragment); // variable code TRcxVarCode = (kRCX_SetVar, kRCX_AddVar, kRCX_SubVar, kRCX_DivVar, kRCX_MulVar, kRCX_SgnVar, kRCX_AbsVar, kRCX_AndVar, kRCX_OrVar); TBaseCmd = class protected fLength : integer; fBodyPtr : PByte; fBodyData : array [0..kRCX_Cmd_MaxShortLength] of Byte; function MakeValue16(opcode : Byte; value : integer) : TBaseCmd; function MakeValue8(opcode : Byte; value : integer) : TBaseCmd; procedure ClearBodyPointer; protected fLog : string; procedure WriteToLog(s : string); public constructor Create; destructor Destroy; override; function GetLength : integer; function GetBody : PByte; function CopyOut(dst : PByte) : integer; procedure SetLength(length : integer); function SetVal(data : PByte; length : integer) : TBaseCmd; overload; function SetVal(d0 : Byte) : TBaseCmd; overload; function SetVal(d0, d1 : Byte) : TBaseCmd; overload; function SetVal(d0, d1, d2 : Byte) : TBaseCmd; overload; function SetVal(d0, d1, d2, d3 : Byte) : TBaseCmd; overload; function SetVal(d0, d1, d2, d3, d4 : Byte) : TBaseCmd; overload; function SetVal(d0, d1, d2, d3, d4, d5 : Byte) : TBaseCmd; overload; function SetVal(d0, d1, d2, d3, d4, d5, d6: Byte): TBaseCmd; overload; procedure Print; property Log : string read fLog; end; TNxtCmd = class(TBaseCmd) public function MakeCmdWriteFile(const b1, b2 : byte; const handle : byte; const Count : Word; Data : array of Byte) : TNxtCmd; function MakeCmdWithFilename(const b1, b2 : byte; const filename : string; const filesize : Cardinal = 0) : TNxtCmd; function MakeCmdRenameFile(const b1 : byte; const old, new : string) : TNxtCmd; function MakeBoot(bResponse : boolean) : TNxtCmd; function MakeSetName(const name : string; bResponse : boolean) : TNxtCmd; function MakeCmdWriteIOMap(const b1, b2 : byte; const ModID : Cardinal; const Offset, Count : Word; Data : array of Byte) : TNxtCmd; function MakeCmdReadIOMap(const b1, b2 : byte; const ModID : Cardinal; const Offset, Count : Word) : TNxtCmd; function MakeSetOutputState(port, mode, regmode, runstate : byte; power, turnratio : shortint; tacholimit : cardinal; bResponse : boolean) : TNxtCmd; end; TNINxtCmd = class(TNxtCmd) public function BytePtr : PByte; function Len : integer; end; TRcxCmd = class(TBaseCmd) private protected procedure SetOffset(offset : integer); function DirSpeed(val : integer) : Byte; public // utility functions to create specific commands // variables function MakeVar(code : TRcxVarCode; myvar : Byte; value : integer) : TRcxCmd; // outputs function MakeOutputMode(outputs : Byte; mode : integer) : TRcxCmd; function MakeOutputPower(outputs : Byte; value : integer) : TRcxCmd; function MakeOutputDir(outputs : Byte; dir : integer) : TRcxCmd; // inputs function MakeInputMode(input : Byte; mode : integer) : TRcxCmd; function MakeInputType(input : Byte; itype : integer) : TRcxCmd; // sound function MakePlaySound(sound : Byte) : TRcxCmd; function MakePlayTone(freq : Word; duration : Byte) : TRcxCmd; // control flow function MakeTest(v1 : integer; rel : integer; v2 : integer; offset : smallint) : TRcxCmd; function MakeJump(offset : smallint) : TRcxCmd; function MakeSetLoop(v : integer) : TRcxCmd; function MakeCheckLoop(offset : smallint) : TRcxCmd; // cybermaster stuff function MakeDrive(m0, m1 : integer) : TRcxCmd; function MakeOnWait(outputs : Byte; aNum : integer; aTime : Byte) : TRcxCmd; function MakeOnWaitDifferent(outputs : Byte; aNum0, aNum1, aNum2 : integer; aTime : Byte) : TRcxCmd; // misc function MakeStopTask(task : Byte) : TRcxCmd; function MakeWait(value : integer) : TRcxCmd; function MakeDisplay(value : integer) : TRcxCmd; overload; function MakeDisplay(src, value : integer) : TRcxCmd; overload; function MakeSet(dst, src : integer) : TRcxCmd; // system commands function MakePoll(value : integer) : TRcxCmd; function MakeUnlock : TRcxCmd; function MakeBegin(ftype : TRcxFragment; taskNumber : Byte; length : Word) : TRcxCmd; function MakeDownload(seq : Word; data : PByte; length : Word) : TRcxCmd; function MakeDeleteTasks : TRcxCmd; function MakeDeleteSubs : TRcxCmd; function MakePing : TRcxCmd; function MakeUploadDatalog(start, count : Word) : TRcxCmd; function MakeSetDatalog(size : Word) : TRcxCmd; function MakeBoot : TRcxCmd; // special command to unlock CyberMaster function MakeUnlockCM : TRcxCmd; end; function RCX_VALUE(t : TRcxValueType; d : smallint) : integer; implementation uses SysUtils, uCommonUtils; function RCX_VALUE(t : TRcxValueType; d : smallint) : integer; begin result := integer((t shl 16) or (d and $FFFF)); end; function RCX_VALUE_TYPE(v : integer) : TRcxValueType; begin result := Byte(smallint(v shr 16) and $FF); end; function RCX_VALUE_DATA(v : integer) : smallint; begin result := smallint(v and $FFFF); end; function kRCX_VarOp(code : TRcxVarCode) : integer; begin result := $14 + (Ord(code) * 16); end; { TBaseCmd } procedure TBaseCmd.ClearBodyPointer; begin if fLength > kRCX_Cmd_MaxShortLength then FreeMem(fBodyPtr, fLength); end; function TBaseCmd.CopyOut(dst: PByte): integer; var tmp : PByte; begin tmp := GetBody; Move(tmp^, dst^, fLength); result := fLength; end; constructor TBaseCmd.Create; begin inherited Create; fLog := ''; fLength := 0; end; destructor TBaseCmd.Destroy; begin ClearBodyPointer; inherited Destroy; end; function TBaseCmd.MakeValue16(opcode: Byte; value: integer): TBaseCmd; var data : SmallInt; begin data := RCX_VALUE_DATA(value); result := SetVal(opcode, Byte(RCX_VALUE_TYPE(value)), Lo(data), Hi(data)); end; function TBaseCmd.MakeValue8(opcode: Byte; value: integer): TBaseCmd; begin result := SetVal(opcode, Byte(RCX_VALUE_TYPE(value)), Byte(RCX_VALUE_DATA(value))); end; procedure TBaseCmd.Print; var ptr : PByte; i : integer; tmp : string; begin ptr := GetBody; tmp := ''; for i := 0 to fLength-1 do begin tmp := tmp + Format('%2x', [ptr^]); inc(ptr); end; WriteToLog(tmp + #13#10); end; procedure TBaseCmd.SetLength(length: integer); begin if length = fLength then Exit; ClearBodyPointer; fLength := length; if fLength > kRCX_Cmd_MaxShortLength then fBodyPtr := AllocMem(fLength * sizeof(Byte)); end; function TBaseCmd.SetVal(data: PByte; length: integer): TBaseCmd; var tmp : PByte; begin SetLength(length); tmp := GetBody; Move(data^, tmp^, length); result := self; end; function TBaseCmd.SetVal(d0: Byte): TBaseCmd; begin SetLength(1); fBodyData[0] := d0; result := self; end; function TBaseCmd.SetVal(d0, d1: Byte): TBaseCmd; begin SetLength(2); fBodyData[0] := d0; fBodyData[1] := d1; result := self; end; function TBaseCmd.SetVal(d0, d1, d2: Byte): TBaseCmd; begin SetLength(3); fBodyData[0] := d0; fBodyData[1] := d1; fBodyData[2] := d2; result := self; end; function TBaseCmd.SetVal(d0, d1, d2, d3: Byte): TBaseCmd; begin SetLength(4); fBodyData[0] := d0; fBodyData[1] := d1; fBodyData[2] := d2; fBodyData[3] := d3; result := self; end; function TBaseCmd.SetVal(d0, d1, d2, d3, d4: Byte): TBaseCmd; begin SetLength(5); fBodyData[0] := d0; fBodyData[1] := d1; fBodyData[2] := d2; fBodyData[3] := d3; fBodyData[4] := d4; result := self; end; function TBaseCmd.SetVal(d0, d1, d2, d3, d4, d5: Byte): TBaseCmd; begin SetLength(6); fBodyData[0] := d0; fBodyData[1] := d1; fBodyData[2] := d2; fBodyData[3] := d3; fBodyData[4] := d4; fBodyData[5] := d5; result := self; end; function TBaseCmd.SetVal(d0, d1, d2, d3, d4, d5, d6: Byte): TBaseCmd; begin SetLength(7); fBodyData[0] := d0; fBodyData[1] := d1; fBodyData[2] := d2; fBodyData[3] := d3; fBodyData[4] := d4; fBodyData[5] := d5; fBodyData[6] := d6; result := self; end; procedure TBaseCmd.WriteToLog(s: string); begin fLog := fLog + s; end; function TBaseCmd.GetBody: PByte; begin if fLength <= kRCX_Cmd_MaxShortLength then result := @fBodyData[0] else result := fBodyPtr; end; function TBaseCmd.GetLength: integer; begin result := fLength; end; { TRcxCmd } function TRcxCmd.DirSpeed(val: integer): Byte; begin result := Byte((val) and 8 xor 8 or ((val)*(((val) shr 3) * 2 xor 1)) and 7); end; function TRcxCmd.MakeBegin(ftype: TRcxFragment; taskNumber: Byte; length: Word): TRcxCmd; var op : Byte; begin if ftype = kRCX_TaskFragment then op := kRCX_BeginTaskOp else op := kRCX_BeginSubOp; result := TRcxCmd(SetVal(op, 0, taskNumber, 0, Lo(length), Hi(length))); end; function TRcxCmd.MakeBoot: TRcxCmd; begin SetVal(kRCX_UnlockFirmOp, $4c, $45, $47, $4f, $ae); // LEGO result := self; end; function TRcxCmd.MakeCheckLoop(offset: smallint): TRcxCmd; begin SetVal(kRCX_CheckLoopOp, 0, 0); SetOffset(offset); result := self; end; function TRcxCmd.MakeWait(value: integer): TRcxCmd; begin result := TRcxCmd(MakeValue16(kRCX_WaitOp, value)); end; function TRcxCmd.MakeDeleteSubs: TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_DeleteSubsOp)); end; function TRcxCmd.MakeDeleteTasks: TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_DeleteTasksOp)); end; function TRcxCmd.MakeDisplay(value: integer): TRcxCmd; begin result := TRcxCmd(MakeValue16(kRCX_DisplayOp, value)); end; function TRcxCmd.MakeDisplay(src, value: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_DisplayOp, Byte(src), Lo(SmallInt(value)), Hi(SmallInt(value)))); end; function TRcxCmd.MakeDownload(seq: Word; data: PByte; length: Word): TRcxCmd; var ptr : PByte; checksum, b : Byte; begin SetLength(6 + length); ptr := GetBody; ptr^ := kRCX_DownloadOp; inc(ptr); ptr^ := Lo(seq); inc(ptr); ptr^ := Hi(seq); inc(ptr); ptr^ := Lo(length); inc(ptr); ptr^ := Hi(length); inc(ptr); checksum := 0; while length > 0 do begin b := data^; inc(data); checksum := Byte(checksum + b); ptr^ := b; inc(ptr); dec(length); end; ptr^ := checksum; result := self; end; function TRcxCmd.MakeDrive(m0, m1: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_DriveOp, DirSpeed(m0) or DirSpeed(m1) shl 4)); end; function TRcxCmd.MakeInputMode(input: Byte; mode: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_InputModeOp, input, Byte(mode))); end; function TRcxCmd.MakeInputType(input: Byte; itype: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_InputTypeOp, input, Byte(itype))); end; function TRcxCmd.MakeJump(offset: smallint): TRcxCmd; var ptr : PByte; begin SetLength(3); ptr := GetBody; ptr^ := kRCX_JumpOp; SetOffset(offset); result := self; end; function TRcxCmd.MakeOnWait(outputs: Byte; aNum: integer; aTime: Byte): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_OnWaitOp, Byte((outputs shl 4) or DirSpeed(aNum)), aTime)); end; function TRcxCmd.MakeOnWaitDifferent(outputs: Byte; aNum0, aNum1, aNum2: integer; aTime: Byte): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_OnWaitDifferentOp, Byte((outputs shl 4) or DirSpeed(aNum0)), Byte((DirSpeed(aNum1) shl 4) or DirSpeed(aNum2)), aTime)); end; function TRcxCmd.MakeOutputDir(outputs: Byte; dir: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_OutputDirOp, Byte(dir or outputs))); end; function TRcxCmd.MakeOutputMode(outputs: Byte; mode: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_OutputModeOp, Byte(mode or outputs))); end; function TRcxCmd.MakeOutputPower(outputs: Byte; value: integer): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_OutputPowerOp, outputs, Byte(RCX_VALUE_TYPE(value)), Byte(RCX_VALUE_DATA(value)))); end; function TRcxCmd.MakePing: TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_PingOp)); end; function TRcxCmd.MakePlaySound(sound: Byte): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_PlaySoundOp, sound)); end; function TRcxCmd.MakePlayTone(freq: Word; duration: Byte): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_PlayToneOp, Lo(freq), Hi(freq), duration)); end; function TRcxCmd.MakePoll(value: integer): TRcxCmd; begin result := TRcxCmd(MakeValue8(kRCX_PollOp, value)); end; function TRcxCmd.MakeSet(dst, src: integer): TRcxCmd; var ptr : PByte; begin SetLength(6); ptr := GetBody; ptr^ := kRCX_SetSourceValueOp; inc(ptr); ptr^ := Byte(RCX_VALUE_TYPE(dst)); inc(ptr); ptr^ := Lo(RCX_VALUE_DATA(dst)); inc(ptr); ptr^ := Byte(RCX_VALUE_TYPE(src)); inc(ptr); ptr^ := Lo(RCX_VALUE_DATA(src)); inc(ptr); ptr^ := Hi(RCX_VALUE_DATA(src)); result := self; end; function TRcxCmd.MakeSetDatalog(size: Word): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_SetDatalogOp, Lo(size), Hi(size))); end; function TRcxCmd.MakeSetLoop(v: integer): TRcxCmd; begin result := TRcxCmd(MakeValue8(kRCX_SetLoopOp, v)); end; function TRcxCmd.MakeStopTask(task: Byte): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_StopTaskOp, task)); end; function TRcxCmd.MakeTest(v1, rel, v2: integer; offset: smallint): TRcxCmd; var d1 : SmallInt; ptr : PByte; begin d1 := RCX_VALUE_DATA(v1); SetLength(8); ptr := GetBody; ptr^ := kRCX_LCheckDoOp; inc(ptr); ptr^ := Byte(((rel shl 6) or Byte(RCX_VALUE_TYPE(v1)))); inc(ptr); ptr^ := Byte(RCX_VALUE_TYPE(v2)); inc(ptr); ptr^ := Lo(d1); inc(ptr); ptr^ := Hi(d1); inc(ptr); ptr^ := Byte(RCX_VALUE_DATA(v2)); SetOffset(offset); result := self; end; function TRcxCmd.MakeUnlock: TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_UnlockOp, 1, 3, 5, 7, 11)); end; type MsgType = array[0..26] of Byte; function TRcxCmd.MakeUnlockCM: TRcxCmd; const unlockMsg : MsgType = (kRCX_UnlockFirmOp, Ord('D'),Ord('o'),Ord(' '),Ord('y'),Ord('o'),Ord('u'), Ord(' '),Ord('b'),Ord('y'),Ord('t'),Ord('e'),Ord(','), Ord(' '),Ord('w'),Ord('h'),Ord('e'),Ord('n'),Ord(' '), Ord('I'),Ord(' '),Ord('k'),Ord('n'),Ord('o'),Ord('c'), Ord('k'),Ord('?')); var msg : MsgType; begin msg := unlockMsg; SetVal(@msg[0], sizeof(unlockMsg)); result := self; end; function TRcxCmd.MakeUploadDatalog(start, count: Word): TRcxCmd; begin result := TRcxCmd(SetVal(kRCX_UploadDatalogOp, Lo(start), Hi(start), Lo(count), Hi(count))); end; function TRcxCmd.MakeVar(code: TRcxVarCode; myvar: Byte; value: integer): TRcxCmd; var data : SmallInt; begin data := RCX_VALUE_DATA(value); result := TRcxCmd(SetVal(Byte(kRCX_VarOp(code)), myvar, Byte(RCX_VALUE_TYPE(value)), Lo(data), Hi(data))); end; procedure TRcxCmd.SetOffset(offset: integer); var ptr, tmp : PByte; neg : Byte; begin neg := 0; offset := offset - (fLength - 2); ptr := GetBody; inc(ptr, fLength); dec(ptr, 2); tmp := GetBody; if tmp^ <> kRCX_JumpOp then begin ptr^ := Byte(offset and $FF); inc(ptr); ptr^ := Byte((offset shr 8) and $FF); end else begin if offset < 0 then begin neg := $80; offset := -offset; end; ptr^ := Byte(neg or (offset and $7F)); inc(ptr); ptr^ := Byte((offset shr 7) and $FF); end; end; { TNxtCmd } function TNxtCmd.MakeCmdWriteFile(const b1, b2: byte; const handle : byte; const Count : Word; Data: array of Byte): TNxtCmd; var i, n : integer; orig : PByte; begin n := Count+3; // if n > kNXT_MaxBytes then n := kNXT_MaxBytes; // total bytes must be <= 64 SetLength(n); orig := GetBody; orig^ := b1; inc(orig); orig^ := b2; inc(orig); orig^ := handle; inc(orig); dec(n, 3); // set n back to count (or max - 3, whichever is smaller) for i := Low(Data) to High(Data) do begin dec(n); if n < 0 then Break; orig^ := Data[i]; inc(orig); end; Result := Self; end; function TNxtCmd.MakeCmdWithFilename(const b1, b2: byte; const filename: string; const filesize : cardinal): TNxtCmd; var i : integer; orig : PByte; begin // filename is limited to 19 bytes + null terminator if filesize > 0 then SetLength(26) else SetLength(22); orig := GetBody; orig^ := b1; inc(orig); orig^ := b2; inc(orig); i := 1; while i <= 19 do begin // copy the first nineteen bytes from the filename provided if i > Length(filename) then orig^ := 0 else orig^ := Ord(filename[i]); inc(orig); inc(i); end; orig^ := 0; // set last byte to null inc(orig); if filesize > 0 then begin orig^ := Byte(Word(filesize)); inc(orig); orig^ := HiByte(Word(filesize)); inc(orig); orig^ := Byte(HiWord(filesize)); inc(orig); orig^ := HiByte(HiWord(filesize)); end; Result := Self; end; function TNxtCmd.MakeBoot(bResponse : boolean) : TNxtCmd; var i : integer; orig : PByte; const bootCmd = 'Let''s dance: SAMBA'; begin SetLength(21); orig := GetBody; if bResponse then orig^ := kNXT_SystemCmd else orig^ := kNXT_SystemCmdNoReply; inc(orig); orig^ := kNXT_SCBootCommand; inc(orig); for i := 1 to Length(bootCmd) do begin orig^ := Byte(bootCmd[i]); inc(orig); end; orig^ := 0; // set last byte to null Result := Self; end; function TNxtCmd.MakeSetName(const name: string; bResponse: boolean): TNxtCmd; var i : integer; orig : PByte; begin SetLength(18); orig := GetBody; if bResponse then orig^ := kNXT_SystemCmd else orig^ := kNXT_SystemCmdNoReply; inc(orig); orig^ := kNXT_SCSetBrickName; inc(orig); for i := 1 to kNXT_NameMaxLen do begin if i > Length(name) then orig^ := 0 // pad with nulls to fixed length else orig^ := Byte(name[i]); inc(orig); end; orig^ := 0; // set last byte to null Result := Self; end; function TNxtCmd.MakeCmdWriteIOMap(const b1, b2: byte; const ModID: Cardinal; const Offset, Count: Word; Data: array of Byte): TNxtCmd; var i, n : integer; orig : PByte; begin n := Count+10; // (10 bytes in addition to the actual data if n > kNXT_MaxBytes then n := kNXT_MaxBytes; // total bytes must be <= 64 SetLength(n); orig := GetBody; orig^ := b1; inc(orig); orig^ := b2; inc(orig); orig^ := Lo(Word(ModID)); inc(orig); orig^ := Hi(Word(ModID)); inc(orig); orig^ := Lo(HiWord(ModID)); inc(orig); orig^ := Hi(HiWord(ModID)); inc(orig); orig^ := Lo(Offset); inc(orig); orig^ := Hi(Offset); inc(orig); orig^ := Lo(count); inc(orig); orig^ := Hi(count); inc(orig); dec(n, 10); // set n back to count (or max - 10, whichever is smaller) for i := Low(Data) to High(Data) do begin dec(n); if n < 0 then Break; orig^ := Data[i]; inc(orig); end; Result := Self; end; function TNxtCmd.MakeCmdReadIOMap(const b1, b2: byte; const ModID: Cardinal; const Offset, Count: Word): TNxtCmd; var orig : PByte; begin SetLength(10); orig := GetBody; orig^ := b1; inc(orig); orig^ := b2; inc(orig); orig^ := Lo(Word(ModID)); inc(orig); orig^ := Hi(Word(ModID)); inc(orig); orig^ := Lo(HiWord(ModID)); inc(orig); orig^ := Hi(HiWord(ModID)); inc(orig); orig^ := Lo(Offset); inc(orig); orig^ := Hi(Offset); inc(orig); orig^ := Lo(Count); inc(orig); orig^ := Hi(Count); Result := Self; end; function TNxtCmd.MakeSetOutputState(port, mode, regmode, runstate: byte; power, turnratio: shortint; tacholimit: cardinal; bResponse: boolean): TNxtCmd; var orig : PByte; begin SetLength(12); orig := GetBody; if bResponse then orig^ := kNXT_DirectCmd else orig^ := kNXT_DirectCmdNoReply; inc(orig); orig^ := kNXT_DCSetOutputState; inc(orig); orig^ := port; inc(orig); orig^ := power; inc(orig); orig^ := mode; inc(orig); orig^ := regmode; inc(orig); orig^ := turnratio; inc(orig); orig^ := runstate; inc(orig); orig^ := Lo(Word(tacholimit)); inc(orig); orig^ := Hi(Word(tacholimit)); inc(orig); orig^ := Lo(HiWord(tacholimit)); inc(orig); orig^ := Hi(HiWord(tacholimit)); Result := Self; end; function TNxtCmd.MakeCmdRenameFile(const b1: byte; const old, new: string): TNxtCmd; var i, j : integer; orig : PByte; tmp : string; begin //kNXT_SCRenameFile SetLength(42); orig := GetBody; orig^ := b1; inc(orig); orig^ := kNXT_SCRenameFile; inc(orig); for j := 0 to 1 do begin if j = 0 then tmp := old else tmp := new; i := 1; while i <= 19 do begin // copy the first nineteen bytes from the filename provided if i > Length(tmp) then orig^ := 0 else orig^ := Ord(tmp[i]); inc(orig); inc(i); end; orig^ := 0; // set last byte to null inc(orig); end; Result := Self; end; { TNINxtCmd } function TNINxtCmd.BytePtr: PByte; begin Result := GetBody; inc(Result); end; function TNINxtCmd.Len: integer; begin Result := GetLength; dec(Result); end; end. bricktools/fantomosx.pas0000644000175000017500000006473011537752657015370 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit fantomosx; interface uses FantomDefs; {$I FANTOM_CONST.INC} function createNXT(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; cdecl; function createNXTIterator(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; cdecl; function iFile_getAvailableSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iFile_getSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iFileIterator_getFile(iterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; function iFileIterator_getSize(fileIterHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iModule_getIOMapSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iModule_getModuleID(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iModule_getModuleSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; function iModule_readIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; function iModule_writeIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; function iModuleIterator_getModule(modIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; function iNXT_createFile(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; cdecl; function iNXT_createFileIterator(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; cdecl; function iNXT_createModule(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; cdecl; function iNXT_createModuleIterator(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; cdecl; function iNXT_pollAvailableLength(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; cdecl; function iNXT_readBufferData(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; cdecl; function iNXT_write(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; cdecl; function iNXTIterator_getNXT(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; procedure destroyNXT(nxtHandle : FantomHandle; var status : integer); cdecl; procedure destroyNXTIterator(nxtIteratorHandle : FantomHandle; var status : integer); cdecl; procedure iFile_close(fileHandle : FantomHandle; var status : integer); cdecl; procedure iFile_getName(fileHandle : FantomHandle; filename : PChar; var status : integer); cdecl; procedure iFile_openForDataAppend(fileHandle : FantomHandle; var status : integer); cdecl; procedure iFile_openForDataWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; procedure iFile_openForLinearWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; procedure iFile_openForRead(fileHandle : FantomHandle; var status : integer); cdecl; procedure iFile_openForWrite(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); cdecl; procedure iFile_read(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); cdecl; procedure iFile_remove(fileHandle : FantomHandle; var status : integer); cdecl; procedure iFile_write(fileHandle : FantomHandle; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); cdecl; procedure iFileIterator_advance(iterHandle : FantomHandle; var status : integer); cdecl; procedure iFileIterator_getName(iterHandle : FantomHandle; filename : PChar; var status : integer); cdecl; procedure iModule_getName(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; procedure iModuleIterator_advance(modIterHandle : FantomHandle; var status : integer); cdecl; procedure iModuleIterator_getName(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; procedure iNXT_bluetoothFactoryReset(nxtHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_bootIntoFirmwareDownloadMode(resourceName : PChar; var status : integer); cdecl; procedure iNXT_destroyFile(nxtHandle : FantomHandle; fileHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_destroyFileIterator(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_destroyModule(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_destroyModuleIterator(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_downloadFirmware(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); cdecl; procedure iNXT_eraseUserFlash(nxtHandle : FantomHandle; var status : integer); cdecl; procedure iNXT_findDeviceInFirmwareDownloadMode(resString : PChar; var status : integer); cdecl; procedure iNXT_getDeviceInfo(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); cdecl; procedure iNXT_getFirmwareVersion(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); cdecl; procedure iNXT_getResourceString(nxtHandle : FantomHandle; resString : PChar; var status : integer); cdecl; procedure iNXT_read(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); cdecl; procedure iNXT_sendDirectCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); cdecl; procedure iNXT_setName(nxtHandle : FantomHandle; newName : PChar; var status : integer); cdecl; procedure iNXTIterator_advance(NXTIterHandle : FantomHandle; var status : integer); cdecl; procedure iNXTIterator_getName(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); cdecl; procedure pairBluetooth(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); cdecl; procedure unpairBluetooth(resourceName : PChar; var status : integer); cdecl; procedure FantomSDKClose; cdecl; procedure FantomSDKInit; cdecl; var FantomAPILoaded: Boolean = False; implementation function nFANTOM100_createNXT(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; cdecl; external; function nFANTOM100_createNXTIterator(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iFile_getAvailableSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iFile_getSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iFileIterator_getFile(iterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iFileIterator_getSize(fileIterHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModule_getIOMapSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModule_getModuleID(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModule_getModuleSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModule_readIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModule_writeIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iModuleIterator_getModule(modIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iNXT_createFile(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iNXT_createFileIterator(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iNXT_createModule(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iNXT_createModuleIterator(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; cdecl; external; function nFANTOM100_iNXT_pollAvailableLength(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iNXT_readBufferData(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iNXT_write(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; cdecl; external; function nFANTOM100_iNXTIterator_getNXT(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; external; procedure nFANTOM100_destroyNXT(nxtHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_destroyNXTIterator(nxtIteratorHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFile_close(fileHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFile_getName(fileHandle : FantomHandle; filename : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iFile_openForDataAppend(fileHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFile_openForDataWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iFile_openForLinearWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iFile_openForRead(fileHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFile_openForWrite(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iFile_read(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iFile_remove(fileHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFile_write(fileHandle : FantomHandle; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iFileIterator_advance(iterHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iFileIterator_getName(iterHandle : FantomHandle; filename : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iModule_getName(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iModuleIterator_advance(modIterHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iModuleIterator_getName(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_bluetoothFactoryReset(nxtHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_bootIntoFirmwareDownloadMode(resourceName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_destroyFile(nxtHandle : FantomHandle; fileHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_destroyFileIterator(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_destroyModule(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_destroyModuleIterator(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_downloadFirmware(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_eraseUserFlash(nxtHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_findDeviceInFirmwareDownloadMode(resString : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_getDeviceInfo(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_getFirmwareVersion(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_getResourceString(nxtHandle : FantomHandle; resString : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_read(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_sendDirectCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); cdecl; external; procedure nFANTOM100_iNXT_setName(nxtHandle : FantomHandle; newName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_iNXTIterator_advance(NXTIterHandle : FantomHandle; var status : integer); cdecl; external; procedure nFANTOM100_iNXTIterator_getName(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); cdecl; external; procedure nFANTOM100_pairBluetooth(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_unpairBluetooth(resourceName : PChar; var status : integer); cdecl; external; procedure nFANTOM100_FantomSDKClose; cdecl; external; procedure nFANTOM100_FantomSDKInit; cdecl; external; function createNXT(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; cdecl; begin Result := nFANTOM100_createNXT(resString, status, checkFWversion); end; function createNXTIterator(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_createNXTIterator(searchBluetooth, bluetoothSearchTimeout, status); end; function iFile_getAvailableSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iFile_getAvailableSize(fileHandle, status); end; function iFile_getSize(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iFile_getSize(fileHandle, status); end; function iFileIterator_getFile(iterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iFileIterator_getFile(iterHandle, status); end; function iFileIterator_getSize(fileIterHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iFileIterator_getSize(fileIterHandle, status); end; function iModule_getIOMapSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iModule_getIOMapSize(moduleHandle, status); end; function iModule_getModuleID(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iModule_getModuleID(moduleHandle, status); end; function iModule_getModuleSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iModule_getModuleSize(moduleHandle, status); end; function iModule_readIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iModule_readIOMap(moduleHandle, offset, numberBytesToRead, dataBuffer, status); end; function iModule_writeIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iModule_writeIOMap(moduleHandle, offset, numberBytesToWrite, dataBuffer, status); end; function iModuleIterator_getModule(modIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iModuleIterator_getModule(modIterHandle, status); end; function iNXT_createFile(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iNXT_createFile(nxtHandle, filename, status); end; function iNXT_createFileIterator(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iNXT_createFileIterator(nxtHandle, filePattern, status); end; function iNXT_createModule(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iNXT_createModule(nxtHandle, moduleName, moduleID, moduleSize, IOMapSize, status); end; function iNXT_createModuleIterator(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iNXT_createModuleIterator(nxtHandle, moduleNamePattern, status); end; function iNXT_pollAvailableLength(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iNXT_pollAvailableLength(nxtHandle, bufferSelector, status); end; function iNXT_readBufferData(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iNXT_readBufferData(nxtHandle, dataBuffer, bufferSelector, numberOfBytesToRead, status); end; function iNXT_write(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; cdecl; begin Result := nFANTOM100_iNXT_write(nxtHandle, writeBuffer, writeBufferSize, status); end; function iNXTIterator_getNXT(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; begin Result := nFANTOM100_iNXTIterator_getNXT(nxtIterHandle, status); end; procedure destroyNXT(nxtHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_destroyNXT(nxtHandle, status); end; procedure destroyNXTIterator(nxtIteratorHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_destroyNXTIterator(nxtIteratorHandle, status); end; procedure iFile_close(fileHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iFile_close(fileHandle, status); end; procedure iFile_getName(fileHandle : FantomHandle; filename : PChar; var status : integer); cdecl; begin nFANTOM100_iFile_getName(fileHandle, filename, status); end; procedure iFile_openForDataAppend(fileHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iFile_openForDataAppend(fileHandle, status); end; procedure iFile_openForDataWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; begin nFANTOM100_iFile_openForDataWrite(fileHandle, sizeInBytes, status); end; procedure iFile_openForLinearWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; begin nFANTOM100_iFile_openForLinearWrite(fileHandle, sizeInBytes, status); end; procedure iFile_openForRead(fileHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iFile_openForRead(fileHandle, status); end; procedure iFile_openForWrite(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); cdecl; begin nFANTOM100_iFile_openForWrite(fileHandle, fileSize, status); end; procedure iFile_read(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); cdecl; begin nFANTOM100_iFile_read(fileHandle, fileDataBuffer, bufferSize, status); end; procedure iFile_remove(fileHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iFile_remove(fileHandle, status); end; procedure iFile_write(fileHandle : FantomHandle; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); cdecl; begin nFANTOM100_iFile_write(fileHandle, writeBuffer, writeBufferLength, status); end; procedure iFileIterator_advance(iterHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iFileIterator_advance(iterHandle, status); end; procedure iFileIterator_getName(iterHandle : FantomHandle; filename : PChar; var status : integer); cdecl; begin nFANTOM100_iFileIterator_getName(iterHandle, filename, status); end; procedure iModule_getName(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; begin nFANTOM100_iModule_getName(moduleHandle, moduleName, status); end; procedure iModuleIterator_advance(modIterHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iModuleIterator_advance(modIterHandle, status); end; procedure iModuleIterator_getName(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl; begin nFANTOM100_iModuleIterator_getName(modIterHandle, moduleName, status); end; procedure iNXT_bluetoothFactoryReset(nxtHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_bluetoothFactoryReset(nxtHandle, status); end; procedure iNXT_bootIntoFirmwareDownloadMode(resourceName : PChar; var status : integer); cdecl; begin nFANTOM100_iNXT_bootIntoFirmwareDownloadMode(resourceName, status); end; procedure iNXT_destroyFile(nxtHandle : FantomHandle; fileHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_destroyFile(nxtHandle, fileHandle, status); end; procedure iNXT_destroyFileIterator(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_destroyFileIterator(nxtHandle, iterHandle, status); end; procedure iNXT_destroyModule(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_destroyModule(nxtHandle, moduleHandle, status); end; procedure iNXT_destroyModuleIterator(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_destroyModule(nxtHandle, modIterHandle, status); end; procedure iNXT_downloadFirmware(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); cdecl; begin nFANTOM100_iNXT_downloadFirmware(nxtHandle, firmwareBuffer, firmwareBufferSize, status); end; procedure iNXT_eraseUserFlash(nxtHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXT_eraseUserFlash(nxtHandle, status); end; procedure iNXT_findDeviceInFirmwareDownloadMode(resString : PChar; var status : integer); cdecl; begin nFANTOM100_iNXT_findDeviceInFirmwareDownloadMode(resString, status); end; procedure iNXT_getDeviceInfo(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); cdecl; begin nFANTOM100_iNXT_getDeviceInfo(nxtHandle, name, address, signalStrength, availableFlash, status); end; procedure iNXT_getFirmwareVersion(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); cdecl; begin nFANTOM100_iNXT_getFirmwareVersion(nxtHandle, protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor, status); end; procedure iNXT_getResourceString(nxtHandle : FantomHandle; resString : PChar; var status : integer); cdecl; begin nFANTOM100_iNXT_getResourceString(nxtHandle, resString, status); end; procedure iNXT_read(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); cdecl; begin nFANTOM100_iNXT_read(nxtHandle, readBuffer, readBufferSize, status); end; procedure iNXT_sendDirectCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); cdecl; begin nFANTOM100_iNXT_sendDirectCommand(nxtHandle, requireResponse, inputBufferPtr, inputBufferSize, outputBufferPtr, outputBufferSize, status); end; procedure iNXT_setName(nxtHandle : FantomHandle; newName : PChar; var status : integer); cdecl; begin nFANTOM100_iNXT_setName(nxtHandle, newName, status); end; procedure iNXTIterator_advance(NXTIterHandle : FantomHandle; var status : integer); cdecl; begin nFANTOM100_iNXTIterator_advance(NXTIterHandle, status); end; procedure iNXTIterator_getName(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); cdecl; begin nFANTOM100_iNXTIterator_getName(NXTIterHandle, resString, status); end; procedure pairBluetooth(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); cdecl; begin nFANTOM100_pairBluetooth(resourceName, passkey, pairedResourceName, status); end; procedure unpairBluetooth(resourceName : PChar; var status : integer); cdecl; begin nFANTOM100_unpairBluetooth(resourceName, status); end; procedure FantomSDKClose; cdecl; begin // nFANTOM100_destroyNXT(nxtHandle, status); end; procedure FantomSDKInit; cdecl; begin // nFANTOM100_destroyNXT(nxtHandle, status); end; initialization FantomAPILoaded := True; end. bricktools/libusb.pas0000644000175000017500000005672611537752657014640 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit libusb; interface {$IFNDEF WIN32} {$MODE OBJFPC} {$LINKLIB usb} {$LINKLIB c} {$PACKRECORDS C} const LIBUSB_PATH_MAX = 4096; {$ELSE} {$A1} const LIBUSB_PATH_MAX = 512; {$ENDIF} const ENOSTAT = 4001; ENOPOOL = 4002; ENOFILE = 4003; EINVAL = 22; { USB spec information This is all stuff grabbed from various USB specs and is pretty much not subject to change } { Device and/or Interface Class codes } { for DeviceClass } const USB_CLASS_PER_INTERFACE = 0; USB_CLASS_AUDIO = 1; USB_CLASS_COMM = 2; USB_CLASS_HID = 3; USB_CLASS_PRINTER = 7; USB_CLASS_MASS_STORAGE = 8; USB_CLASS_HUB = 9; USB_CLASS_DATA = 10; USB_CLASS_VENDOR_SPEC = $ff; { Descriptor types } USB_DT_DEVICE = $01; USB_DT_CONFIG = $02; USB_DT_STRING = $03; USB_DT_INTERFACE = $04; USB_DT_ENDPOINT = $05; USB_DT_HID = $21; USB_DT_REPORT = $22; USB_DT_PHYSICAL = $23; USB_DT_HUB = $29; { Descriptor sizes per descriptor type } USB_DT_DEVICE_SIZE = 18; USB_DT_CONFIG_SIZE = 9; USB_DT_INTERFACE_SIZE = 9; USB_DT_ENDPOINT_SIZE = 7; { Audio extension } USB_DT_ENDPOINT_AUDIO_SIZE = 9; USB_DT_HUB_NONVAR_SIZE = 7; { All standard descriptors have these 2 fields in common } type PUSBDescriptorHeader = ^USBDescriptorHeader; USBDescriptorHeader = record bLength : Byte; bDescriptorType : Byte; end; { String descriptor } PUSBStringDescriptor = ^USBStringDescriptor; USBStringDescriptor = record bLength : Byte; bDescriptorType : Byte; wData : array[0..0] of Word; end; { HID descriptor } PUSBHIDDescriptor = ^USBHIDDescriptor; USBHIDDescriptor = record bLength : Byte; bDescriptorType : Byte; bcdHID : Word; bCountryCode : Byte; bNumDescriptors : Byte; end; { Endpoint descriptor } const USB_MAXENDPOINTS = 32; { Extra descriptors } type PUSBEndpointDescriptor = ^USBEndpointDescriptor; USBEndpointDescriptor = record bLength : Byte; bDescriptorType : Byte; bEndpointAddress : Byte; bmAttributes : Byte; wMaxPacketSize : Word; bInterval : Byte; bRefresh : Byte; bSynchAddress : Byte; extra : PByte; extralen : Longint; end; { in bEndpointAddress } const USB_ENDPOINT_ADDRESS_MASK = $0f; USB_ENDPOINT_DIR_MASK = $80; { in bmAttributes } USB_ENDPOINT_TYPE_MASK = $03; USB_ENDPOINT_TYPE_CONTROL = 0; USB_ENDPOINT_TYPE_ISOCHRONOUS = 1; USB_ENDPOINT_TYPE_BULK = 2; USB_ENDPOINT_TYPE_INTERRUPT = 3; { Interface descriptor } const USB_MAXINTERFACES = 32; type PUSBInterfaceDescriptor = ^USBInterfaceDescriptor; USBInterfaceDescriptor = record bLength : Byte; bDescriptorType : Byte; bInterfaceNumber : Byte; bAlternateSetting : Byte; bNumEndpoints : Byte; bInterfaceClass : Byte; bInterfaceSubClass : Byte; bInterfaceProtocol : Byte; iInterface : Byte; endpoint : PUSBEndpointDescriptor; extra : Pbyte; // extra descriptors extralen : Longint; end; const USB_MAXALTSETTING = 128; // hard limit type PUSB_Interface = ^USB_Interface; USB_Interface = record altsetting : PUSBInterfaceDescriptor; num_altsetting : Longint; end; { Configuration descriptor information.. } const USB_MAXCONFIG = 8; type PUSBConfigDescriptor = ^USBConfigDescriptor; USBConfigDescriptor = record bLength : Byte; bDescriptorType : Byte; wTotalLength : Word; bNumInterfaces : Byte; bConfigurationValue : Byte; iConfiguration : Byte; bmAttributes : Byte; MaxPower : Byte; TheInterface : PUSB_Interface; extra : Pbyte; { Extra descriptors } extralen : Longint; end; { Device descriptor } PUSBDeviceDescriptor = ^USBDeviceDescriptor; USBDeviceDescriptor = record bLength : Byte; bDescriptorType : Byte; bcdUSB : Word; bDeviceClass : Byte; bDeviceSubClass : Byte; bDeviceProtocol : Byte; bMaxPacketSize0 : Byte; idVendor : Word; idProduct : Word; bcdDevice : Word; iManufacturer : Byte; iProduct : Byte; iSerialNumber : Byte; bNumConfigurations : Byte; end; USBCtrlSetup = record bRequestType : Byte; bRequest : Byte; wValue : Word; wIndex : Word; wLength : Word; end; { Standard requests } const USB_REQ_GET_STATUS = $00; USB_REQ_CLEAR_FEATURE = $01; { 0x02 is reserved } USB_REQ_SET_FEATURE = $03; { 0x04 is reserved } USB_REQ_SET_ADDRESS = $05; USB_REQ_GET_DESCRIPTOR = $06; USB_REQ_SET_DESCRIPTOR = $07; USB_REQ_GET_CONFIGURATION = $08; USB_REQ_SET_CONFIGURATION = $09; USB_REQ_GET_INTERFACE = $0A; USB_REQ_SET_INTERFACE = $0B; USB_REQ_SYNCH_FRAME = $0C; USB_TYPE_STANDARD = $00 shl 5; USB_TYPE_CLASS = $01 shl 5; USB_TYPE_VENDOR = $02 shl 5; USB_TYPE_RESERVED = $03 shl 5; USB_RECIP_DEVICE = $00; USB_RECIP_INTERFACE = $01; USB_RECIP_ENDPOINT = $02; USB_RECIP_OTHER = $03; { Various libusb API related stuff } USB_ENDPOINT_IN = $80; USB_ENDPOINT_OUT = $00; { Error codes } USB_ERROR_BEGIN = 500000; type PUSBBus = ^USBBus; PPUSBDevice = ^PUSBDevice; PUSBDevice = ^USBDevice; USBDevice = record next : PUSBDevice; prev : PUSBDevice; filename : array[0..LIBUSB_PATH_MAX] of Char; bus : PUSBBus; descriptor : USBDeviceDescriptor; config : PUSBConfigDescriptor; dev : Pointer; devnum : Byte; num_children : Byte; children : PPUSBDevice; end; USBBus = record next : PUSBBus; prev : PUSBBus; dirname : array[0..LIBUSB_PATH_MAX] of Char; devices : PUSBDevice; location : Cardinal; root_dev : PUSBDevice; end; PUSBDevHandle = ^TUSBDevHandle; TUSBDevHandle = record end; {$IFNDEF WIN32} {$linklib usb} { Variables } var USBBusses : PUSBBus; cvar; external; { Function prototypes } function usb_open(dev:PUSBDevice):PUSBDevHandle; cdecl; external; function usb_close(dev:PUSBDevHandle):Longint; cdecl; external; function usb_get_string(dev : PUSBDevHandle; index : LongInt; langid : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; external; function usb_get_string_simple(dev : PUSBDevHandle; index : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; external; function usb_get_descriptor_by_endpoint(dev : PUSBDevHandle; ep : LongInt; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; external; function usb_get_descriptor(dev : PUSBDevHandle; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; external; function usb_bulk_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; external; function usb_bulk_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; external; function usb_interrupt_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; external; function usb_interrupt_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; external; function usb_control_msg(dev:PUSBDevHandle; requestType:Longint; request:Longint; value:Longint; index:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; external; function usb_set_configuration(dev:PUSBDevHandle; configuration:Longint):Longint; cdecl; external; function usb_claim_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; external; function usb_release_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; external; function usb_set_altinterface(dev:PUSBDevHandle; alternate:Longint):Longint; cdecl; external; function usb_resetep(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; external; function usb_clear_halt(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; external; function usb_reset(dev:PUSBDevHandle):Longint; cdecl; external; function usb_strerror:PChar; cdecl; external; procedure usb_init; cdecl; external; procedure usb_set_debug(level:Longint); cdecl; external; function usb_find_busses:Longint; cdecl; external; function usb_find_devices:Longint; cdecl; external; function usb_device(dev:PUSBDevHandle):PUSBDevice; cdecl; external; function usb_get_busses : PUSBBus; cdecl; external; (* function usb_install_service_np(); LongInt; cdecl; external; function usb_uninstall_service_np(); LongInt; cdecl; external; function usb_install_driver_np(inf_file : PChar) : LongInt; cdecl; external; function usb_get_version() : PUSBVersion; cdecl; external; typedef int ( *usb_isochronous_setup_async_t)(usb_dev_handle *dev, void **context, unsigned char ep, int pktsize); typedef int ( *usb_bulk_setup_async_t)(usb_dev_handle *dev, void **context, unsigned char ep); typedef int ( *usb_interrupt_setup_async_t)(usb_dev_handle *dev, void **context, unsigned char ep); typedef int ( *usb_submit_async_t)(void *context, char *bytes, int size); typedef int ( *usb_reap_async_t)(void *context, int timeout); typedef int ( *usb_free_async_t)(void **context); *) {$ELSE} function usb_open(dev:PUSBDevice):PUSBDevHandle; cdecl; function usb_close(dev:PUSBDevHandle):Longint; cdecl; function usb_get_string(dev : PUSBDevHandle; index : LongInt; langid : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; function usb_get_string_simple(dev : PUSBDevHandle; index : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; function usb_get_descriptor_by_endpoint(dev : PUSBDevHandle; ep : LongInt; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; function usb_get_descriptor(dev : PUSBDevHandle; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; function usb_bulk_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; function usb_bulk_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; function usb_interrupt_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; function usb_interrupt_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; function usb_control_msg(dev:PUSBDevHandle; requestType:Longint; request:Longint; value:Longint; index:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; function usb_set_configuration(dev:PUSBDevHandle; configuration:Longint):Longint; cdecl; function usb_claim_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; function usb_release_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; function usb_set_altinterface(dev:PUSBDevHandle; alternate:Longint):Longint; cdecl; function usb_resetep(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; function usb_clear_halt(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; function usb_reset(dev:PUSBDevHandle):Longint; cdecl; function usb_strerror:PChar; cdecl; procedure usb_init; cdecl; procedure usb_set_debug(level:Longint); cdecl; function usb_find_busses:Longint; cdecl; function usb_find_devices:Longint; cdecl; function usb_device(Dev:PUSBDevHandle):PUSBDevice; cdecl; function usb_get_busses : PUSBBus; cdecl; var LibUSBLoaded: Boolean = False; procedure UnloadLibUSB; {$ENDIF} implementation {$IFDEF WIN32} uses Windows; var _usb_open : function(dev:PUSBDevice):PUSBDevHandle; cdecl; _usb_close : function(dev:PUSBDevHandle):Longint; cdecl; _usb_get_string : function(dev : PUSBDevHandle; index : LongInt; langid : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; _usb_get_string_simple : function(dev : PUSBDevHandle; index : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; _usb_get_descriptor_by_endpoint : function(dev : PUSBDevHandle; ep : LongInt; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; _usb_get_descriptor : function(dev : PUSBDevHandle; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; _usb_bulk_write : function(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; _usb_bulk_read : function(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; _usb_interrupt_write : function(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; _usb_interrupt_read : function(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; _usb_control_msg : function(dev:PUSBDevHandle; requestType:Longint; request:Longint; value:Longint; index:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; _usb_set_configuration : function(dev:PUSBDevHandle; configuration:Longint):Longint; cdecl; _usb_claim_interface : function(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; _usb_release_interface : function(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; _usb_set_altinterface : function(dev:PUSBDevHandle; alternate:Longint):Longint; cdecl; _usb_resetep : function(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; _usb_clear_halt : function(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; _usb_reset : function(dev:PUSBDevHandle):Longint; cdecl; _usb_strerror : function : PChar; cdecl; _usb_init : procedure; cdecl; _usb_set_debug : procedure(level:Longint); cdecl; _usb_find_busses : function : Longint; cdecl; _usb_find_devices : function : Longint; cdecl; _usb_device : function(Dev:PUSBDevHandle):PUSBDevice; cdecl; _usb_get_busses : function : PUSBBus; cdecl; function usb_open(dev : PUSBDevice):PUSBDevHandle; cdecl; begin if Assigned(_usb_open) then Result := _usb_open(dev) else Result := nil; end; function usb_close(dev:PUSBDevHandle):Longint; cdecl; begin if Assigned(_usb_close) then Result := _usb_close(dev) else Result := -ENOFILE; end; function usb_get_string(dev : PUSBDevHandle; index : LongInt; langid : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; begin if Assigned(_usb_get_string) then Result := _usb_get_string(dev, index, langid, buf, buflen) else Result := -ENOFILE; end; function usb_get_string_simple(dev : PUSBDevHandle; index : LongInt; buf : PChar; buflen : Integer) : LongInt; cdecl; begin if Assigned(_usb_get_string_simple) then Result := _usb_get_string_simple(dev, index, buf, buflen) else Result := -ENOFILE; end; function usb_get_descriptor_by_endpoint(dev : PUSBDevHandle; ep : LongInt; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; begin if Assigned(_usb_get_descriptor_by_endpoint) then Result := _usb_get_descriptor_by_endpoint(dev, ep, _type, index, buf, size) else Result := -ENOFILE; end; function usb_get_descriptor(dev : PUSBDevHandle; _type : Byte; index : Byte; buf : Pointer; size : Integer) : LongInt; cdecl; begin if Assigned(_usb_get_descriptor) then Result := _usb_get_descriptor(dev, _type, index, buf, size) else Result := -ENOFILE; end; function usb_bulk_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; begin if Assigned(_usb_bulk_write) then Result := _usb_bulk_write(dev, ep, bytes, size, timeout) else Result := -ENOFILE; end; function usb_bulk_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; begin if Assigned(_usb_bulk_read) then Result := _usb_bulk_read(dev, ep, bytes, size, timeout) else Result := -ENOFILE; end; function usb_interrupt_write(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; begin if Assigned(_usb_interrupt_write) then Result := _usb_interrupt_write(dev, ep, bytes, size, timeout) else Result := -ENOFILE; end; function usb_interrupt_read(dev:PUSBDevHandle; ep:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; begin if Assigned(_usb_interrupt_read) then Result := _usb_interrupt_read(dev, ep, bytes, size, timeout) else Result := -ENOFILE; end; function usb_control_msg(dev:PUSBDevHandle; requestType:Longint; request:Longint; value:Longint; index:Longint; bytes:PChar; size:Longint; timeout:Longint):Longint; cdecl; begin if Assigned(_usb_control_msg) then Result := _usb_control_msg(dev, requestType, request, value, index, bytes, size, timeout) else Result := -ENOFILE; end; function usb_set_configuration(dev:PUSBDevHandle; configuration:Longint):Longint; cdecl; begin if Assigned(_usb_set_configuration) then Result := _usb_set_configuration(dev, configuration) else Result := -ENOFILE; end; function usb_claim_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; begin if Assigned(_usb_claim_interface) then Result := _usb_claim_interface(dev, TheInterface) else Result := -ENOFILE; end; function usb_release_interface(dev:PUSBDevHandle; TheInterface:Longint):Longint; cdecl; begin if Assigned(_usb_release_interface) then Result := _usb_release_interface(dev, TheInterface) else Result := -ENOFILE; end; function usb_set_altinterface(dev:PUSBDevHandle; alternate:Longint):Longint; cdecl; begin if Assigned(_usb_set_altinterface) then Result := _usb_set_altinterface(dev, alternate) else Result := -ENOFILE; end; function usb_resetep(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; begin if Assigned(_usb_resetep) then Result := _usb_resetep(dev, ep) else Result := -ENOFILE; end; function usb_clear_halt(dev:PUSBDevHandle; ep:Cardinal):Longint; cdecl; begin if Assigned(_usb_clear_halt) then Result := _usb_clear_halt(dev, ep) else Result := -ENOFILE; end; function usb_reset(dev:PUSBDevHandle):Longint; cdecl; begin if Assigned(_usb_reset) then Result := _usb_reset(dev) else Result := -ENOFILE; end; function usb_strerror:PChar; cdecl; begin if Assigned(_usb_strerror) then Result := _usb_strerror() else Result := nil; end; procedure usb_init; cdecl; begin if Assigned(_usb_init) then _usb_init(); end; procedure usb_set_debug(level:Longint); cdecl; begin if Assigned(_usb_set_debug) then _usb_set_debug(level); end; function usb_find_busses : Longint; cdecl; begin if Assigned(_usb_find_busses) then Result := _usb_find_busses() else Result := -ENOFILE; end; function usb_find_devices : Longint; cdecl; begin if Assigned(_usb_find_devices) then Result := _usb_find_devices() else Result := -ENOFILE; end; function usb_device(dev:PUSBDevHandle):PUSBDevice; cdecl; begin if Assigned(_usb_device) then Result := _usb_device(dev) else Result := nil; end; function usb_get_busses : PUSBBus; cdecl; begin if Assigned(_usb_get_busses) then Result := _usb_get_busses() else Result := nil; end; var SaveExit: pointer; DLLHandle: THandle; ErrorMode: Integer; procedure UnloadLibUSB; begin if LibUSBLoaded then begin if DLLHandle >= 32 then FreeLibrary(DLLHandle); LibUSBLoaded := False; end; end; procedure NewExit; //far; begin ExitProc := SaveExit; UnloadLibUSB; end; procedure LoadDLL; begin if LibUSBLoaded then Exit; ErrorMode := SetErrorMode($8000{SEM_NoOpenFileErrorBox}); DLLHandle := LoadLibrary('libusb0.dll'); if DLLHandle >= 32 then begin LibUSBLoaded := True; SaveExit := ExitProc; ExitProc := @NewExit; @_usb_open := GetProcAddress(DLLHandle, 'usb_open'); Assert(@_usb_open <> nil); @_usb_close := GetProcAddress(DLLHandle, 'usb_close'); Assert(@_usb_close <> nil); @_usb_get_string := GetProcAddress(DLLHandle, 'usb_get_string'); Assert(@_usb_get_string <> nil); @_usb_get_string_simple := GetProcAddress(DLLHandle, 'usb_get_string_simple'); Assert(@_usb_get_string_simple <> nil); @_usb_get_descriptor_by_endpoint := GetProcAddress(DLLHandle, 'usb_get_descriptor_by_endpoint'); Assert(@_usb_get_descriptor_by_endpoint <> nil); @_usb_get_descriptor := GetProcAddress(DLLHandle, 'usb_get_descriptor'); Assert(@_usb_get_descriptor <> nil); @_usb_bulk_write := GetProcAddress(DLLHandle, 'usb_bulk_write'); Assert(@_usb_bulk_write <> nil); @_usb_bulk_read := GetProcAddress(DLLHandle, 'usb_bulk_read'); Assert(@_usb_bulk_read <> nil); @_usb_interrupt_write := GetProcAddress(DLLHandle, 'usb_interrupt_write'); Assert(@_usb_interrupt_write <> nil); @_usb_interrupt_read := GetProcAddress(DLLHandle, 'usb_interrupt_read'); Assert(@_usb_interrupt_read <> nil); @_usb_control_msg := GetProcAddress(DLLHandle, 'usb_control_msg'); Assert(@_usb_control_msg <> nil); @_usb_set_configuration := GetProcAddress(DLLHandle, 'usb_set_configuration'); Assert(@_usb_set_configuration <> nil); @_usb_claim_interface := GetProcAddress(DLLHandle, 'usb_claim_interface'); Assert(@_usb_claim_interface <> nil); @_usb_release_interface := GetProcAddress(DLLHandle, 'usb_release_interface'); Assert(@_usb_release_interface <> nil); @_usb_set_altinterface := GetProcAddress(DLLHandle, 'usb_set_altinterface'); Assert(@_usb_set_altinterface <> nil); @_usb_resetep := GetProcAddress(DLLHandle, 'usb_resetep'); Assert(@_usb_resetep <> nil); @_usb_clear_halt := GetProcAddress(DLLHandle, 'usb_clear_halt'); Assert(@_usb_clear_halt <> nil); @_usb_reset := GetProcAddress(DLLHandle, 'usb_reset'); Assert(@_usb_reset <> nil); @_usb_strerror := GetProcAddress(DLLHandle, 'usb_strerror'); Assert(@_usb_strerror <> nil); @_usb_init := GetProcAddress(DLLHandle, 'usb_init'); Assert(@_usb_init <> nil); @_usb_set_debug := GetProcAddress(DLLHandle, 'usb_set_debug'); Assert(@_usb_set_debug <> nil); @_usb_find_busses := GetProcAddress(DLLHandle, 'usb_find_busses'); Assert(@_usb_find_busses <> nil); @_usb_find_devices := GetProcAddress(DLLHandle, 'usb_find_devices'); Assert(@_usb_find_devices <> nil); @_usb_device := GetProcAddress(DLLHandle, 'usb_device'); Assert(@_usb_device <> nil); @_usb_get_busses := GetProcAddress(DLLHandle, 'usb_get_busses'); Assert(@_usb_get_busses <> nil); end else begin LibUSBLoaded := False; { Error: libusb0.dll could not be loaded !! } end; SetErrorMode(ErrorMode) end; initialization LoadDLL; {$ENDIF} end. bricktools/FANTOM.pas0000644000175000017500000003746011537752657014336 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit fantom; interface uses FantomDefs; {$I FANTOM_CONST.INC} var createNXT : function(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; cdecl; createNXTIterator : function(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; cdecl; iFile_getAvailableSize : function(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iFile_getSize : function(fileHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iFileIterator_getFile : function(iterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; iFileIterator_getSize : function(fileIterHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iModule_getIOMapSize : function(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iModule_getModuleID : function(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iModule_getModuleSize : function(moduleHandle : FantomHandle; var status : integer) : Cardinal; cdecl; iModule_readIOMap : function(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; iModule_writeIOMap : function(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; cdecl; iModuleIterator_getModule : function(modIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; iNXT_createFile : function(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; cdecl; iNXT_createFileIterator : function(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; cdecl; iNXT_createModule : function(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; cdecl; iNXT_createModuleIterator : function(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; cdecl; iNXT_pollAvailableLength : function(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; cdecl; iNXT_readBufferData : function(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; cdecl; iNXT_write : function(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; cdecl; iNXTIterator_getNXT : function(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; cdecl; destroyNXT : procedure(nxtHandle : FantomHandle; var status : integer); cdecl; destroyNXTIterator : procedure(nxtIteratorHandle : FantomHandle; var status : integer); cdecl; iFile_close : procedure(fileHandle : FantomHandle; var status : integer); cdecl; iFile_getName : procedure(fileHandle : FantomHandle; filename : PChar; var status : integer); cdecl; iFile_openForDataAppend : procedure(fileHandle : FantomHandle; var status : integer); cdecl; iFile_openForDataWrite : procedure(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; iFile_openForLinearWrite : procedure(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); cdecl; iFile_openForRead : procedure(fileHandle : FantomHandle; var status : integer); cdecl; iFile_openForWrite : procedure(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); cdecl; iFile_read : procedure(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); cdecl; iFile_remove : procedure(fileHandle : FantomHandle; var status : integer); cdecl; iFile_write : procedure(fileHandle : Cardinal; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); cdecl; iFileIterator_advance : procedure(iterHandle : FantomHandle; var status : integer); cdecl; iFileIterator_getName : procedure(iterHandle : FantomHandle; filename : PChar; var status : integer); cdecl; iModule_getName : procedure(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl;// 20 bytes iModuleIterator_advance : procedure(modIterHandle : FantomHandle; var status : integer); cdecl; iModuleIterator_getName : procedure(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); cdecl;// 256 bytes iNXT_bluetoothFactoryReset : procedure(nxtHandle : FantomHandle; var status : integer); cdecl; iNXT_bootIntoFirmwareDownloadMode : procedure(resourceName : PChar; var status : integer); cdecl; iNXT_destroyFile : procedure(nxtHandle : FantomHandle; fileHandle : Cardinal; var status : integer); cdecl; iNXT_destroyFileIterator : procedure(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); cdecl; iNXT_destroyModule : procedure(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); cdecl; iNXT_destroyModuleIterator : procedure(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); cdecl; iNXT_downloadFirmware : procedure(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); cdecl; iNXT_eraseUserFlash : procedure(nxtHandle : FantomHandle; var status : integer); cdecl; iNXT_findDeviceInFirmwareDownloadMode : procedure(resString : PChar; var status : integer); cdecl; iNXT_getDeviceInfo : procedure(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); cdecl; iNXT_getFirmwareVersion : procedure(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); cdecl; iNXT_getResourceString : procedure(nxtHandle : FantomHandle; resString : PChar; var status : integer); cdecl;// 55 bytes iNXT_read : procedure(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); cdecl; iNXT_sendDirectCommand : procedure(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); cdecl; iNXT_setName : procedure(nxtHandle : FantomHandle; newName : PChar; var status : integer); cdecl; iNXTIterator_advance : procedure(NXTIterHandle : FantomHandle; var status : integer); cdecl; iNXTIterator_getName : procedure(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); cdecl;// 256 bytes pairBluetooth : procedure(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); cdecl;// 256 bytes unpairBluetooth : procedure(resourceName : PChar; var status : integer); cdecl; FantomSDKClose : procedure; cdecl; FantomSDKInit : procedure; cdecl; var FantomAPILoaded: Boolean = False; procedure UnloadFantomAPI; implementation uses Windows; var // SaveExit: pointer; DLLHandle: THandle; ErrorMode: Integer; procedure UnloadFantomAPI; begin if FantomAPILoaded then begin if DLLHandle >= 32 then FreeLibrary(DLLHandle); FantomAPILoaded := False; end; end; { procedure NewExit; far; begin ExitProc := SaveExit; UnloadFantomAPI; end; } procedure LoadDLL; begin if FantomAPILoaded then Exit; ErrorMode := SetErrorMode($8000{SEM_NoOpenFileErrorBox}); DLLHandle := LoadLibrary('FANTOM.DLL'); if DLLHandle >= 32 then begin FantomAPILoaded := True; // SaveExit := ExitProc; // ExitProc := @NewExit; @createNXT := GetProcAddress(DLLHandle, 'nFANTOM100_createNXT'); Assert(@createNXT <> nil); @createNXTIterator := GetProcAddress(DLLHandle, 'nFANTOM100_createNXTIterator'); Assert(@createNXTIterator <> nil); @iFile_getAvailableSize := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_getAvailableSize'); Assert(@iFile_getAvailableSize <> nil); @iFile_getSize := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_getSize'); Assert(@iFile_getSize <> nil); @iFileIterator_getFile := GetProcAddress(DLLHandle, 'nFANTOM100_iFileIterator_getFile'); Assert(@iFileIterator_getFile <> nil); @iFileIterator_getSize := GetProcAddress(DLLHandle, 'nFANTOM100_iFileIterator_getSize'); Assert(@iFileIterator_getSize <> nil); @iModule_getIOMapSize := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_getIOMapSize'); Assert(@iModule_getIOMapSize <> nil); @iModule_getModuleID := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_getModuleID'); Assert(@iModule_getModuleID <> nil); @iModule_getModuleSize := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_getModuleSize'); Assert(@iModule_getModuleSize <> nil); @iModule_readIOMap := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_readIOMap'); Assert(@iModule_readIOMap <> nil); @iModule_writeIOMap := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_writeIOMap'); Assert(@iModule_writeIOMap <> nil); @iModuleIterator_getModule := GetProcAddress(DLLHandle, 'nFANTOM100_iModuleIterator_getModule'); Assert(@iModuleIterator_getModule <> nil); @iNXT_createFile := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_createFile'); Assert(@iNXT_createFile <> nil); @iNXT_createFileIterator := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_createFileIterator'); Assert(@iNXT_createFileIterator <> nil); @iNXT_createModule := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_createModule'); Assert(@iNXT_createModule <> nil); @iNXT_createModuleIterator := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_createModuleIterator'); Assert(@iNXT_createModuleIterator <> nil); @iNXT_pollAvailableLength := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_pollAvailableLength'); Assert(@iNXT_pollAvailableLength <> nil); @iNXT_readBufferData := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_readBufferData'); Assert(@iNXT_readBufferData <> nil); @iNXT_write := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_write'); Assert(@iNXT_write <> nil); @iNXTIterator_getNXT := GetProcAddress(DLLHandle, 'nFANTOM100_iNXTIterator_getNXT'); Assert(@iNXTIterator_getNXT <> nil); @destroyNXT := GetProcAddress(DLLHandle, 'nFANTOM100_destroyNXT'); Assert(@destroyNXT <> nil); @destroyNXTIterator := GetProcAddress(DLLHandle, 'nFANTOM100_destroyNXTIterator'); Assert(@destroyNXTIterator <> nil); @iFile_close := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_close'); Assert(@iFile_close <> nil); @iFile_getName := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_getName'); Assert(@iFile_getName <> nil); @iFile_openForDataAppend := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_openForDataAppend'); Assert(@iFile_openForDataAppend <> nil); @iFile_openForDataWrite := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_openForDataWrite'); Assert(@iFile_openForDataWrite <> nil); @iFile_openForLinearWrite := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_openForLinearWrite'); Assert(@iFile_openForLinearWrite <> nil); @iFile_openForRead := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_openForRead'); Assert(@iFile_openForRead <> nil); @iFile_openForWrite := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_openForWrite'); Assert(@iFile_openForWrite <> nil); @iFile_read := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_read'); Assert(@iFile_read <> nil); @iFile_remove := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_remove'); Assert(@iFile_remove <> nil); @iFile_write := GetProcAddress(DLLHandle, 'nFANTOM100_iFile_write'); Assert(@iFile_write <> nil); @iFileIterator_advance := GetProcAddress(DLLHandle, 'nFANTOM100_iFileIterator_advance'); Assert(@iFileIterator_advance <> nil); @iFileIterator_getName := GetProcAddress(DLLHandle, 'nFANTOM100_iFileIterator_getName'); Assert(@iFileIterator_getName <> nil); @iModule_getName := GetProcAddress(DLLHandle, 'nFANTOM100_iModule_getName'); Assert(@iModule_getName <> nil); @iModuleIterator_advance := GetProcAddress(DLLHandle, 'nFANTOM100_iModuleIterator_advance'); Assert(@iModuleIterator_advance <> nil); @iModuleIterator_getName := GetProcAddress(DLLHandle, 'nFANTOM100_iModuleIterator_getName'); Assert(@iModuleIterator_getName <> nil); @iNXT_bluetoothFactoryReset := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_bluetoothFactoryReset'); Assert(@iNXT_bluetoothFactoryReset <> nil); @iNXT_bootIntoFirmwareDownloadMode := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_bootIntoFirmwareDownloadMode'); Assert(@iNXT_bootIntoFirmwareDownloadMode <> nil); @iNXT_destroyFile := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_destroyFile'); Assert(@iNXT_destroyFile <> nil); @iNXT_destroyFileIterator := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_destroyFileIterator'); Assert(@iNXT_destroyFileIterator <> nil); @iNXT_destroyModule := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_destroyModule'); Assert(@iNXT_destroyModule <> nil); @iNXT_destroyModuleIterator := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_destroyModuleIterator'); Assert(@iNXT_destroyModuleIterator <> nil); @iNXT_downloadFirmware := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_downloadFirmware'); Assert(@iNXT_downloadFirmware <> nil); @iNXT_eraseUserFlash := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_eraseUserFlash'); Assert(@iNXT_eraseUserFlash <> nil); @iNXT_findDeviceInFirmwareDownloadMode := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_findDeviceInFirmwareDownloadMode'); Assert(@iNXT_findDeviceInFirmwareDownloadMode <> nil); @iNXT_getDeviceInfo := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_getDeviceInfo'); Assert(@iNXT_getDeviceInfo <> nil); @iNXT_getFirmwareVersion := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_getFirmwareVersion'); Assert(@iNXT_getFirmwareVersion <> nil); @iNXT_getResourceString := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_getResourceString'); Assert(@iNXT_getResourceString <> nil); @iNXT_read := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_read'); Assert(@iNXT_read <> nil); @iNXT_sendDirectCommand := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_sendDirectCommand'); Assert(@iNXT_sendDirectCommand <> nil); @iNXT_setName := GetProcAddress(DLLHandle, 'nFANTOM100_iNXT_setName'); Assert(@iNXT_setName <> nil); @iNXTIterator_advance := GetProcAddress(DLLHandle, 'nFANTOM100_iNXTIterator_advance'); Assert(@iNXTIterator_advance <> nil); @iNXTIterator_getName := GetProcAddress(DLLHandle, 'nFANTOM100_iNXTIterator_getName'); Assert(@iNXTIterator_getName <> nil); @pairBluetooth := GetProcAddress(DLLHandle, 'nFANTOM100_pairBluetooth'); Assert(@pairBluetooth <> nil); @unpairBluetooth := GetProcAddress(DLLHandle, 'nFANTOM100_unpairBluetooth'); Assert(@unpairBluetooth <> nil); @FantomSDKClose := GetProcAddress(DLLHandle, 'sdk_close'); Assert(@FantomSDKClose <> nil); @FantomSDKInit := GetProcAddress(DLLHandle, 'sdk_init'); Assert(@FantomSDKInit <> nil); end else begin FantomAPILoaded := False; { Error: fantom.DLL could not be loaded !! } end; SetErrorMode(ErrorMode) end; initialization LoadDLL; finalization UnloadFantomAPI; end. bricktools/rcx_constants.pas0000644000175000017500000005512511537752657016240 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit rcx_constants; interface const // opcodes kRCX_PingOp = $10; kRCX_MemMapOp = $20; // not scout, not spybot kRCX_BatteryLevelOp = $30; // not scout kRCX_DeleteTasksOp = $40; // not spybot ? kRCX_StopAllOp = $50; kRCX_PBTurnOffOp = $60; kRCX_DeleteSubsOp = $70; // not spybot kRCX_ClearSound = $80; // rcx2 & spybot only kRCX_ClearMsgOp = $90; // not spybot kRCX_ExitAccessCtrlOp = $a0; // rcx2, scout, & spybot (program) kRCX_ExitEventChkOp = $b0; // rcx2, scout, & spybot (program) kRCX_LSCalibrateOp = $c0; // scout only kRCX_MuteSoundOp = $d0; // rcx2 & spybot only kRCX_UnmuteSoundOp = $e0; // rcx2 & spybot only // kRCX_UnknownOp = $f0; kRCX_PopStackEntryOp = $01; // spybot (program) kRCX_UploadEepromOp = $11; // spybot (direct) kRCX_ClearTachoOp = $11; // cybermaster only kRCX_OutputModeOp = $21; // not spybot kRCX_IRModeOp = $31; // not spybot kRCX_DriveOp = $41; // cybermaster only kRCX_PlaySoundOp = $51; kRCX_DeleteTaskOp = $61; // not spybot kRCX_StartTaskOp = $71; kRCX_StopTaskOp = $81; kRCX_SelectProgramOp = $91; // rcx only kRCX_ClearTimerOp = $a1; kRCX_AutoOffOp = $b1; kRCX_DeleteSubOp = $c1; // not spybot kRCX_ClearSensorOp = $d1; // not spybot kRCX_OutputDirOp = $e1; // kRCX_UnknownOp = $f1; kRCX_PlayToneVarOp = $02; kRCX_PollOp = $12; kRCX_SetWatchOp = $22; // not spybot kRCX_InputTypeOp = $32; // not spybot kRCX_InputModeOp = $42; kRCX_SetDatalogOp = $52; // rcx/rcx2 only kRCX_DatalogOp = $62; // rcx/rcx2 only kRCX_JumpOp = $72; // (program) kRCX_SetLoopOp = $82; // (program) not spybot kRCX_CheckLoopOp = $92; // (program) not spybot // kRCX_UnknownOp = $a2; kRCX_SendMessageOp = $b2; // (program) not spybot kRCX_SendUARTDataOp = $c2; // rcx2 & spybot only kRCX_OnWaitOp = $c2; // cybermaster only kRCX_Remote = $d2; // rcx2 & scout only kRCX_VLLOp = $e2; // scout & spybot kRCX_DecVarJmpLTZOp = $f2; // (program) kRCX_DirectEventOp = $03; kRCX_OutputPowerOp = $13; kRCX_PlayToneOp = $23; kRCX_DisplayOp = $33; // not spybot kRCX_WaitOp = $43; // (program) kRCX_OnWaitDifferentOp = $53; // cybermaster only kRCX_PollMemoryOp = $63; // rcx2, scout, and spybot kRCX_EnterAccessCtrlOp = $73; // rcx2, scout, and spybot (program) kRCX_SetFeedbackOp = $83; // scout kRCX_SetEventOp = $93; // rcx2 & spybot only kRCX_GOutputPowerOp = $a3; // rcx2, scout, & spybot kRCX_LSUpperThreshOp = $b3; // scout kRCX_LSLowerThreshOp = $c3; // scout kRCX_LSHysteresisOp = $d3; // scout kRCX_PushStackEntryOp = $e3; // spybot (program) kRCX_LSBlinkTimeOp = $e3; // scout kRCX_LDecVarJmpLTZOp = $f3; // (program) kRCX_CalibrateEventOp = $04; // rcx2 & spybot only kRCX_SetVarOp = $14; kRCX_SumVarOp = $24; kRCX_SubVarOp = $34; kRCX_DivVarOp = $44; kRCX_MulVarOp = $54; kRCX_SgnVarOp = $64; kRCX_AbsVarOp = $74; kRCX_AndVarOp = $84; kRCX_OrVarOp = $94; kRCX_UploadDatalogOp = $a4; // rcx/rcx2 only kRCX_SEnterEventChkOp = $b4; // rcx2, scout, & spybot (program) kRCX_SetTimerLimitOp = $c4; // scout kRCX_SetCounterOp = $d4; // scout // kRCX_UnknownOp = $e4; // kRCX_UnknownOp = $f4; kRCX_SetSourceValueOp = $05; kRCX_UnlockOp = $15; kRCX_BeginTaskOp = $25; // (program) not spybot kRCX_BeginSubOp = $35; // (program) not spybot kRCX_DownloadOp = $45; // (program) // kRCX_UnknownOp = $55; kRCX_BootModeOp = $65; // rcx/rcx2 only kRCX_BeginFirmwareOp = $75; // (program) kRCX_SCheckDoOp = $85; // (program) kRCX_LCheckDoOp = $95; // (program) kRCX_UnlockFirmOp = $a5; // not spybot kRCX_LEnterEventChkOp = $b5; // rcx2 & spybot only (program) // kRCX_UnknownOp = $c5; kRCX_FindOp = $d5; // spybot only kRCX_ScoutRulesOp = $d5; // scout kRCX_ViewSourceValOp = $e5; // rcx2 only // kRCX_UnknownOp = $f5; kRCX_ClearAllEventsOp = $06; // rcx2 & spybot only // kRCX_UnknownOp = $16; // kRCX_UnknownOp = $26; kRCX_ClearRelTableOp = $36; // spybot (program) // kRCX_UnknownOp = $46; // kRCX_UnknownOp = $56; // kRCX_UnknownOp = $66; // kRCX_UnknownOp = $76; // kRCX_UnknownOp = $86; // kRCX_UnknownOp = $96; // kRCX_UnknownOp = $a6; // kRCX_UnknownOp = $b6; // kRCX_UnknownOp = $c6; // kRCX_UnknownOp = $d6; // kRCX_UnknownOp = $e6; kRCX_EndOfSubOp = $F6; // (program) // kRCX_UnknownOp = $07; kRCX_GoSubOp = $17; // (program) kRCX_SJumpOp = $27; // (program) kRCX_SChkLoopCtrOp = $37; // (program) not spybot? kRCX_ScoutOp = $47; // scout only kRCX_SoundOp = $57; // scout only kRCX_GOutputModeOp = $67; // rcx2, scout, & spybot kRCX_GOutputDirOp = $77; // rcx2, scout, & spybot kRCX_LightOp = $87; // scout & spybot kRCX_IncCounterOp = $97; // rcx2, scout, & spybot kRCX_DecCounterOp = $a7; // rcx2, scout, & spybot kRCX_ClearCounterOp = $b7; // rcx2, scout, & spybot kRCX_PlaySysMoodOp = $c7; // spybot only kRCX_SetPriorityOp = $d7; // rcx2, scout, & spybot (program) kRCX_PlaySysSndVarOp = $e7; // spybot only kRCX_Message = $f7; // not spybot // output mode kRCX_OutputFloat = 0; kRCX_OutputOff = $40; kRCX_OutputOn = $80; // output direction kRCX_OutputBackward = 0; kRCX_OutputToggle = $40; kRCX_OutputForward = $80; const kNXT_VMState_Idle = 0; kNXT_VMState_RunFree = 1; kNXT_VMState_Single = 2; kNXT_VMState_Pause = 3; kNXT_VMState_Reset = 4; // NXT constants kNXT_NoResponseMask = $80; kNXT_DirectCmd = $00; kNXT_SystemCmd = $01; kNXT_CmdReply = $02; kNXT_DirectCmdNoReply = $80; kNXT_SystemCmdNoReply = $81; kNXT_MaxBytes = 64; kNXT_NameMaxLen = 15; // NXT direct commands kNXT_DCStartProgram = $00; kNXT_DCStopProgram = $01; kNXT_DCPlaySoundFile = $02; kNXT_DCPlayTone = $03; kNXT_DCSetOutputState = $04; kNXT_DCSetInputMode = $05; kNXT_DCGetOutputState = $06; kNXT_DCGetInputValues = $07; kNXT_DCResetInputScaledValue = $08; kNXT_DCMessageWrite = $09; kNXT_DCResetMotorPosition = $0A; kNXT_DCGetBatteryLevel = $0B; kNXT_DCStopSoundPlayback = $0C; kNXT_DCKeepAlive = $0D; kNXT_DCLSGetStatus = $0E; kNXT_DCLSWrite = $0F; kNXT_DCLSRead = $10; kNXT_DCGetCurrentProgramName = $11; kNXT_DCGetButtonState = $12; kNXT_DCMessageRead = $13; kNXT_DCReserved1 = $14; kNXT_DCReserved2 = $15; kNXT_DCReserved3 = $16; kNXT_DCReserved4 = $17; kNXT_DCReserved5 = $18; kNXT_DCDatalogRead = $19; kNXT_DCDatalogSetTimes = $1a; kNXT_DCBTGetContactCount = $1b; kNXT_DCBTGetContactName = $1c; kNXT_DCBTGetConnectionCount = $1d; kNXT_DCBTGetConnectionName = $1e; kNXT_DCSetProperty = $1f; kNXT_DCGetProperty = $20; kNXT_DCUpdateResetCount = $21; kNXT_DCSetVMState = $22; kNXT_DCGetVMState = $23; kNXT_DCSetBreakpoints = $24; kNXT_DCGetBreakpoints = $25; kNXT_Property_BTOnOff = $0; kNXT_Property_SoundLevel = $1; kNXT_Property_SleepTimeout = $2; kNXT_Property_Undefined1 = $3; kNXT_Property_Undefined2 = $4; kNXT_Property_Undefined3 = $5; kNXT_Property_Undefined4 = $6; kNXT_Property_Undefined5 = $7; kNXT_Property_Undefined6 = $8; kNXT_Property_Undefined7 = $9; kNXT_Property_Undefined8 = $a; kNXT_Property_Undefined9 = $b; kNXT_Property_Undefined10 = $c; kNXT_Property_Undefined11 = $d; kNXT_Property_Undefined12 = $e; kNXT_Property_Debugging = $f; // NXT system commands kNXT_SCOpenRead = $80; kNXT_SCOpenWrite = $81; kNXT_SCRead = $82; kNXT_SCWrite = $83; kNXT_SCClose = $84; kNXT_SCDelete = $85; kNXT_SCFindFirst = $86; kNXT_SCFindNext = $87; kNXT_SCGetVersions = $88; kNXT_SCOpenWriteLinear = $89; kNXT_SCOpenReadLinear = $8A; kNXT_SCOpenWriteData = $8B; kNXT_SCOpenAppendData = $8C; kNXT_SCUnknown1 = $8D; kNXT_SCUnknown2 = $8E; kNXT_SCUnknown3 = $8F; kNXT_SCFindFirstModule = $90; kNXT_SCFindNextModule = $91; kNXT_SCCloseModuleHandle = $92; kNXT_SCUnknown4 = $93; kNXT_SCIOMapRead = $94; kNXT_SCIOMapWrite = $95; kNXT_SCUnknown5 = $96; kNXT_SCBootCommand = $97; kNXT_SCSetBrickName = $98; kNXT_SCUnknown6 = $99; kNXT_SCGetBTAddress = $9A; kNXT_SCGetDeviceInfo = $9B; kNXT_SCUnknown7 = $9C; kNXT_SCUnknown8 = $9D; kNXT_SCUnknown9 = $9E; kNXT_SCUnknown10 = $9F; kNXT_SCDeleteUserFlash = $A0; kNXT_SCPollCommandLen = $A1; kNXT_SCPollCommand = $A2; kNXT_SCRenameFile = $A3; kNXT_SCBTFactoryReset = $A4; // NXT status codes kNXT_StatusSuccess = $00; kNXT_StatusNoMoreHandles = $81; kNXT_StatusNoSpace = $82; kNXT_StatusNoMoreFiles = $83; kNXT_StatusEOFExpected = $84; kNXT_StatusEOF = $85; kNXT_StatusNotLinearFile = $86; kNXT_StatusFileNotFound = $87; kNXT_StatusHandleClosed = $88; kNXT_StatusNoLinearSpace = $89; kNXT_StatusUndefinedErr = $8a; kNXT_StatusFileIsBusy = $8b; kNXT_StatusNoWriteBufs = $8c; kNXT_StatusAppendNotPoss = $8d; kNXT_StatusFileIsFull = $8e; kNXT_StatusFileExists = $8f; kNXT_StatusModuleNotFound = $90; kNXT_StatusOutOfBoundary = $91; kNXT_StatusIllegalFilname = $92; kNXT_StatusIllegalHandle = $93; const NXT_MODULE_COUNT = 12; // NXT modules type ID (TT) kNXT_TT_Cmd = $01; kNXT_TT_Output = $02; kNXT_TT_Input = $03; kNXT_TT_Button = $04; kNXT_TT_Comm = $05; kNXT_TT_IOCtrl = $06; kNXT_TT_Led = $07; kNXT_TT_Sound = $08; kNXT_TT_Loader = $09; kNXT_TT_Display = $0A; kNXT_TT_LowSpeed = $0B; kNXT_TT_UI = $0C; // Module programmer ID (PP) kNXT_PidLEGOGroup = $01; // module IDs are // PP TT CC FF (MSB..LSB) // programmer Id, module ID (above), coarse version, fine version // e.g., $01 $03 $01 $14 == TLG, Input, 1.14 kNXT_ModuleCmd = $00010001; kNXT_ModuleOutput = $00020001; kNXT_ModuleInput = $00030001; kNXT_ModuleButton = $00040001; kNXT_ModuleComm = $00050001; kNXT_ModuleIOCtrl = $00060001; kNXT_ModuleLed = $00070001; kNXT_ModuleSound = $00080001; kNXT_ModuleLoader = $00090001; kNXT_ModuleDisplay = $000A0001; kNXT_ModuleLowSpeed = $000B0001; kNXT_ModuleUI = $000C0001; const NXT_CMD_RESPONSE_LENGTH : array[0..$ff] of byte = ( 3, // DCStartProgram (x00) 3, // DCStopProgram (x01) 3, // DCPlaySoundFile (x02) 3, // DCPlayTone (x03) 3, // DCSetOutputState (x04) 3, // DCSetInputMode (x05) 25, // DCGetOutputState (x06) 16, // DCGetInputValues (x07) 3, // DCResetInputScaledValue (x08) 3, // DCMessageWrite (x09) 3, // DCResetMotorPosition (x0a) 5, // DCGetBatteryLevel (x0b) 3, // DCStopSoundPlayback (x0c) 7, // DCKeepAlive (x0d) 4, // DCLSGetStatus (x0e) 3, // DCLSWrite (x0f) 20, // DCLSRead (x10) 23, // DCGetCurrentProgramName (x11) 0, // DCGetButtonState (not implemented) (x12) 64, // DCMessageRead (x13) 0, // DCRESERVED1 (x14) 0, // DCRESERVED2 (x15) 0, // DCRESERVED3 (x16) 0, // DCRESERVED4 (x17) 0, // DCRESERVED5 (x18) 64, // DCDatalogRead (1.28+) (x19) 3, // DCDatalogSetTimes (1.28+) (x1a) 4, // DCBTGetContactCount (1.28+) (x1b) 21, // DCBTGetContactName (1.28+) (x1c) 4, // DCBTGetConnCount (1.28+) (x1d) 21, // DCBTGetConnName (1.28+) (x1e) 3, // DCSetProperty(1.28+) (x1f) 7, // DCGetProperty (1.28+) (x20) 3, // DCUpdateResetCount (1.28+) (x21) 7, // RC_SET_VM_STATE (enhanced only) (x22) 7, // RC_GET_VM_STATE (enhanced only) (x23) 15, // RC_SET_BREAKPOINTS (enhanced only) (x24) 15, // RC_GET_BREAKPOINTS (enhanced only) (x25) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x26-x2f) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x30-x3f) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x40-x4f) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x50-x5f) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x60-x6f) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (x70-x7f) 8, // OPENREAD = 0x80, 4, // OPENWRITE = 0x81, 64, // READ = 0x82, (actually is a variable length response) 6, // WRITE = 0x83, 4, // CLOSE = 0x84, 23, // DELETE = 0x85, 28, // FINDFIRST = 0x86, 28, // FINDNEXT = 0x87, 7, // VERSIONS = 0x88, 4, // OPENWRITELINEAR = 0x89, 7, // OPENREADLINEAR = 0x8A, (not actually implemented) 4, // OPENWRITEDATA = 0x8B, 8, // OPENAPPENDDATA = 0x8C, 4, // CROPDATAFILE = 0x8D, /* New cmd for datalogging */ 0, // XXXXXXXXXXXXXX = 0x8E, 0, // XXXXXXXXXXXXXX = 0x8F, 34, // FINDFIRSTMODULE = 0x90, 34, // FINDNEXTMODULE = 0x91, 4, // CLOSEMODHANDLE = 0x92, 0, // XXXXXXXXXXXXXX = 0x93, 64, // IOMAPREAD = 0x94, (actually is a variable length response) 9, // IOMAPWRITE = 0x95, 0, // XXXXXXXXXXXXXX = 0x96, 7, // BOOTCMD = 0x97, (can only be executed via USB) 3, // SETBRICKNAME = 0x98, 0, // XXXXXXXXXXXXXX = 0x99, 10, // BTGETADR = 0x9A, 33, // DEVICEINFO = 0x9B, 0, // XXXXXXXXXXXXXX = 0x9C, 0, // XXXXXXXXXXXXXX = 0x9D, 0, // XXXXXXXXXXXXXX = 0x9E, 0, // XXXXXXXXXXXXXX = 0x9F, 3, // DELETEUSERFLASH = 0xA0, 5, // POLLCMDLEN = 0xA1, 64, // POLLCMD = 0xA2, 44, // RENAMEFILE = 0xA3, 3, // BTFACTORYRESET = 0xA4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (xA5-xAF) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (xB0-xBf) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (xC0-xCf) 0, // RESIZEDATAFILE = 0xD0, 0, // SEEKFROMSTART = 0xD1, 0, // SEEKFROMCURRENT = 0xD2, 0, // SEEKFROMEND = 0xD3 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (xD4-xDF) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // (xE0-xEF) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // (xF0-xFF) ); const kNXT_ModuleCmdName = 'Command.mod'; kNXT_ModuleOutputName = 'Output.mod'; kNXT_ModuleInputName = 'Input.mod'; kNXT_ModuleButtonName = 'Button.mod'; kNXT_ModuleCommName = 'Comm.mod'; kNXT_ModuleIOCtrlName = 'IOCtrl.mod'; kNXT_ModuleLedName = 'Led.mod'; kNXT_ModuleSoundName = 'Sound.mod'; kNXT_ModuleLoaderName = 'Loader.mod'; kNXT_ModuleDisplayName = 'Display.mod'; kNXT_ModuleLowSpeedName = 'Low Speed.mod'; kNXT_ModuleUIName = 'Ui.mod'; type TNXTModule = record ID : Cardinal; Name : String; end; const NXTModuleMap : array[0..NXT_MODULE_COUNT-1] of TNXTModule = ( (ID: kNXT_ModuleCmd; Name: kNXT_ModuleCmdName), (ID: kNXT_ModuleOutput; Name: kNXT_ModuleOutputName), (ID: kNXT_ModuleInput; Name: kNXT_ModuleInputName), (ID: kNXT_ModuleButton; Name: kNXT_ModuleButtonName), (ID: kNXT_ModuleComm; Name: kNXT_ModuleCommName), (ID: kNXT_ModuleIOCtrl; Name: kNXT_ModuleIOCtrlName), (ID: kNXT_ModuleLed; Name: kNXT_ModuleLedName), (ID: kNXT_ModuleSound; Name: kNXT_ModuleSoundName), (ID: kNXT_ModuleLoader; Name: kNXT_ModuleLoaderName), (ID: kNXT_ModuleDisplay; Name: kNXT_ModuleDisplayName), (ID: kNXT_ModuleLowSpeed; Name: kNXT_ModuleLowSpeedName), (ID: kNXT_ModuleUI; Name: kNXT_ModuleUIName) ); type // Value type TRcxValueType = 0..63; const kRCX_VariableType = 0; kRCX_TimerType = 1; kRCX_ConstantType = 2; kRCX_OutputStatusType = 3; kRCX_RandomType = 4; kRCX_TachCounterType = 5; // cybermaster only kRCX_TachSpeedType = 6; // cybermaster only kRCX_OutputCurrentType = 7; // cybermaster only kRCX_MotorPowerSignedType = 5; // swan only kRCX_IntrinsicIndGlobalType = 6; // swan only kRCX_MotorBrakePowerType = 7; // swan only kRCX_ProgramSlotType = 8; // RCX only kRCX_InputValueType = 9; kRCX_InputTypeType = 10; // not spybot kRCX_InputModeType = 11; // not scout kRCX_InputRawType = 12; kRCX_InputBooleanType = 13; // not spybot, not scout kRCX_WatchType = 14; // RCX only kRCX_MessageType = 15; // spybot = VLL // all sources beyond 15 are not present in RCX and Cybermaster kRCX_AGCType = 16; // cybermaster only kRCX_MotorPower128Type = 16; // swan only kRCX_GlobalMotorStatusType = 17; // not RCX or CM kRCX_ScoutRulesType = 18; // scout only kRCX_ScoutLightParamsType = 19; // scout only kRCX_ScoutTimerLimitType = 20; // scout only kRCX_SpybotStackType = 18; // spybot only kRCX_SpybotTimerCtrlType = 19; // spybot only kRCX_SpybotEepromType = 20; // spybot only kRCX_EventTypeType = 18; // swan only kRCX_EventType = 19; // swan only kRCX_EventCountsType = 20; // swan only kRCX_CounterType = 21; // RCX2, scout, & spybot only kRCX_ScoutCounterLimitType = 22; // scout only kRCX_SpybotLEDType = 22; // spybot only kRCX_1MSTimerType = 22; // swan only kRCX_TaskEventsType = 23; // rcx2, scout, spybot kRCX_ScoutEventFBType = 24; // scout only kRCX_SystemType = 24; // swan only kRCX_EventStateType = 25; // rcx2 & spybot kRCX_TenMSTimerType = 26; // rcx2 & spybot fast timer kRCX_ClickCounterType = 27; // rcx2 kRCX_UpperThresholdType = 28; // rcx2 & spybot kRCX_LowerThresholdType = 29; // rcx2 & spybot kRCX_HysteresisType = 30; // rcx2 & spybot kRCX_DurationType = 31; // rcx2 & spybot kRCX_SpybotTaskIDType = 32; // spybot only kRCX_MotorPower8Type = 32; // swan only kRCX_UARTSetupType = 33; // rcx2 & spybot kRCX_BatteryLevelType = 34; // rcx2 & spybot kRCX_FirmwareVersionType = 35; // rcx2 & spybot kRCX_IndirectVarType = 36; // rcx2 & spybot kRCX_DatalogTypeIndirectType = 37; kRCX_DatalogTypeDirectType = 38; kRCX_DatalogValueIndirectType = 39; kRCX_DatalogValueDirectType = 40; kRCX_DatalogRawIndirectType = 41; kRCX_DatalogRawDirectType = 42; kRCX_SpybotGameNotesType = 43; // spybot only kRCX_SpybotRobotDistType = 45; // spybot only kRCX_SpybotRobotDirType = 46; // spybot only kRCX_SpybotRobotOrientType = 47; // spybot only kRCX_SpybotRobotIDType = 49; // spybot only kRCX_SpybotRobotTargetType = 50; // spybot only kRCX_SpybotPingCtrlType = 51; // spybot only kRCX_SpybotBeaconCtrlType = 52; // spybot only kRCX_SpybotSoundCtrlType = 53; // spybot only kRCX_SpybotIndEepromType = 54; // spybot only kRCX_GlobalVarType = 43; // swan only kRCX_IndirectGlobalIntType = 44; // swan only kRCX_IndexedGlobalConstType = 47; // swan only kRCX_StackVarType = 49; // swan only kRCX_ConstantVarType = 50; // swan only kRCX_FunctionRetValWordType = 51; // swan only kRCX_VarByteType = 54; // swan only kRCX_VarWordType = 55; // swan only kRCX_TaskStackVarByteType = 57; // swan only kRCX_TaskStackVarWordType = 58; // swan only kRCX_TaskVarType = 60; // swan only kRCX_TaskStackAddressType = 61; // swan only kRCX_TaskStackSizeType = 62; // swan only const // kRCX_ValueUsesTemp = $1000000; // input mode kRCX_InputRaw = 0; kRCX_InputBoolean = $20; kRCX_InputEdgeCounter = $40; kRCX_InputPeriodicCounter = $60; kRCX_InputPercentage = $80; kRCX_InputCelcius = $a0; kRCX_InputFahrenheit = $c0; kRCX_InputAngle = $e0; type // input type TRcxInputType = (kRCX_InputNone, kRCX_InputSwitch, kRCX_InputTemp, kRCX_InputLight, kRCX_InputRotation, kRCX_InputID0, kRCX_InputID1, kRCX_InputID2); // rcx relation TRcxRelation = (kRCX_LessOrEqual, kRCX_GreaterOrEqual, kRCX_NotEqualTo, kRCX_EqualTo); const kRCX_OK = 0; kRCX_OpenSerialError = -1; // serial port could not be opened and/or configured kRCX_IREchoError = -2; // no echo received from IR tower kRCX_ReplyError = -3; // no (or invalid) reply from RCX kRCX_RequestError = -4; // attempt to send too much data kRCX_FileError = -5; // could not open/read/write file kRCX_FormatError = -6; // unknown file format kRCX_AbortError = -7; // canceled by RCX_Link::DownloadProgress() kRCX_MemFullError = -8; // not enough room in RCX program memory kRCX_PipeModeError = -9; // pipe mode error kRCX_LastError = -9; // last error code implementation end. bricktools/FantomSpirit.pas0000644000175000017500000035703711537752657015776 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit FantomSpirit; interface uses Classes, SysUtils, rcx_cmd, uSpirit, uNXTConstants, FantomDefs; type TFantomSpirit = class(TBrickComm) private fResPort : string; fNXTHandle : FantomHandle; fResourceNames : TStrings; // fNXTFileHandle : FantomHandle; // fNXTFileIteratorHandle : FantomHandle; dcResponse : array [0..63] of byte; function TransferFirmware(aStream: TStream): boolean; protected function GetDownloadWaitTime: Integer; override; function GetEEPROM(addr: Byte): Byte; override; function GetEEPROMBlock(idx: Integer): EEPROMBlock; override; function GetIsOpen: boolean; override; function GetLSBlock(aPort: byte): NXTLSBlock; override; function GetFullPortName: string; override; function GetNicePortName: string; override; function GetOmitHeader: Boolean; override; function GetPortName: string; override; function GetQuiet: Boolean; override; function GetRCXFirmwareChunkSize: Integer; override; function GetRxTimeout: Word; override; function GetLinkLog: string; override; function GetUseBT: Boolean; override; procedure SetDownloadWaitTime(const Value: Integer); override; procedure SetEEPROM(addr: Byte; const Value: Byte); override; procedure SetLSBlock(aPort: byte; const Value: NXTLSBlock); override; procedure SetOmitHeader(const Value: Boolean); override; procedure SetPort(const Value: string); override; procedure SetQuiet(const Value: Boolean); override; procedure SetRCXFirmwareChunkSize(const Value: Integer); override; procedure SetRxTimeout(const Value: Word); override; protected function dcBuffer: PByte; function GetReplyByte(index: integer): Byte; function GetReplyCardinal(index: integer): Cardinal; function GetReplyWord(index: integer): Word; procedure SetResourcePort(const name : string); procedure LookupResourceName; function InternalNXTUploadFileToStream(handle : FantomHandle; const name : string; const totalSize, availSize : cardinal; aStream : TStream) : boolean; procedure LookupOffsetsIfNeeded; function GetNXTVariableHelper(aNum, aIdx, aCount, aDigits : integer) : variant; function GetVariantFromByteArray(dst : TDSType; buf : array of byte; idx : integer) : variant; public constructor Create(aType : byte = 0; const aPort : string = ''); override; destructor Destroy; override; function Open : boolean; override; function Close : boolean; override; // PBrick sound commands function PlayTone(aFreq, aTime : word) : boolean; override; function PlaySystemSound(aSnd : byte) : boolean; override; // PBrick output control commands function MotorsOn(aMotorList : Byte) : boolean; override; function MotorsOff(aMotorList : Byte) : boolean; override; function MotorsFloat(aMotorList : Byte) : boolean; override; function SetFwd(aMotorList : Byte) : boolean; override; function SetRwd(aMotorList : Byte) : boolean; override; function SwitchDirection(aMotorList : Byte) : boolean; override; function SetMotorPower(aMotorList : Byte; aSrc, aNum : integer) : boolean; override; // PBrick input control commands function SetSensorType(aNum, aType : integer) : boolean; override; function SetSensorMode(aNum, aMode, aSlope : integer) : boolean; override; function ClearSensorValue(aNum : integer) : boolean; override; // general function TowerExists : boolean; override; function Ping : boolean; override; function PrepareBrick : boolean; override; function UnlockFirmware : boolean; override; function UnlockBrick : string; override; function DownloadMemoryMap : TStrings; override; function MonitorIR(aSeconds: integer): TStrings; override; function PowerDownTime(aTime : integer) : boolean; override; function BatteryLevel : integer; override; function BrickAlive : boolean; override; function Shutdown : boolean; override; function Sleep(aVal : integer) : boolean; override; function Version(var rom : Cardinal; var ram : Cardinal) : boolean; override; function TransmitPower(aLevel : TTransmitLevel) : boolean; override; function Poll(aSrc, aNum : integer) : variant; override; function StartTask(aTask : integer) : boolean; override; function StopTask(aTask : integer) : boolean; override; function StopAllTasks : boolean; override; function DeleteTask(aTask : integer) : boolean; override; function DeleteAllTasks : boolean; override; function DeleteSub(aSub : integer) : boolean; override; function DeleteAllSubs : boolean; override; function ClearTimer(aNum : integer) : boolean; override; function ClearMemory : boolean; override; function GetOutputStatus(aOut : integer) : integer; override; function GetVariableValue(aVar: integer): variant; override; function GetInputValue(aIn: integer): integer; override; function GetMessageValue(aNum : integer) : integer; override; function GetTimerValue(aNum : integer) : integer; override; function GetCounterValue(aNum : integer) : integer; override; // PBrick arithmetic/logical commands function SetVar(aVar, aSrc, aNum : integer) : boolean; override; function SumVar(aVar, aSrc, aNum : integer) : boolean; override; function SubVar(aVar, aSrc, aNum : integer) : boolean; override; function DivVar(aVar, aSrc, aNum : integer) : boolean; override; function MulVar(aVar, aSrc, aNum : integer) : boolean; override; function SgnVar(aVar, aSrc, aNum : integer) : boolean; override; function AbsVar(aVar, aSrc, aNum : integer) : boolean; override; function AndVar(aVar, aSrc, aNum : integer) : boolean; override; function OrVar(aVar, aSrc, aNum : integer) : boolean; override; // communication to brick function SendRawCommand(aCmd : string; bRetry : boolean) : string; override; function SendRemoteStr(aEvent : string; aRepeat : integer = 1) : boolean; override; function SendRemote(aEvent : Word; aRepeat : integer = 1) : boolean; override; function SendMessage(aMsg : integer) : boolean; override; // RCX/2 only function SelectProgram(aProg : integer) : boolean; override; function SelectDisplay(aSrc, aNumber : integer) : boolean; override; function SetWatchHHMM(aHrs, aMins : integer) : boolean; override; function SetWatch(aTime : string) : boolean; override; function DownloadFirmware(aFile : string; bFast, bComp, bUnlock : boolean) : boolean; override; function SetDatalog(aSize : integer) : boolean; override; function DatalogNext(aSrc, aNum : integer) : boolean; override; function UploadPartialDatalog(aFrom, aSize : integer) : TStrings; override; function UploadDatalog(bVerbose : boolean) : TStrings; override; // CM only methods function Drive(aLeft, aRight : integer) : boolean; override; function ClearTachoCounter(aMotorList : Byte) : boolean; override; function OnWait(aMotorList : Byte; aNum : integer; aTime : Byte) : boolean; override; function OnWaitDifferent(aMotorList : Byte; aNum0, aNum1, aNum2 : integer; aTime : Byte) : boolean; override; // Scout only methods function ScoutNum(aVal : integer) : boolean; override; function Scout(bPower : boolean = true) : boolean; override; function CalibrateLightSensor : boolean; override; function SetFeedback(src, val : integer) : boolean; override; function SetLightSensorUpperThreshold(src : TLSSource; val : TThresholdValue) : boolean; override; function SetLightSensorLowerThreshold(src : TLSSource; val : TThresholdValue) : boolean; override; function SetLightSensorHysteresis(src : TLSSource; val : TThresholdValue) : boolean; override; function SetLightSensorBlinkTime(src : TLSSource; val : TBlinkTimeValue) : boolean; override; function SetTimerLimit(num : TTimerNumber; src : TTCSource; val : integer) : boolean; override; function SetCounterLimit(num : TCounterNumber; src : TTCSource; val : integer) : boolean; override; function ScoutRules(motion : TScoutMotion; touch : TScoutTouch; light : TScoutLight; time : TScoutScale; fx : TScoutEffects) : boolean; override; function ScoutSound(bSoundEnable : boolean; bSoundOff : boolean; aNum : TSoundSetNumber) : boolean; override; // Scout & Spybot only methods function SendVLL(aSrc, aNum : integer) : boolean; override; function SetLight(bOn : boolean) : boolean; override; // RCX2, Scout, & Spybot methods function PollMemory(address : Integer; size : Integer = 128) : TStrings; override; function SetGlobalOutput(motors : TMotorsNum; action : TGlobalOutAction) : boolean; override; function SetGlobalDirection(motors : TMotorsNum; action : TGlobalDirAction) : boolean; override; function SetMaxPower(motors : TMotorsNum; src, num : integer) : boolean; override; function IncCounter(num : TCounterNumber) : boolean; override; function DecCounter(num : TCounterNumber) : boolean; override; function ClearCounter(num : TCounterNumber) : boolean; override; // RCX2 & spybot only methods function ClearSound : boolean; override; function UnmuteSound : boolean; override; function SendUARTData(start, size : integer) : boolean; override; function SetEvent(enum, snum, etype : integer) : boolean; override; function CalibrateEvent(enum, upper, lower, hysteresis : integer) : boolean; override; function ClearAllEvents : boolean; override; function SetSourceValue(aDestSrc, aDestVal, aOrigSrc: Byte; aOrigVal: Smallint): boolean; override; // RCX2, Spy, & NXT function MuteSound : boolean; override; // RCX2 only methods function ViewSourceValue(prec, src, value : integer) : boolean; override; // Spybot only methods function PollEEPROM(block : Integer = -1) : TStrings; override; // NXT only methods // NXT direct commands function StartProgram(const filename : string) : boolean; override; function StopProgram : boolean; override; function PlaySoundFile(const filename : string; bLoop : boolean) : boolean; override; function GetNXTOutputState(const aPort : byte; var power : integer; var mode, regmode : byte; var turnratio : integer; var runstate : byte; var tacholimit : cardinal; var tachocount, blocktachocount, rotationcount : longint) : boolean; override; function SetNXTOutputState(const aPort : byte; const power : integer; const mode, regmode : byte; const turnratio : integer; const runstate : byte; const tacholimit : cardinal) : boolean; override; function GetNXTInputValues(const aPort : byte; var valid, calibrated : boolean; var stype, smode : byte; var raw, normalized : word; var scaled, calvalue : smallint) : boolean; override; function SetNXTInputMode(const aPort, stype, smode : byte) : boolean; override; function ResetInputScaledValue(const aPort : byte) : boolean; override; function ResetOutputPosition(const aPort : byte; const Relative : boolean) : boolean; override; function MessageWrite(const inbox : byte; const msg : string) : boolean; override; function KeepAlive(var time : cardinal; const chkResponse : boolean = true) : boolean; override; function LSGetStatus(aPort : byte; var bytesReady : byte) : boolean; override; function GetCurrentProgramName(var name : string) : boolean; override; function GetButtonState(const idx : byte; const reset : boolean; var pressed : boolean; var count : byte) : boolean; override; function MessageRead(const remote, local : byte; const remove : boolean; var Msg : NXTMessage) : boolean; override; function SetPropDebugging(const debugging : boolean; const pauseClump : byte; const pausePC : Word) : boolean; override; function GetPropDebugging(var debugging : boolean; var pauseClump : byte; var pausePC : Word) : boolean; override; function SetVMState(const state : byte) : boolean; override; function SetVMStateEx(var state : byte; var clump : byte; var pc : word) : boolean; override; function GetVMState(var state : byte; var clump : byte; var pc : word) : boolean; override; // NXT system commands function NXTOpenRead(const filename : string; var handle : FantomHandle; var size : cardinal) : boolean; override; function NXTOpenWrite(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; override; function NXTRead(var handle : FantomHandle; var count : word; var buffer : NXTDataBuffer) : boolean; override; function NXTWrite(var handle : FantomHandle; const buffer : NXTDataBuffer; var count : word; const chkResponse : boolean = false) : boolean; override; function NXTCloseFile(var handle : FantomHandle; const chkResponse: boolean = false) : boolean; override; function NXTDeleteFile(var filename : string; const chkResponse: boolean = false) : boolean; override; function NXTFindFirstFile(var filename : string; var IterHandle : FantomHandle; var filesize, availsize : cardinal) : boolean; override; function NXTFindNextFile(var IterHandle : FantomHandle; var filename : string; var filesize, availsize : cardinal) : boolean; override; function NXTFindClose(var IterHandle : FantomHandle) : boolean; override; function NXTGetVersions(var protmin, protmaj, firmmin, firmmaj : byte) : boolean; override; function NXTOpenWriteLinear(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; override; function NXTOpenReadLinear(const filename : string; var handle : FantomHandle; var size : cardinal) : boolean; override; function NXTOpenWriteData(const filename : string; const size : cardinal; var handle : FantomHandle) : boolean; override; function NXTOpenAppendData(const filename : string; var size : cardinal; var handle : FantomHandle) : boolean; override; function NXTCloseModuleHandle(var handle : FantomHandle; const chkResponse: boolean = false) : boolean; override; function NXTBootCommand(const chkResponse: boolean = false) : boolean; override; function NXTSetBrickName(const name : string; const chkResponse: boolean = false) : boolean; override; function NXTGetDeviceInfo(var name : string; var BTAddress : string; var BTSignal : Cardinal; var memFree : Cardinal) : boolean; override; function NXTFreeMemory : integer; override; function NXTDeleteUserFlash(const chkResponse: boolean = false) : boolean; override; function NXTBTFactoryReset(const chkResponse: boolean = false) : boolean; override; function NXTPollCommandLen(const bufNum : byte; var count : byte) : boolean; override; function NXTPollCommand(const bufNum : byte; var count : byte; var buffer : NXTDataBuffer) : boolean; override; function NXTWriteIOMap(var ModID : Cardinal; const Offset : Word; var count : Word; const buffer : NXTDataBuffer; chkResponse : Boolean = False) : boolean; override; function NXTReadIOMap(var ModID : Cardinal; const Offset : Word; var count : Word; var buffer : NXTDataBuffer) : boolean; override; function NXTFindFirstModule(var ModName : string; var Handle : FantomHandle; var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; override; function NXTFindNextModule(var Handle : FantomHandle; var ModName : string; var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; override; function NXTRenameFile(const old, new : string; const chkResponse: boolean = false) : boolean; override; { kNXT_SCGetBTAddress = $9A; } // wrapper functions function NXTDownloadFile(const filename : string; const filetype : TNXTFileType) : boolean; override; function NXTDownloadStream(aStream : TStream; const dest : string; const filetype : TNXTFileType) : boolean; override; function NXTUploadFile(const filename : string; const dir : string = '') : boolean; override; function NXTUploadFileToStream(const filename : string; aStream : TStream) : boolean; override; function NXTListFiles(const searchPattern : string; Files : TStrings) : boolean; override; function NXTListModules(const searchPattern : string; Modules : TStrings) : boolean; override; function NXTListBricks(Bricks : TStrings) : boolean; override; procedure NXTInitializeResourceNames; override; procedure NXTUpdateResourceNames; override; end; implementation uses rcx_constants, Contnrs, Math, uCommonUtils, uDebugLogging, {$IFNDEF FPC} FANTOM {$ELSE} {$IFDEF Darwin}fantomosx{$ENDIF} {$IFNDEF Darwin} {$IFDEF Unix}fantomfpc{$ENDIF} {$IFDEF Windows}FANTOM{$ENDIF} {$ENDIF} {$ENDIF}; procedure iNXT_sendSystemCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); var BufOut, BufIn : PByte; dstatus : integer; begin if status < kStatusNoError then Exit; BufOut := nil; GetMem(BufOut, inputBufferSize+1); try BufOut^ := kNXT_SystemCmd; if not Boolean(requireResponse) then BufOut^ := BufOut^ or kNXT_NoResponseMask; inc(BufOut); Move(inputBufferPtr^, BufOut^, inputBufferSize); dec(BufOut); iNXT_write(nxtHandle, BufOut, inputBufferSize+1, status); if Boolean(requireResponse) and (status >= kStatusNoError) then begin BufIn := nil; GetMem(BufIn, outputBufferSize+1); try iNXT_read(nxtHandle, BufIn, outputBufferSize+1, status); if Boolean(requireResponse) and (status >= kStatusNoError) then begin inc(BufIn); Move(BufIn^, outputBufferPtr^, outputBufferSize); dec(BufIn); end; finally FreeMem(BufIn); end; end else begin // no response required or error occurred on write // drain our channel of any leftover data BufIn := nil; GetMem(BufIn, 1); try dstatus := kStatusNoError; while dstatus = kStatusNoError do iNXT_read(nxtHandle, BufIn, 1, dstatus); finally FreeMem(BufIn); end; end; finally FreeMem(BufOut); end; end; var scResponse : array [0..63] of byte; procedure iNXT_getDeviceInfoEx(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); var cmd : TNINxtCmd; scBuffer : PByte; b1, b2, b3, b4 : Byte; begin FillChar(scResponse, 64, 0); scBuffer := @scResponse[0]; cmd := TNINxtCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCGetDeviceInfo); iNXT_sendSystemCommand(nxtHandle, 1, cmd.BytePtr, cmd.Len, scBuffer, 32, status); if status = kStatusNoError then begin inc(scBuffer, 2); // offset to start of name in the response Move(scBuffer^, name^, 15); inc(scBuffer, 15); // move to address Move(scBuffer^, address^, 6); inc(scBuffer, 7); // move to signal strength Move(scBuffer^, signalStrength^, 4); inc(scBuffer, 4); b1 := scBuffer^; inc(scBuffer); b2 := scBuffer^; inc(scBuffer); b3 := scBuffer^; inc(scBuffer); b4 := scBuffer^; inc(scBuffer); availableFlash := BytesToCardinal(b1, b2, b3, b4); end; finally cmd.Free; end; end; procedure iNXT_sendDirectCommandEnhanced(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer; bEnhanced : boolean = false); var BufOut, BufIn : PByte; dstatus : integer; begin // is this an enhanced direct command? if requireResponse = 127 then begin if status < kStatusNoError then Exit; BufOut := nil; GetMem(BufOut, inputBufferSize+1); try BufOut^ := kNXT_DirectCmd; if not Boolean(requireResponse) then BufOut^ := BufOut^ or kNXT_NoResponseMask; inc(BufOut); Move(inputBufferPtr^, BufOut^, inputBufferSize); dec(BufOut); iNXT_write(nxtHandle, BufOut, inputBufferSize+1, status); if Boolean(requireResponse) and (status >= kStatusNoError) then begin BufIn := nil; GetMem(BufIn, outputBufferSize+1); try iNXT_read(nxtHandle, BufIn, outputBufferSize+1, status); if Boolean(requireResponse) and (status >= kStatusNoError) then begin inc(BufIn); Move(BufIn^, outputBufferPtr^, outputBufferSize); dec(BufIn); end; finally FreeMem(BufIn); end; end else begin // no response required or error occurred on write // drain our channel of any leftover data BufIn := nil; GetMem(BufIn, 1); try dstatus := kStatusNoError; while dstatus = kStatusNoError do iNXT_read(nxtHandle, BufIn, 1, dstatus); finally FreeMem(BufIn); end; end; finally FreeMem(BufOut); end; end else iNXT_sendDirectCommand(nxtHandle, requireResponse, inputBufferPtr, inputBufferSize, outputBufferPtr, outputBufferSize, status); end; function NXTModuleIDToName(const modID : cardinal) : string; var i : integer; begin Result := '*.*'; for i := Low(NXTModuleMap) to High(NXTModuleMap) do begin if NXTModuleMap[i].ID = modID then begin Result := NXTModuleMap[i].Name; Break; end; end; end; { TFantomSpirit } constructor TFantomSpirit.Create(aType: byte; const aPort: string); begin inherited Create(aType, aPort); fResPort := ''; fResourceNames := TStringList.Create; end; destructor TFantomSpirit.Destroy; begin FreeAndNil(fResourceNames); inherited Destroy; end; function TFantomSpirit.BatteryLevel: integer; var bopen : boolean; cmd : TNINxtCmd; status : integer; begin Result := -1; bopen := IsOpen; if bopen then begin cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetBatteryLevel); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 4, status); if status < kStatusNoError then begin result := kRCX_ReplyError; Exit; end; Result := GetReplyWord(0); finally cmd.Free; end; end; end; function TFantomSpirit.Shutdown: boolean; var modID : Cardinal; count : Word; buffer : NXTDataBuffer; begin Result := IsOpen; if not Result then Exit; modID := kNXT_ModuleIOCtrl; count := 2; buffer.Data[0] := $0; buffer.Data[1] := $5a; Result := NXTWriteIOMap(modID, IOCtrlOffsetPowerOn, count, buffer); end; const MotorBits : array[0..2] of byte = (1, 2, 4); function TFantomSpirit.MotorsOn(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; oldpower, power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorOn[i] := True; rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; oldpower := 0; Result := Result and GetNXTOutputState(i, oldpower, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); power := fMotorPower[i] * 14; if not fMotorForward[i] then power := power * -1; if (oldpower <> power) or ((mode and OUT_MODE_MOTORON) <> OUT_MODE_MOTORON) or ((runstate and OUT_RUNSTATE_RUNNING) <> OUT_RUNSTATE_RUNNING) then begin mode := OUT_MODE_MOTORON+OUT_MODE_BRAKE; runstate := OUT_RUNSTATE_RUNNING; Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; end; if not Result then Break; end; end; function TFantomSpirit.MotorsOff(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorOn[i] := False; power := 0; mode := OUT_MODE_MOTORON+OUT_MODE_BRAKE; regmode := OUT_REGMODE_IDLE; runstate := OUT_RUNSTATE_RUNNING; turnratio := 0; // straight (side effect of stopping motors is to reset turn ratio) tacholimit := 0; // no limit (side effect of stopping motors is to reset tacho limit) Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; if not Result then Break; end; end; function TFantomSpirit.MotorsFloat(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorOn[i] := False; power := 0; mode := 0; // OUT_MODE_COAST; regmode := 0; // OUT_REGMODE_IDLE; runstate := 0; // OUT_RUNSTATE_IDLE; turnratio := 0; // straight (side effect of stopping motors is to reset turn ratio) tacholimit := 0; // no limit (side effect of stopping motors is to reset tacho limit) Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; if not Result then Break; end; end; function TFantomSpirit.SetFwd(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorForward[i] := True; rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; power := 0; Result := Result and GetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); if power < 0 then begin power := power * -1; if not fMotorOn[i] then begin // make sure we are idle mode := 0; regmode := 0; runstate := 0; end; Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; end; if not Result then Break; end; end; function TFantomSpirit.SetRwd(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorForward[i] := False; rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; power := 0; Result := Result and GetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); if power > 0 then begin power := power * -1; if not fMotorOn[i] then begin // make sure we are idle mode := 0; regmode := 0; runstate := 0; end; Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; end; if not Result then Break; end; end; function TFantomSpirit.SwitchDirection(aMotorList: Byte): boolean; var mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; i : Byte; begin Result := IsOpen; if not Result then Exit; for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorForward[i] := not fMotorForward[i]; rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; power := 0; Result := Result and GetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); power := power * -1; Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; if not Result then Break; end; end; function TFantomSpirit.SetMotorPower(aMotorList: Byte; aSrc, aNum: integer): boolean; var mode, regmode, runstate : byte; oldpower, power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; i : Byte; begin Result := IsOpen; if not Result then Exit; if aSrc <> 2 then begin Result := False; Exit; end else begin for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin fMotorPower[i] := Byte(Abs(aNum) mod 8); rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; oldpower := 0; Result := Result and GetNXTOutputState(i, oldpower, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); power := fMotorPower[i] * 14; if fMotorPower[i] = 7 then power := 100; if not fMotorForward[i] then power := power * -1; if oldpower <> power then begin if not fMotorOn[i] then begin // make sure we are idle mode := 0; regmode := 0; runstate := 0; end; Result := Result and SetNXTOutputState(i, power, mode, regmode, turnratio, runstate, tacholimit); end; end; if not Result then Break; end; end; end; function TFantomSpirit.PlayTone(aFreq, aTime: word): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCPlayTone, Lo(aFreq), Hi(aFreq), Lo(aTime), Hi(aTime)); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.SetSensorType(aNum, aType: integer): boolean; begin Result := IsOpen; if not Result then Exit; fSensorType[aNum] := Byte(aType); Result := SetNXTInputMode(Byte(aNum), Byte(aType), fSensorMode[aNum]); end; function TFantomSpirit.SetSensorMode(aNum, aMode, aSlope: integer): boolean; begin Result := IsOpen; if not Result then Exit; fSensorMode[aNum] := Byte(((aMode and $7) shl 5) or (aSlope and $F)); Result := SetNXTInputMode(Byte(aNum), fSensorType[aNum], fSensorMode[aNum]); end; function TFantomSpirit.ClearSensorValue(aNum: integer): boolean; begin Result := ResetInputScaledValue(Byte(aNum)); end; function TFantomSpirit.Close: boolean; var status : integer; begin Result := inherited Close; if IsOpen then begin DebugLog('TFantomSpirit.Close: Closing our open connection'); fResPort := ''; // clear this so that it gets looked up again when opening fUseBT := False; status := kStatusNoError; destroyNXT(fNXTHandle, status); fActive := False; fNXTHandle := 0; Result := Result and (status >= kStatusNoError); end; end; function TFantomSpirit.Open: boolean; var nih : FantomHandle; status, status2 : integer; resNamePC : array[0..54] of Char; pairedResNamePC : array[0..54] of Char; resName, pName, bName : string; begin DebugLog('TFantomSpirit.Open: Checking whether the connection is already open'); Result := IsOpen; if not FantomAPILoaded then Exit; if not Result then begin DebugLog('TFantomSpirit.Open: IsOpen returned FALSE'); if fResPort = '' then LookupResourceName; if fResPort = '' then fResPort := fPort; resName := ''; pName := AnsiUpperCase(fResPort); bName := AnsiUpperCase(BluetoothName); DebugFmt('TFantomSpirit.Open: pName = "%s"', [pName]); DebugFmt('TFantomSpirit.Open: bName = "%s"', [bName]); if (Length(pName) > 4) and (Pos('::', pName) > 0) then begin // we think this is a resource string // if we are using bluetooth then we need to make sure we are paired // with the brick status := kStatusNoError; // if we are using a brick resource string we think we have already paired // with the PC so try without pairing. If that fails then try again after // pairing. DebugLog('TFantomSpirit.Open: Already have a full brick resource string so try to connect using it'); fNXTHandle := createNXT(PChar(pName), status, 0); if status >= kStatusNoError then begin DebugLog('TFantomSpirit.Open: First attempt to createNXT worked. All done.'); fActive := True; Result := True; end else begin DebugFmt('TFantomSpirit.Open: First attempt to createNXT failed. Status = %d.', [status]); // if bluetooth then try again after pairing if UseBluetooth then begin DebugLog('TFantomSpirit.Open: UseBluetooth is TRUE'); status := kStatusNoError; DebugLog('TFantomSpirit.Open: Try pairing with pin = 1234'); pairBluetooth(PChar(pName), '1234', pairedResNamePC, status); pName := pairedResNamePC; DebugFmt('TFantomSpirit.Open: pName now = "%s"', [pName]); if status >= kStatusNoError then begin DebugFmt('TFantomSpirit.Open: status = %d', [status]); status := kStatusNoError; DebugLog('TFantomSpirit.Open: Try calling createNXT again'); fNXTHandle := createNXT(PChar(pName), status, 0); if status >= kStatusNoError then begin DebugLog('TFantomSpirit.Open: Second attempt to createNXT worked. All done.'); fActive := True; Result := True; end; end; end; end; end else begin DebugLog('TFantomSpirit.Open: We do not already have a full brick resource string'); // use Fantom API to obtain a handle to an NXT on either USB or bluetooth status := kStatusNoError; DebugLog('TFantomSpirit.Open: calling createNXTIterator to search for devices'); nih := createNXTIterator(Ord(UseBluetooth), BluetoothSearchTimeout, status); while status >= kStatusNoError do begin status2 := kStatusNoError; DebugLog('TFantomSpirit.Open: calling iNXTIterator_getName'); iNXTIterator_getName(nih, resNamePC, status2); resName := AnsiUpperCase(resNamePC); DebugFmt('TFantomSpirit.Open: current resource name = "%s"', [resNamePC]); if UseBluetooth then begin if bName = '' then bName := 'BTH'; if Pos(bName, resName) > 0 then Break; end else if Pos(pName, resName) > 0 then Break; iNXTIterator_advance(nih, status); end; // if we are using bluetooth then we need to make sure we are paired // with the brick if UseBluetooth then begin status := kStatusNoError; DebugLog('TFantomSpirit.Open: Try pairing with pin = 1234'); pairBluetooth(resNamePC, '1234', pairedResNamePC, status); resName := AnsiUpperCase(pairedResNamePC); DebugFmt('TFantomSpirit.Open: resource name now = "%s"', [resName]); end; if status >= kStatusNoError then begin DebugLog('TFantomSpirit.Open: calling iNXTIterator_getNXT'); fNXTHandle := iNXTIterator_getNXT(nih, status); if status >= kStatusNoError then begin DebugFmt('TFantomSpirit.Open: Got NXT with resName = "%s". All done.', [resName]); SetResourcePort(resName); fActive := True; Result := True; end; end; status := kStatusNoError; DebugLog('TFantomSpirit.Open: calling destroyNXTIterator'); destroyNXTIterator(nih, status); end; end; end; function TFantomSpirit.ClearMemory: boolean; begin Result := NXTDeleteUserFlash(True); end; function TFantomSpirit.Sleep(aVal: integer): boolean; begin Result := PowerDownTime(aVal); end; function TFantomSpirit.GetInputValue(aIn : integer) : integer; var bOpen : boolean; begin Result := -1; bopen := Open; if bOpen then begin Result := Poll(kRCX_InputValueType, aIn); end; end; procedure TFantomSpirit.SetPort(const Value: string); begin if (Value <> fPort) or (fResPort = '') then begin Close; inherited SetPort(Value); fResPort := fPort; LookupResourceName; end; end; function TFantomSpirit.DownloadFirmware(aFile: string; bFast : Boolean; bComp : Boolean; bUnlock : boolean): boolean; var MS : TMemoryStream; begin if not IsOpen then Open; Result := FileExists(aFile); if Result and (bFast or bComp or bUnlock or True) then begin // put the NXT into firmware download mode first and wait a few seconds MS := TMemoryStream.Create; try MS.LoadFromFile(aFile); DoDownloadStart; Result := NXTDownloadStream(MS, aFile, nftFirmware); DoDownloadDone; finally MS.Free; end; end; end; function TFantomSpirit.Ping: boolean; var time : cardinal; begin Result := IsOpen; if not Result then Exit; time := 0; Result := KeepAlive(time); end; function TFantomSpirit.MuteSound: boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCStopSoundPlayback); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.UnmuteSound: boolean; var cmd : TNINxtCmd; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try // TODO : Implement Unmute Sound finally cmd.Free; end; end; function TFantomSpirit.GetPortName: string; begin Result := FPort; end; function TFantomSpirit.GetFullPortName: string; begin Result := fResPort; end; function TFantomSpirit.GetNicePortName: string; var i : integer; begin i := Pos('::', fResPort); if i > 0 then Result := Copy(fResPort, 1, i-1) else Result := fResPort; end; function TFantomSpirit.GetIsOpen: boolean; begin Result := inherited GetIsOpen; Result := Result and FantomAPILoaded; end; function TFantomSpirit.StartProgram(const filename: string): boolean; var cmd : TNINxtCmd; status : integer; tmp : string; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try // any time you start a program reset the stored DS and DVA offsets fOffsetDS := MaxInt; fOffsetDVA := MaxInt; status := kStatusNoError; tmp := MakeValidNXTFilename(filename); cmd.MakeCmdWithFilename(kNXT_DirectCmd, kNXT_DCStartProgram, tmp); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 2, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.StopProgram: boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try // reset offsets to "no program running" values fOffsetDS := $FFFF; fOffsetDVA := $FFFF; status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCStopProgram); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 2, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.PlaySoundFile(const filename: string; bLoop: boolean): boolean; var i : integer; cmd : TNINxtCmd; orig : PByte; nxtFilename : string; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; // filename is limited to 19 bytes + null terminator cmd.SetLength(23); orig := cmd.GetBody; orig^ := kNXT_DirectCmdNoReply; inc(orig); orig^ := kNXT_DCPlaySoundFile; inc(orig); orig^ := Ord(bLoop); inc(orig); i := 1; nxtFilename := MakeValidNXTFilename(filename); while i <= 19 do begin // copy the first nineteen bytes from the filename provided if i > Length(nxtFilename) then orig^ := 0 else orig^ := Ord(nxtFilename[i]); inc(orig); inc(i); end; orig^ := 0; // set last byte to null iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.GetNXTOutputState(const aPort: byte; var power: integer; var mode, regmode: byte; var turnratio: integer; var runstate: byte; var tacholimit: cardinal; var tachocount, blocktachocount, rotationcount: Integer): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetOutputState, aPort); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 24, status); Result := status >= kStatusNoError; if not Result then Exit; // port := GetReplyByte(0) power := ShortInt(GetReplyByte(1)); mode := GetReplyByte(2); regmode := GetReplyByte(3); turnratio := ShortInt(GetReplyByte(4)); runstate := GetReplyByte(5); tacholimit := GetReplyCardinal(6); tachocount := Integer(GetReplyCardinal(10)); blocktachocount := Integer(GetReplyCardinal(14)); rotationcount := Integer(GetReplyCardinal(18)); finally cmd.Free; end; end; function TFantomSpirit.SetNXTOutputState(const aPort: byte; const power: integer; const mode, regmode: byte; const turnratio: integer; const runstate: byte; const tacholimit: cardinal): boolean; var cmd : TNINxtCmd; // orig : PByte; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.MakeSetOutputState(aPort, mode, regmode, runstate, ShortInt(power), ShortInt(turnratio), tacholimit, False); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.GetNXTInputValues(const aPort: byte; var valid, calibrated: boolean; var stype, smode: byte; var raw, normalized: word; var scaled, calvalue: smallint): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetInputValues, aPort); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 15, status); Result := status >= kStatusNoError; if not Result then Exit; // port := GetReplyByte(0); valid := GetReplyByte(1) <> 0; calibrated := GetReplyByte(2) <> 0; stype := GetReplyByte(3); smode := GetReplyByte(4); raw := GetReplyWord(5); normalized := GetReplyWord(7); scaled := SmallInt(GetReplyWord(9)); calvalue := SmallInt(GetReplyWord(11)); finally cmd.Free; end; end; function TFantomSpirit.SetNXTInputMode(const aPort, stype, smode: byte): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCSetInputMode, aPort, stype, smode); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.ResetInputScaledValue(const aPort: byte): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCResetInputScaledValue, aPort); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.ResetOutputPosition(const aPort: byte; const Relative: boolean): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCResetMotorPosition, aPort, Ord(Relative)); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.MessageWrite(const inbox: byte; const msg: string): boolean; var i, len : integer; cmd : TNINxtCmd; orig : PByte; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; // message is limited to 59 bytes + null terminator len := Min(Length(msg), kNXT_MaxBytes-5); cmd.SetLength(len+5); orig := cmd.GetBody; orig^ := kNXT_DirectCmdNoReply; inc(orig); orig^ := kNXT_DCMessageWrite; inc(orig); orig^ := inbox; inc(orig); orig^ := Byte(len+1); // add null terminator inc(orig); i := 1; while i <= len do begin orig^ := Ord(msg[i]); inc(orig); inc(i); end; orig^ := 0; // set last byte to null iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.KeepAlive(var time: cardinal; const chkResponse : boolean): boolean; var cmd : TNINxtCmd; b : byte; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; result := False; if chkResponse then b := kNXT_DirectCmd else b := kNXT_DirectCmdNoReply; cmd.SetVal(b, kNXT_DCKeepAlive); if chkResponse then iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 6, status) else iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); Result := status >= kStatusNoError; if chkResponse then begin if not Result then Exit; time := Integer(GetReplyCardinal(0)); end; finally cmd.Free; end; end; function TFantomSpirit.LSGetStatus(aPort : byte; var bytesReady: byte): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCLSGetStatus, aPort); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 3, status); Result := status >= kStatusNoError; if not Result then Exit; bytesReady := GetReplyByte(0); finally cmd.Free; end; end; function TFantomSpirit.GetLSBlock(aPort: byte): NXTLSBlock; var cmd : TNINxtCmd; i : integer; status : integer; begin // LSRead Result.TXCount := 0; if not IsOpen then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCLSRead, aPort); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 19, status); if status < kStatusNoError then begin Result.RXCount := 0; Exit; end; Result.RXCount := GetReplyByte(0); for i := 1 to 16 do begin Result.Data[i-1] := GetReplyByte(i); end; finally cmd.Free; end; end; procedure TFantomSpirit.SetLSBlock(aPort: byte; const Value: NXTLSBlock); var i, len : integer; cmd : TNINxtCmd; orig : PByte; status : integer; begin // LSWrite if not IsOpen then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; len := Min(Value.TXCount, 16); cmd.SetLength(len+5); // up to a max of 21 bytes orig := cmd.GetBody; orig^ := kNXT_DirectCmdNoReply; inc(orig); orig^ := kNXT_DCLSWrite; inc(orig); orig^ := aPort; inc(orig); orig^ := Byte(len); inc(orig); orig^ := Byte(Min(Value.RXCount, 16)); inc(orig); i := 0; while i < len do begin orig^ := Value.Data[i]; inc(orig); inc(i); end; orig^ := 0; // set last byte to null iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status); finally cmd.Free; end; end; function TFantomSpirit.GetCurrentProgramName(var name: string): boolean; var cmd : TNINxtCmd; i : integer; Buf : array[0..19] of Char; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetCurrentProgramName); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 22, status); Result := status >= kStatusNoError; if not Result then begin name := ''; Exit; end; for i := 0 to 19 do begin Buf[i] := Char(GetReplyByte(i)); end; name := Buf; Result := name <> ''; finally cmd.Free; end; end; function TFantomSpirit.GetButtonState(const idx: byte; const reset: boolean; var pressed: boolean; var count: byte): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetButtonState, idx, Ord(reset)); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 3, status); Result := status >= kStatusNoError; if not Result then Exit; pressed := Boolean(GetReplyByte(0)); count := GetReplyByte(1); finally cmd.Free; end; end; function TFantomSpirit.MessageRead(const remote, local: byte; const remove: boolean; var Msg: NXTMessage): boolean; var cmd : TNINxtCmd; i : integer; status : integer; begin Msg.Inbox := 0; Msg.Size := 0; Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCMessageRead, remote, local, Ord(remove)); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 63, status); Result := status >= kStatusNoError; if not Result then Exit; Msg.Inbox := GetReplyByte(0); Msg.Size := GetReplyByte(1); for i := 2 to 60 do begin Msg.Data[i-2] := GetReplyByte(i); end; finally cmd.Free; end; end; function TFantomSpirit.NXTOpenRead(const filename: string; var handle: FantomHandle; var size: cardinal): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFile_openForRead(handle, status); Result := status >= kStatusNoError; if Result then begin size := iFile_getSize(handle, status); Result := status >= kStatusNoError; end; if not Result then begin status := kStatusNoError; iNXT_destroyFile(fNXTHandle, handle, status); end; end; end; function TFantomSpirit.NXTOpenReadLinear(const filename: string; var handle: FantomHandle; var size: cardinal): boolean; begin Result := NXTOpenRead(filename, handle, size); end; function TFantomSpirit.NXTOpenAppendData(const filename: string; var size: cardinal; var handle: FantomHandle): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFile_openForDataAppend(handle, status); Result := status >= kStatusNoError; if Result then begin size := iFile_getSize(handle, status); Result := status >= kStatusNoError; end; if not Result then begin status := kStatusNoError; iNXT_destroyFile(fNXTHandle, handle, status); end; end; end; function TFantomSpirit.NXTOpenWrite(const filename: string; const size: cardinal; var handle: FantomHandle): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFile_openForWrite(handle, size, status); Result := status >= kStatusNoError; if not Result then begin status := kStatusNoError; iNXT_destroyFile(fNXTHandle, handle, status); end; end; end; function TFantomSpirit.NXTOpenWriteData(const filename: string; const size: cardinal; var handle: FantomHandle): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFile_openForDataWrite(handle, size, status); Result := status >= kStatusNoError; if not Result then begin status := kStatusNoError; iNXT_destroyFile(fNXTHandle, handle, status); end; end; end; function TFantomSpirit.NXTOpenWriteLinear(const filename: string; const size: cardinal; var handle: FantomHandle): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFile_openForLinearWrite(handle, size, status); Result := status >= kStatusNoError; if not Result then begin status := kStatusNoError; iNXT_destroyFile(fNXTHandle, handle, status); end; end; end; function TFantomSpirit.NXTRead(var handle: FantomHandle; var count: word; var buffer: NXTDataBuffer): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iFile_read(handle, @buffer.Data[0], count, status); Result := status >= kStatusNoError; end; function TFantomSpirit.NXTWrite(var handle: FantomHandle; const buffer: NXTDataBuffer; var count: word; const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iFile_write(handle, @buffer.Data[0], count, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; end; function TFantomSpirit.NXTCloseFile(var handle: FantomHandle; const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iFile_close(handle, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; if Result then begin iNXT_destroyFile(FNXTHandle, handle, status); Result := status >= kStatusNoError; end; end; function TFantomSpirit.NXTDeleteFile(var filename: string; const chkResponse: boolean): boolean; var handle : FantomHandle; status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; handle := iNXT_createFile(FNXTHandle, PChar(filename), status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; if Result then begin iFile_remove(handle, status); Result := status >= kStatusNoError; status := kStatusNoError; iNXT_destroyFile(FNXTHandle, handle, status); end; end; function TFantomSpirit.NXTFindFirstFile(var filename: string; var IterHandle: FantomHandle; var filesize, availsize : cardinal): boolean; var status : integer; buf : array[0..19] of Char; NXTFileHandle : FantomHandle; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; IterHandle := iNXT_createFileIterator(FNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin iFileIterator_getName(IterHandle, buf, status); filename := buf; status := kStatusNoError; filesize := iFileIterator_getSize(IterHandle, status); NXTFileHandle := iFileIterator_getFile(IterHandle, status); status := kStatusNoError; availsize := iFile_getAvailableSize(NXTFileHandle, status); status := kStatusNoError; iFile_close(NXTFileHandle, status); end; end; function TFantomSpirit.NXTFindNextFile(var IterHandle: FantomHandle; var filename: string; var filesize, availsize : cardinal): boolean; var status : integer; Buf : array[0..19] of Char; NXTFileHandle : FantomHandle; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iFileIterator_advance(IterHandle, status); Result := status >= kStatusNoError; if Result then begin iFileIterator_getName(IterHandle, buf, status); filename := buf; status := kStatusNoError; filesize := iFileIterator_getSize(IterHandle, status); NXTFileHandle := iFileIterator_getFile(IterHandle, status); status := kStatusNoError; availsize := iFile_getAvailableSize(NXTFileHandle, status); status := kStatusNoError; iFile_close(NXTFileHandle, status); end else begin Result := NXTFindClose(IterHandle); filename := ''; end; end; function TFantomSpirit.NXTFindClose(var IterHandle: FantomHandle): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; // destroy the iterator status := kStatusNoError; iNXT_destroyFileIterator(fNXTHandle, IterHandle, status); IterHandle := 0; Result := status >= kStatusNoError; end; function TFantomSpirit.NXTGetVersions(var protmin, protmaj, firmmin, firmmaj : byte): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_getFirmwareVersion(fNXTHandle, protmaj, protmin, firmmaj, firmmin, status); Result := status >= kStatusNoError; end; function TFantomSpirit.NXTCloseModuleHandle(var handle: FantomHandle; const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_destroyModule(fNXTHandle, handle, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; end; function TFantomSpirit.NXTBootCommand(const chkResponse: boolean): boolean; var status : integer; resBuf : array[0..60] of Char; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_getResourceString(fNXTHandle, resBuf, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; if Result then begin iNXT_bootIntoFirmwareDownloadMode(resBuf, status); Result := status >= kStatusNoError; end; end; function TFantomSpirit.NXTSetBrickName(const name: string; const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_setName(fNXTHandle, PChar(name), status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; end; function TFantomSpirit.NXTGetDeviceInfo(var name: string; var BTAddress : String; var BTSignal : Cardinal; var memFree : Cardinal): boolean; var status : integer; buf : array[0..20] of Char; addr : array[0..6] of Byte; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_getDeviceInfoEx(fNXTHandle, buf, @addr[0], @BTSignal, memFree, status); name := buf; BTAddress := Format('%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x', [addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]]); Result := status >= kStatusNoError; end; function TFantomSpirit.NXTDeleteUserFlash(const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_eraseUserFlash(fNXTHandle, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; end; function TFantomSpirit.NXTBTFactoryReset(const chkResponse: boolean): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iNXT_bluetoothFactoryReset(fNXTHandle, status); if chkResponse then Result := status >= kStatusNoError else Result := status >= kStatusNoError; end; type TFileInfoRec = class public FileHandle : FantomHandle; TotalSize : Cardinal; AvailableSize : Cardinal; Name : string; end; function TFantomSpirit.NXTUploadFile(const filename: string; const dir : string): boolean; var handle : FantomHandle; totalSize, availableSize : Cardinal; MS : TMemoryStream; tmpFilename : string; NXTFileIteratorHandle : FantomHandle; status, i : integer; buf : array[0..20] of Char; FIR : TFileInfoRec; OL : TObjectList; begin Result := IsOpen; if not Result then Exit; // upload means from NXT to PC OL := TObjectList.Create; try status := kStatusNoError; NXTFileIteratorHandle := iNXT_createFileIterator(fNXTHandle, PChar(filename), status); Result := status >= kStatusNoError; if Result then begin while status >= kStatusNoError do begin iFileIterator_getName(NXTFileIteratorHandle, buf, status); tmpFilename := buf; status := kStatusNoError; totalSize := iFileIterator_getSize(NXTFileIteratorHandle, status); status := kStatusNoError; handle := iFileIterator_getFile(NXTFileIteratorHandle, status); status := kStatusNoError; availableSize := iFile_getAvailableSize(handle, status); // save the info for this file into our object list FIR := TFileInfoRec.Create; OL.Add(FIR); FIR.FileHandle := handle; FIR.Name := tmpFilename; FIR.TotalSize := totalSize; FIR.AvailableSize := availableSize; // advance to the next file status := kStatusNoError; iFileIterator_advance(NXTFileIteratorHandle, status); end; status := kStatusNoError; iNXT_destroyFileIterator(fNXTHandle, NXTFileIteratorHandle, status); Result := OL.Count > 0; for i := 0 to OL.Count - 1 do begin FIR := TFileInfoRec(OL.Items[i]); MS := TMemoryStream.Create; try InternalNXTUploadFileToStream(FIR.FileHandle, FIR.Name, FIR.TotalSize, FIR.AvailableSize, MS); NXTCloseFile(FIR.FileHandle); // now try to save the file tmpFilename := FIR.Name; if dir <> '' then tmpFilename := IncludeTrailingPathDelimiter(dir) + tmpFilename; if Result then MS.SaveToFile(tmpFilename); finally MS.Free; end; end; end; finally OL.Free; end; end; function TFantomSpirit.NXTUploadFileToStream(const filename: string; aStream: TStream): boolean; var handle : FantomHandle; totalSize, availableSize : Cardinal; tmpFilename : string; NXTFileIteratorHandle : FantomHandle; status : integer; buf : array[0..20] of Char; begin Result := IsOpen; if not Result then Exit; // upload means from NXT to PC status := kStatusNoError; NXTFileIteratorHandle := iNXT_createFileIterator(fNXTHandle, PChar(filename), status); if status >= kStatusNoError then begin iFileIterator_getName(NXTFileIteratorHandle, buf, status); tmpFilename := buf; status := kStatusNoError; totalSize := iFileIterator_getSize(NXTFileIteratorHandle, status); status := kStatusNoError; handle := iFileIterator_getFile(NXTFileIteratorHandle, status); status := kStatusNoError; availableSize := iFile_getAvailableSize(handle, status); status := kStatusNoError; iNXT_destroyFileIterator(fNXTHandle, NXTFileIteratorHandle, status); // upload file InternalNXTUploadFileToStream(handle, tmpFilename, totalSize, availableSize, aStream); NXTCloseFile(handle); end; end; function TFantomSpirit.InternalNXTUploadFileToStream(handle: FantomHandle; const name: string; const totalSize, availSize: cardinal; aStream: TStream): boolean; var size : cardinal; tmpFilename : string; status : integer; fileBuf : PByte; bEOFOnRead : boolean; begin tmpFilename := name; size := Cardinal(Max(totalSize - availSize, 0)); status := kStatusNoError; iFile_openForRead(handle, status); aStream.Size := 0; aStream.Position := 0; // aStream.Clear; // empty the stream fileBuf := nil; GetMem(fileBuf, size); try FillChar(fileBuf^, size, 0); status := kStatusNoError; iFile_read(handle, fileBuf, size, status); bEOFOnRead := status = kStatusFWEndOfFile; Result := (status >= kStatusNoError) or bEOFOnRead; if Result then aStream.Write(fileBuf^, size); finally FreeMem(fileBuf); end; // hmmm we may have a problem here. If we encountered an EOF on // read then that means the file we are trying to upload is one of // those files which has been created using the syscall file io // functions and it's contents are less than its reported size. // In that case we need to discard what we just did and try to // read the file one byte at a time. if bEOFOnRead then begin status := kStatusNoError; iFile_close(handle, status); // close the file and reopen it status := kStatusNoError; iFile_openForRead(handle, status); Result := status >= kStatusNoError; aStream.Size := 0; aStream.Position := 0; // aStream.Clear; // empty the stream GetMem(fileBuf, 1); try FillChar(fileBuf^, 1, 0); while status >= kStatusNoError do begin iFile_read(handle, fileBuf, 1, status); if status >= kStatusNoError then aStream.Write(fileBuf^, 1); end; finally FreeMem(fileBuf); end; end; end; function TFantomSpirit.NXTListFiles(const searchPattern: string; Files: TStrings): boolean; var size : Cardinal; tmpfilename : string; NXTFileIteratorHandle : FantomHandle; buf : array[0..20] of Char; status : integer; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; NXTFileIteratorHandle := iNXT_createFileIterator(fNXTHandle, PChar(searchPattern), status); Result := status >= kStatusNoError; while status >= kStatusNoError do begin iFileIterator_getName(NXTFileIteratorHandle, buf, status); tmpFilename := buf; size := iFileIterator_getSize(NXTFileIteratorHandle, status); Files.Add(tmpfilename + '=' + IntToStr(size)); Result := status >= kStatusNoError; iFileIterator_advance(NXTFileIteratorHandle, status); end; status := kStatusNoError; iNXT_destroyFileIterator(fNXTHandle, NXTFileIteratorHandle, status); end; function TFantomSpirit.NXTListModules(const searchPattern: string; Modules: TStrings): boolean; var size, mID : Cardinal; NXTModuleIteratorHandle, handle : FantomHandle; buf : array[0..20] of Char; status : integer; iosize : Word; tmpname : string; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; NXTModuleIteratorHandle := iNXT_createModuleIterator(fNXTHandle, PChar(searchPattern), status); Result := status >= kStatusNoError; while status >= kStatusNoError do begin handle := iModuleIterator_getModule(NXTModuleIteratorHandle, status); iModule_getName(handle, buf, status); tmpname := buf; status := kStatusNoError; iosize := Word(iModule_getIOMapSize(handle, status)); status := kStatusNoError; mID := iModule_getModuleID(handle, status); status := kStatusNoError; size := iModule_getModuleSize(handle, status); Modules.Add(Format('%s=%d, %d, %d', [tmpname, mID, size, iosize])); status := kStatusNoError; iNXT_destroyModule(fNXTHandle, handle, status); status := kStatusNoError; iModuleIterator_advance(NXTModuleIteratorHandle, status); end; status := kStatusNoError; iNXT_destroyModuleIterator(fNXTHandle, NXTModuleIteratorHandle, status); end; function TFantomSpirit.NXTDownloadFile(const filename: string; const filetype: TNXTFileType): boolean; var MS : TMemoryStream; begin Result := IsOpen; if not Result then Exit; // download means from PC to NXT Result := FileExists(filename); if Result then begin MS := TMemoryStream.Create; try MS.LoadFromFile(filename); Result := NXTDownloadStream(MS, filename, filetype); finally MS.Free; end; end; end; function TFantomSpirit.TransferFirmware(aStream : TStream) : boolean; var size : Cardinal; resBuf : array[0..255] of Char; status : integer; buf : PByte; elapsedTime : Cardinal; bStop : boolean; cur, i : integer; const K_SEC = 1000; MaximumWait = 30*K_SEC; // 30 seconds K_STEPS = 30; begin Result := IsOpen; DebugLog('TFantomSpirit.TransferFirmware: Connection is open = ' + BoolToStr(Result)); size := Cardinal(aStream.Size); bStop := False; status := kStatusNoError; cur := 0; DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; if Result then begin // if we could open the NXT then it isn't in firmware download mode iNXT_getResourceString(fNXTHandle, resBuf, status); Result := status >= kStatusNoError; DebugLog('TFantomSpirit.TransferFirmware: iNXT_getResourceString status = ' + IntToStr(status) + ', resBuf = ' + String(resBuf)); if Result then begin status := kStatusNoError; iNXT_bootIntoFirmwareDownloadMode(resBuf, status); DebugLog('TFantomSpirit.TransferFirmware: iNXT_bootIntoFirmwareDownloadMode status = ' + IntToStr(status) + ', resBuf = ' + String(resBuf)); Result := status >= kStatusNoError; if Result then begin destroyNXT(fNXTHandle, status); DebugLog('TFantomSpirit.TransferFirmware: destroyNXT status = ' + IntToStr(status)); end; end; inc(cur); DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; end; // the device should now be in firmware download mode elapsedTime := 0; repeat SysUtils.Sleep(K_SEC); inc(elapsedTime, K_SEC); status := kStatusNoError; iNXT_findDeviceInFirmwareDownloadMode(resBuf, status); DebugLog('TFantomSpirit.TransferFirmware: iNXT_findDeviceInFirmwareDownloadMode status = ' + IntToStr(status) + ', resBuf = ' + String(resBuf)); inc(cur); DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; until (status >= kStatusNoError) or (elapsedTime >= MaximumWait); cur := 16; DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; // now download the firmware if status >= kStatusNoError then begin status := kStatusNoError; fNXTHandle := createNXT(resBuf, status, 0); DebugLog('TFantomSpirit.TransferFirmware: createNXT status = ' + IntToStr(status) + ', resBuf = ' + String(resBuf)); inc(cur); DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; buf := nil; GetMem(buf, size); try aStream.Position := 0; // start at the beginning aStream.Read(buf^, size); status := kStatusNoError; iNXT_downloadFirmware(fNXTHandle, buf, size, status); DebugLog('TFantomSpirit.TransferFirmware: iNXT_downloadFirmware status = ' + IntToStr(status) + ', resBuf = ' + String(resBuf)); inc(cur); DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; finally FreeMem(buf); end; // wait 10 seconds for i := 0 to 9 do begin SysUtils.Sleep(K_SEC); inc(cur); DoDownloadStatus(cur, K_STEPS, bStop); if bStop then begin Result := False; Exit; end; end; Close; SysUtils.Sleep(K_SEC); // one more second before reopening Open; Result := status >= kStatusNoError; end; end; function TFantomSpirit.NXTDownloadStream(aStream: TStream; const dest : string; const filetype: TNXTFileType): boolean; var size : Cardinal; handle : FantomHandle; status : integer; buf : PByte; nxtFilename, delname : string; begin handle := 0; Result := IsOpen; if not FantomAPILoaded then Exit; status := kStatusNoError; if filetype = nftFirmware then begin Result := TransferFirmware(aStream); end else begin if not Result then Exit; size := Cardinal(aStream.Size); // download means from PC to NXT // make destination filename a valid NXT filename (15.3) nxtFilename := MakeValidNXTFilename(dest); delname := nxtFilename; NXTDeleteFile(delname, True); if filetype in [nftProgram, nftGraphics] then Result := NXTOpenWriteLinear(nxtFilename, size, handle) else if filetype = nftData then Result := NXTOpenWriteData(nxtFilename, size, handle) else Result := NXTOpenWrite(nxtFilename, size, handle); if Result then begin buf := nil; GetMem(buf, size); try aStream.Position := 0; // start at the beginning aStream.Read(buf^, size); status := kStatusNoError; iFile_write(handle, buf, size, status); Result := status >= kStatusNoError; finally FreeMem(buf); end; Result := NXTCloseFile(handle) and Result; end; end; end; function TFantomSpirit.NXTPollCommandLen(const bufNum : byte; var count: byte): boolean; var status : integer; begin Result := IsOpen; if not Result then Exit; status := 0; count := Byte(iNXT_pollAvailableLength(fNXTHandle, bufNum, status)); Result := status < kStatusNoError; if not Result then count := 0; end; function TFantomSpirit.NXTPollCommand(const bufNum: byte; var count: byte; var buffer: NXTDataBuffer): boolean; var dataBuffer : PByte; status : Integer; begin Result := IsOpen; if not Result then Exit; if count > 64 then count := 64; dataBuffer := @buffer.Data[0]; status := 0; count := Byte(iNXT_readBufferData(fNXTHandle, dataBuffer, bufNum, count, status)); Result := status >= kStatusNoError; if not Result then count := 0; end; function TFantomSpirit.NXTWriteIOMap(var ModID: Cardinal; const Offset: Word; var count: Word; const buffer: NXTDataBuffer; chkResponse : Boolean): boolean; var status : integer; mh : FantomHandle; modName : string; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; modName := NXTModuleIDToName(ModID); mh := iNXT_createModule(fNXTHandle, PChar(modName), ModID, 0, 0, status); if status >= kStatusNoError then begin // found the correct module status := kStatusNoError; iModule_writeIOMap(mh, Offset, count, @(buffer.Data), status); // now destroy it status := kStatusNoError; iNXT_destroyModule(fNXTHandle, mh, status); if not chkResponse then status := kStatusNoError; end; end; function TFantomSpirit.NXTReadIOMap(var ModID: Cardinal; const Offset: Word; var Count: Word; var buffer: NXTDataBuffer): boolean; var status : integer; mh : FantomHandle; modName : string; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; modName := NXTModuleIDToName(ModID); mh := iNXT_createModule(fNXTHandle, PChar(modName), ModID, 0, 0, status); if status >= kStatusNoError then begin // found the correct module status := kStatusNoError; FillChar(buffer.Data[0], kNXT_MaxBytes, 0); iModule_readIOMap(mh, Offset, Count, @(buffer.Data), status); Result := status = kStatusNoError; // now destroy it status := kStatusNoError; iNXT_destroyModule(fNXTHandle, mh, status); end; end; function TFantomSpirit.NXTFindNextModule(var Handle: FantomHandle; var ModName: string; var ModID, ModSize: Cardinal; var IOMapSize: Word): boolean; var status : integer; Buf : array[0..19] of Char; mh : FantomHandle; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; iModuleIterator_advance(Handle, status); Result := status >= kStatusNoError; if Result then begin mh := iModuleIterator_getModule(Handle, status); status := kStatusNoError; iModule_getName(mh, buf, status); ModName := buf; status := kStatusNoError; ModSize := iModule_getModuleSize(mh, status); status := kStatusNoError; ModID := iModule_getModuleID(mh, status); status := kStatusNoError; IOMapSize := Word(iModule_getIOMapSize(mh, status)); status := kStatusNoError; iNXT_destroyModule(FNXTHandle, mh, status); end else begin // destroy the iterator status := kStatusNoError; iNXT_destroyModuleIterator(fNXTHandle, Handle, status); handle := 0; ModName := ''; end; end; function TFantomSpirit.NXTFindFirstModule(var ModName: string; var Handle: FantomHandle; var ModID, ModSize: Cardinal; var IOMapSize: Word): boolean; var status : integer; buf : array[0..19] of Char; mh : FantomHandle; begin Result := IsOpen; if not Result then Exit; status := kStatusNoError; Handle := iNXT_createModuleIterator(FNXTHandle, PChar(ModName), status); Result := status >= kStatusNoError; if Result then begin mh := iModuleIterator_getModule(Handle, status); status := kStatusNoError; iModule_getName(mh, buf, status); ModName := buf; status := kStatusNoError; ModSize := iModule_getModuleSize(mh, status); status := kStatusNoError; ModID := iModule_getModuleID(mh, status); status := kStatusNoError; IOMapSize := Word(iModule_getIOMapSize(mh, status)); status := kStatusNoError; iNXT_destroyModule(FNXTHandle, mh, status); end; end; function TFantomSpirit.dcBuffer: PByte; begin Result := @dcResponse[0]; end; function TFantomSpirit.GetReplyByte(index: integer): Byte; const DCReplyOffset = 2; begin Result := dcResponse[index + DCReplyOffset]; end; function TFantomSpirit.GetReplyCardinal(index: integer): Cardinal; begin Result := BytesToCardinal(GetReplyByte(index), GetReplyByte(index+1), GetReplyByte(index+2), GetReplyByte(index+3)); end; function TFantomSpirit.GetReplyWord(index: integer): Word; begin Result := Word(BytesToCardinal(GetReplyByte(index), GetReplyByte(index+1))); end; function TFantomSpirit.NXTListBricks(Bricks: TStrings): boolean; var nih : FantomHandle; status, status2 : integer; resNamePC : array[0..255] of Char; resName, alias, tmp : string; begin Result := False; Bricks.Clear; if FantomAPILoaded then begin resName := ''; status := kStatusNoError; // use Fantom API to obtain a handle to an NXT on either USB or bluetooth nih := createNXTIterator(1, BluetoothSearchTimeout, status); while status >= kStatusNoError do begin status2 := kStatusNoError; iNXTIterator_getName(nih, resNamePC, status2); resName := AnsiUpperCase(resNamePC); // if the resource name starts with BTH then grab the beginning of // the resource name and use it as the alias // if the resource name starts with USB then grab the end of the // resource name instead if Pos('BTH', resName) = 1 then begin tmp := Copy(resName, 6, MaxInt); alias := 'BTH::' + Copy(tmp, 1, Pos('::', tmp)-1); end else begin alias := Copy(resName, 23, MaxInt); System.Delete(alias, Length(alias)-4, 5); end; // alias := AnsiLowerCase(Copy(resName, 1, Pos('::', resName)-1)); Bricks.Add(alias + '=' + resName); iNXTIterator_advance(nih, status); end; status := kStatusNoError; destroyNXTIterator(nih, status); // also look for bricks in firmware download mode status := kStatusNoError; iNXT_findDeviceInFirmwareDownloadMode(resNamePC, status); if status >= kStatusNoError then begin resName := AnsiUpperCase(resNamePC); alias := Copy(resName, 23, MaxInt); System.Delete(alias, Length(alias)-4, 5); // alias := AnsiLowerCase(Copy(resName, 1, Pos('::', resName)-1)); Bricks.Add(alias + '=' + resName); end; Result := Bricks.Count > 0; end; end; function TFantomSpirit.GetDownloadWaitTime: Integer; begin Result := 0; end; function TFantomSpirit.GetEEPROM(addr: Byte): Byte; begin Result := addr; end; function TFantomSpirit.GetEEPROMBlock(idx: Integer): EEPROMBlock; begin Result.Data[idx] := 0; // do nothing end; function TFantomSpirit.GetLinkLog: string; begin Result := ''; end; function TFantomSpirit.GetOmitHeader: Boolean; begin Result := False; end; function TFantomSpirit.GetQuiet: Boolean; begin Result := False; end; function TFantomSpirit.GetRCXFirmwareChunkSize: Integer; begin Result := 200; end; function TFantomSpirit.GetRxTimeout: Word; begin Result := 400; end; procedure TFantomSpirit.SetDownloadWaitTime(const Value: Integer); begin // do nothing if Value = 0 then Exit; end; procedure TFantomSpirit.SetEEPROM(addr: Byte; const Value: Byte); begin // do nothing if Value = 0 then Exit; if addr = 0 then Exit; end; procedure TFantomSpirit.SetOmitHeader(const Value: Boolean); begin // do nothing if Value then Exit; end; procedure TFantomSpirit.SetQuiet(const Value: Boolean); begin // do nothing if Value then Exit; end; procedure TFantomSpirit.SetRCXFirmwareChunkSize(const Value: Integer); begin // do nothing if Value = 0 then Exit; end; procedure TFantomSpirit.SetRxTimeout(const Value: Word); begin // do nothing if Value = 0 then Exit; end; function TFantomSpirit.AbsVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if aVar = 0 then Exit; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.AndVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if aVar = 0 then Exit; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.BrickAlive: boolean; begin Result := Open; end; function TFantomSpirit.CalibrateEvent(enum, upper, lower, hysteresis: integer): boolean; begin Result := Open; if enum = 0 then Exit; if upper = 0 then Exit; if lower = 0 then Exit; if hysteresis = 0 then Exit; end; function TFantomSpirit.CalibrateLightSensor: boolean; begin Result := Open; end; function TFantomSpirit.ClearAllEvents: boolean; begin Result := Open; end; function TFantomSpirit.ClearCounter(num: TCounterNumber): boolean; begin Result := Open; if num = 0 then Exit; end; function TFantomSpirit.ClearSound: boolean; begin Result := Open; end; function TFantomSpirit.ClearTachoCounter(aMotorList: Byte): boolean; var i : Byte; begin Result := Open; if Result then begin for i := 0 to 2 do begin if (MotorBits[i] and aMotorList) = MotorBits[i] then begin Result := Result and ResetOutputPosition(i, False); if not Result then Break; end; end; end; end; function TFantomSpirit.ClearTimer(aNum: integer): boolean; begin Result := Open; if aNum = 0 then Exit; end; function TFantomSpirit.DatalogNext(aSrc, aNum: integer): boolean; begin Result := Open; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.DecCounter(num: TCounterNumber): boolean; begin Result := Open; if num = 0 then Exit; end; function TFantomSpirit.DeleteAllSubs: boolean; begin Result := Open; end; function TFantomSpirit.DeleteAllTasks: boolean; begin Result := Open; end; function TFantomSpirit.DeleteSub(aSub: integer): boolean; begin Result := Open; if aSub = 0 then Exit; end; function TFantomSpirit.DeleteTask(aTask: integer): boolean; begin Result := Open; if aTask = 0 then Exit; end; function TFantomSpirit.DivVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if aVar = 0 then Exit; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.DownloadMemoryMap: TStrings; var SL : TStringList; i, p, id : integer; tmp : string; begin fMemMap.Clear; SL := TStringList.Create; try fMemMap.Add('Files'); fMemMap.Add(''); if NXTListFiles('*.*', SL) then begin for i := 0 to SL.Count - 1 do begin fMemMap.Add(SL.Names[i]); fMemMap.Add(SL.ValueFromIndex[i]); end; end; SL.Clear; fMemMap.Add(''); fMemMap.Add(''); fMemMap.Add('Modules'); fMemMap.Add(''); if NXTListModules('*.*', SL) then begin for i := 0 to SL.Count - 1 do begin fMemMap.Add(SL.Names[i]); tmp := SL.ValueFromIndex[i]; // tmp = moduleID, size, iosize p := Pos(',', tmp); id := StrToIntDef(Copy(tmp, 1, p-1), 0); Delete(tmp, 1, p); p := Pos(',', tmp); Delete(tmp, 1, p); fMemMap.Add(IntToStr(id)+'|'+tmp); // moduleID|iomap size end; end; fMemMap.Add(''); fMemMap.Add(''); i := NXTFreeMemory; fMemMap.Add('Free Memory'); fMemMap.Add(IntToStr(i)); finally SL.Free; end; Result := fMemMap; end; function TFantomSpirit.Drive(aLeft, aRight: integer): boolean; begin Result := Open; if aLeft = 0 then Exit; if aRight = 0 then Exit; end; function TFantomSpirit.GetCounterValue(aNum: integer): integer; begin Result := Poll(kRCX_CounterType, aNum); end; function TFantomSpirit.GetMessageValue(aNum: integer): integer; begin Result := Poll(kRCX_MessageType, aNum); end; function TFantomSpirit.GetOutputStatus(aOut: integer): integer; var res : boolean; mode, regmode, runstate : byte; power, turnratio : integer; tacholimit : cardinal; tachocount, blocktachocount, rotationcount : integer; bBrake : boolean; begin Result := 0; rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; power := 0; res := GetNXTOutputState(Byte(aOut), power, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); if res then begin // what is the power? fMotorOn[aOut] := ((mode and OUT_MODE_MOTORON) = OUT_MODE_MOTORON) and ((runstate and OUT_RUNSTATE_RUNNING) = OUT_RUNSTATE_RUNNING) and (power <> 0); bBrake := (mode and OUT_MODE_BRAKE) = OUT_MODE_BRAKE; // if the power is 0 and fMotorOn[aOut] is false then do not change // the stored power level if fMotorOn[aOut] then fMotorPower[aOut] := Byte(abs(power div 14) mod 8); fMotorForward[aOut] := power >= 0; Result := fMotorPower[aOut]; // bits 0..2 if fMotorForward[aOut] then Result := Result + (1 shl 3); // bit 3 if bBrake then Result := Result + (1 shl 6); // bit 6 if fMotorOn[aOut] then Result := Result + (1 shl 7); // bit 7 end; end; function TFantomSpirit.GetTimerValue(aNum: integer): integer; begin Result := Poll(kRCX_TimerType, aNum); end; function TFantomSpirit.GetVariableValue(aVar: integer): variant; begin Result := Poll(kRCX_VariableType, aVar); end; function TFantomSpirit.IncCounter(num: TCounterNumber): boolean; begin Result := Open; if num = 0 then Exit; end; function TFantomSpirit.MonitorIR(aSeconds: integer): TStrings; begin Result := fMemData; if aSeconds = 0 then Exit; end; function TFantomSpirit.MulVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if aVar = 0 then Exit; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.OnWait(aMotorList: Byte; aNum: integer; aTime: Byte): boolean; begin Result := Open; if aMotorList = 0 then Exit; if aNum = 0 then Exit; if aTime = 0 then Exit; end; function TFantomSpirit.OnWaitDifferent(aMotorList: Byte; aNum0, aNum1, aNum2: integer; aTime: Byte): boolean; begin Result := Open; if aMotorList = 0 then Exit; if aNum0 = 0 then Exit; if aNum1 = 0 then Exit; if aNum2 = 0 then Exit; if aTime = 0 then Exit; end; function TFantomSpirit.OrVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if aVar = 0 then Exit; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.PlaySystemSound(aSnd: byte): boolean; begin Result := Open; if aSnd = 0 then Exit; end; function TFantomSpirit.Poll(aSrc, aNum: integer): variant; var valid, calibrated, res : boolean; stype, smode : byte; raw, normalized : word; scaled, calvalue : smallint; modID : Cardinal; count : Word; buffer : NXTDataBuffer; power, turnratio, tachocount, blocktachocount, rotationcount : integer; mode, regmode, runstate : byte; tacholimit : cardinal; protmin, protmaj, firmmin, firmmaj : byte; begin Result := 0; case aSrc of kRCX_VariableType : begin Result := GetNXTVariableHelper(aNum, 0, 0, 18); end; kRCX_ConstantType : begin Result := aNum; end; kRCX_OutputStatusType : begin Result := GetOutputStatus(aNum); end; kRCX_RandomType : begin Result := Random(aNum); end; kRCX_TachCounterType : begin rotationcount := 0; blocktachocount := 0; tachocount := 0; tacholimit := 0; runstate := 0; turnratio := 0; mode := 0; regmode := 0; power := 0; res := GetNXTOutputState(Byte(aNum), power, mode, regmode, turnratio, runstate, tacholimit, tachocount, blocktachocount, rotationcount); if res then Result := rotationcount; end; kRCX_TimerType : begin // IOMapRead CommandOffsetTick modID := kNXT_ModuleCmd; count := 4; buffer.Data[0] := 0; res := NXTReadIOMap(modID, CommandOffsetTick, count, buffer); if res then begin Result := BytesToCardinal(buffer.Data[0], buffer.Data[1], buffer.Data[2], buffer.Data[3]); end; end; kRCX_BatteryLevelType : begin Result := BatteryLevel; end; kRCX_FirmwareVersionType : begin firmmaj := 0; firmmin := 0; protmin := 0; protmaj := 0; if NXTGetVersions(protmin, protmaj, firmmin, firmmaj) then begin // 1.03 => 1030 Result := (firmmaj * 100) + firmmin; end; end; kRCX_InputTypeType, kRCX_InputModeType, kRCX_InputValueType, kRCX_InputRawType, kRCX_InputBooleanType : begin // get input type or input mode calibrated := False; stype := 0; smode := 0; raw := 0; normalized := 0; scaled := 0; calvalue := 0; valid := False; res := GetNXTInputValues(Byte(aNum), valid, calibrated, stype, smode, raw, normalized, scaled, calvalue); if res then begin if aSrc = kRCX_InputTypeType then begin fSensorType[aNum] := stype; Result := stype; end else if aSrc = kRCX_InputModeType then begin fSensorMode[aNum] := smode; Result := smode; end else if aSrc = kRCX_InputValueType then begin Result := scaled; // normalized? end else if aSrc = kRCX_InputRawType then begin Result := raw; end else if aSrc = kRCX_InputBooleanType then begin Result := scaled; end; end; end; end; end; function TFantomSpirit.PollEEPROM(block: Integer): TStrings; var i, j, start, finish, status : Integer; mh : FantomHandle; Offset, cnt : Cardinal; buf : PByte; const MAX_BLOCK = $803; BLOCK_SIZE = $10; begin Open; Result := fMemData; fMemData.Clear; start := block; finish := block; if block < 0 then begin start := 0; finish := MAX_BLOCK; end else if block > MAX_BLOCK then begin start := MAX_BLOCK; finish := MAX_BLOCK; end; status := 0; mh := iNXT_createModule(fNXTHandle, PChar(kNXT_ModuleCmdName), kNXT_ModuleCmd, 0, 0, status); // are we in a position to poll memory? if status >= kStatusNoError then begin buf := nil; GetMem(buf, BLOCK_SIZE); try for j := start to finish do begin status := kStatusNoError; Offset := j*BLOCK_SIZE; cnt := iModule_readIOMap(mh, Offset, BLOCK_SIZE, buf, status); if status >= kStatusNoError then begin for i := 0 to Integer(cnt) - 1 do begin fMemData.Add(Format('%d', [PByte(PChar(buf) + i)^])); end; end else Break; end; finally FreeMem(buf); end; // now destroy the module handle status := kStatusNoError; iNXT_destroyModule(fNXTHandle, mh, status); end; end; function TFantomSpirit.PollMemory(address, size: Integer): TStrings; var status, cnt : integer; mh : FantomHandle; Offset : Cardinal; amt, i : Integer; buf : PByte; const // CHUNK = $FFFF; CHUNK = $36; begin Open; fMemData.Clear; Result := fMemData; status := 0; mh := iNXT_createModule(fNXTHandle, PChar(kNXT_ModuleCmdName), kNXT_ModuleCmd, 0, 0, status); // are we in a position to poll memory? if status >= kStatusNoError then begin // found the Command module now use it Offset := address; amt := 0; buf := nil; GetMem(buf, CHUNK); try while (amt < size) and (status >= kStatusNoError) do begin status := kStatusNoError; cnt := Min(CHUNK, size-amt); cnt := iModule_readIOMap(mh, Offset, cnt, buf, status); if status >= kStatusNoError then begin for i := 0 to cnt - 1 do begin fMemData.Add(Format('%d', [PByte(PChar(buf) + i)^])); end; end; inc(amt, CHUNK); inc(Offset, CHUNK); end; finally FreeMem(buf); end; // now destroy the module handle status := kStatusNoError; iNXT_destroyModule(fNXTHandle, mh, status); end; end; function TFantomSpirit.PowerDownTime(aTime: integer): boolean; var modID : Cardinal; count : Word; buffer : NXTDataBuffer; begin Result := Open; if not Result then Exit; modID := kNXT_ModuleUI; count := 1; buffer.Data[0] := Byte(abs(aTime) mod $FF); Result := NXTWriteIOMap(modID, UIOffsetSleepTimeout, count, buffer); end; function TFantomSpirit.PrepareBrick: boolean; begin Result := Open; end; function TFantomSpirit.Scout(bPower: boolean): boolean; begin Result := Open and bPower; end; function TFantomSpirit.ScoutNum(aVal: integer): boolean; begin Result := Open; if aVal = 0 then Exit; end; function TFantomSpirit.ScoutRules(motion: TScoutMotion; touch: TScoutTouch; light: TScoutLight; time: TScoutScale; fx: TScoutEffects): boolean; begin Result := Open; if motion = smNone then Exit; if touch = stIgnore then Exit; if light = slIgnore then Exit; if time = ssShort then Exit; if fx = seNone then Exit; end; function TFantomSpirit.ScoutSound(bSoundEnable, bSoundOff: boolean; aNum: TSoundSetNumber): boolean; begin Result := Open and bSoundEnable and bSoundOff; if aNum = 0 then Exit; end; function TFantomSpirit.SelectDisplay(aSrc, aNumber: integer): boolean; begin Result := Open; if aSrc = 0 then Exit; if aNumber = 0 then Exit; end; function TFantomSpirit.SelectProgram(aProg: integer): boolean; begin Result := Open; if aProg = 0 then Exit; end; function TFantomSpirit.SendMessage(aMsg: integer): boolean; begin Result := MessageWrite(0, IntToStr(aMsg)); end; function TFantomSpirit.SendRawCommand(aCmd: string; bRetry: boolean): string; var SL : TStringList; data : array of byte; status, i, j : integer; cmdType, reqResp, len : byte; tmpStr : string; scBuffer : PByte; begin Result := ''; if Length(aCmd) = 0 then Exit; FillChar(scResponse, 64, 0); // the raw command is either a system command or a direct command // formatted as a series of 2digit hex bytes separated by a comma. // first byte tells whether system or direct. SL := TStringList.Create; try if aCmd[Length(aCmd)] = ',' then System.Delete(aCmd, Length(aCmd), 1); SL.CommaText := aCmd; if SL.Count < 2 then Exit; // convert string to array of bytes // check that each byte is valid SetLength(data, SL.Count-1); j := StrToIntDef('$'+SL[0], -1); if (j < 0) or (j > 255) then Exit; cmdType := Byte(j); for i := 1 to SL.Count - 1 do begin tmpStr := SL[i]; j := StrToIntDef('$'+tmpStr, -1); if (j < 0) or (j > 255) then break; data[i-1] := Byte(j); end; finally SL.Free; end; // call system or direct command functions if it looks like it is a valid // command status := kStatusNoError; reqResp := Byte((cmdType and $80) <> $80); cmdType := cmdType and $7F; if reqResp <> 0 then begin len := NXT_CMD_RESPONSE_LENGTH[data[0]]-1; scBuffer := @scResponse[0]; end else begin len := 0; scBuffer := nil; end; if cmdType = $01 then iNXT_sendSystemCommand(fNXTHandle, reqResp, @data[0], Length(data), scBuffer, len, status) else if cmdType = $00 then iNXT_sendDirectCommandEnhanced(fNXTHandle, reqResp, @data[0], Length(data), scBuffer, len, status) else Exit; if status >= kStatusNoError then begin for i := 0 to len - 1 do begin Result := Result + Format('%2.2x ', [scResponse[i]]); end; Result := Trim(Result); end; end; function TFantomSpirit.SendRemoteStr(aEvent: string; aRepeat: integer): boolean; begin Result := Open; if aEvent = '' then Exit; if aRepeat = 0 then Exit; end; function TFantomSpirit.SendRemote(aEvent: Word; aRepeat: integer): boolean; begin Result := Open; if aEvent = 0 then Exit; if aRepeat = 0 then Exit; end; function TFantomSpirit.SendUARTData(start, size: integer): boolean; begin Result := Open; if start = 0 then Exit; if size = 0 then Exit; end; function TFantomSpirit.SendVLL(aSrc, aNum: integer): boolean; begin Result := Open; if aSrc = 0 then Exit; if aNum = 0 then Exit; end; function TFantomSpirit.SetCounterLimit(num: TCounterNumber; src: TTCSource; val: integer): boolean; begin Result := Open; if num = 0 then Exit; if src = tcVariable then Exit; if val = 0 then Exit; end; function TFantomSpirit.SetDatalog(aSize: integer): boolean; begin Result := Open; if aSize = 0 then Exit; end; function TFantomSpirit.SetEvent(enum, snum, etype: integer): boolean; begin Result := Open; if (enum = 0) or (snum = 0) or (etype = 0) then Exit; end; function TFantomSpirit.SetFeedback(src, val: integer): boolean; begin Result := Open; if (src = 0) or (val = 0) then Exit; end; function TFantomSpirit.SetGlobalDirection(motors: TMotorsNum; action: TGlobalDirAction): boolean; begin Result := Open; if (motors = 0) or (action = gdaBackward) then Exit; end; function TFantomSpirit.SetGlobalOutput(motors: TMotorsNum; action: TGlobalOutAction): boolean; begin Result := Open; if (motors = 0) or (action = goaFloat) then Exit; end; function TFantomSpirit.SetLight(bOn: boolean): boolean; begin Result := Open and bOn; end; function TFantomSpirit.SetLightSensorBlinkTime(src: TLSSource; val: TBlinkTimeValue): boolean; begin Result := Open; if (src = lsVariable) or (val = 0) then Exit; end; function TFantomSpirit.SetLightSensorHysteresis(src: TLSSource; val: TThresholdValue): boolean; begin Result := Open; if (src = lsVariable) or (val = 0) then Exit; end; function TFantomSpirit.SetLightSensorLowerThreshold(src: TLSSource; val: TThresholdValue): boolean; begin Result := Open; if (src = lsVariable) or (val = 0) then Exit; end; function TFantomSpirit.SetLightSensorUpperThreshold(src: TLSSource; val: TThresholdValue): boolean; begin Result := Open; if (src = lsVariable) or (val = 0) then Exit; end; function TFantomSpirit.SetMaxPower(motors: TMotorsNum; src, num: integer): boolean; begin Result := Open; if (motors = 0) or (src = 0) or (num = 0) then Exit; end; function TFantomSpirit.SetSourceValue(aDestSrc, aDestVal, aOrigSrc: Byte; aOrigVal: Smallint): boolean; begin Result := Open; if (aDestSrc = 0) or (aDestVal = 0) or (aOrigSrc = 0) or (aOrigVal = 0) then Exit; end; function TFantomSpirit.SetTimerLimit(num: TTimerNumber; src: TTCSource; val: integer): boolean; begin Result := Open; if (val = 0) or (src = tcVariable) or (num = 0) then Exit; end; function TFantomSpirit.SetVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if (aVar = 0) or (aSrc = 0) or (aNum = 0) then Exit; end; function TFantomSpirit.SetWatch(aTime: string): boolean; begin Result := Open; if aTime = '' then Exit; end; function TFantomSpirit.SetWatchHHMM(aHrs, aMins: integer): boolean; begin Result := Open; if (aHrs = 0) or (aMins = 0) then Exit; end; function TFantomSpirit.SgnVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if (aVar = 0) or (aSrc = 0) or (aNum = 0) then Exit; end; function TFantomSpirit.StartTask(aTask: integer): boolean; begin Result := Open; if aTask = 0 then Exit; end; function TFantomSpirit.StopAllTasks: boolean; begin Result := Open; end; function TFantomSpirit.StopTask(aTask: integer): boolean; begin Result := Open; if aTask = 0 then Exit; end; function TFantomSpirit.SubVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if (aVar = 0) or (aSrc = 0) or (aNum = 0) then Exit; end; function TFantomSpirit.SumVar(aVar, aSrc, aNum: integer): boolean; begin Result := Open; if (aVar = 0) or (aSrc = 0) or (aNum = 0) then Exit; end; function TFantomSpirit.TowerExists: boolean; begin Result := Open; end; function TFantomSpirit.TransmitPower(aLevel: TTransmitLevel): boolean; begin Result := Open; if aLevel = tlNear then Exit; end; function TFantomSpirit.UnlockBrick: string; begin Open; Result := ''; end; function TFantomSpirit.UnlockFirmware: boolean; begin Result := Open; end; function TFantomSpirit.UploadDatalog(bVerbose: boolean): TStrings; begin Open; Result := fDataLog; if bVerbose then Exit; end; function TFantomSpirit.UploadPartialDatalog(aFrom, aSize: integer): TStrings; begin Open; Result := fDataLog; if aFrom = 0 then Exit; if aSize = 0 then Exit; end; function TFantomSpirit.Version(var rom, ram: Cardinal): boolean; var protmin, protmaj, firmmin, firmmaj : byte; begin firmmaj := 0; firmmin := 0; protmin := 0; protmaj := 0; Result := NXTGetVersions(protmin, protmaj, firmmin, firmmaj); rom := (protmin shl 8) + (protmaj shl 16); ram := (firmmin shl 0) + (firmmaj shl 16); end; function TFantomSpirit.ViewSourceValue(prec, src, value: integer): boolean; begin Result := Open; if (prec = 0) or (src = 0) or (value = 0) then Exit; end; function TFantomSpirit.GetUseBT: Boolean; begin DebugFmt('TFantomSpirit.GetUseBT: fUseBT was = %s', [BoolToStr(fUseBT)]); DebugFmt('TFantomSpirit.GetUseBT: fResPort = %s', [fResPort]); DebugFmt('TFantomSpirit.GetUseBT: (Pos(''BTH'', fResPort) > 0) = %s', [BoolToStr((Pos('BTH', fResPort) > 0))]); Result := fUseBT or (Pos('BTH', fResPort) > 0); if Result then fUseBT := True; DebugFmt('TFantomSpirit.GetUseBT: fUseBT now = %s', [BoolToStr(fUseBT)]); end; procedure TFantomSpirit.NXTInitializeResourceNames; var SL : TStringList; name : string; begin SL := TStringList.Create; try NXTListBricks(SL); name := GetInitFilename; ForceDirectories(ExtractFilePath(name)); SL.Sort; SL.SaveToFile(name); finally SL.Free; end; end; function TFantomSpirit.NXTFreeMemory: integer; var memFree, BTSig : Cardinal; nxtName, nxtAddr : string; begin Result := 0; memFree := 0; BTSig := 0; nxtName := ''; nxtAddr := ''; if NXTGetDeviceInfo(nxtName, nxtAddr, BTSig, memFree) then begin Result := memFree; end; end; function TFantomSpirit.NXTRenameFile(const old, new: string; const chkResponse: boolean): boolean; var cmd : TNxtCmd; status : integer; b : byte; buf, readBuf : PByte; bufLen : Cardinal; begin Result := Open; if not Result then Exit; cmd := TNxtCmd.Create; try if chkResponse then b := kNXT_SystemCmd else b := kNXT_SystemCmdNoReply; cmd.MakeCmdRenameFile(b, new, old); // cmd.MakeCmdRenameFile(b, old, new); buf := cmd.GetBody; bufLen := cmd.GetLength; status := kStatusNoError; iNXT_write(fNXTHandle, buf, bufLen, status); // now read the response if (status >= kStatusNoError) and chkResponse then begin readBuf := nil; GetMem(readBuf, 44); try iNXT_read(fNXTHandle, readBuf, 44, status); finally FreeMem(readBuf); end; end; Result := status >= kStatusNoError; finally cmd.Free; end; end; procedure TFantomSpirit.SetResourcePort(const name: string); var sl : TStringList; i : integer; fname : string; begin fResPort := name; sl := TStringList.Create; try fname := GetInitFilename; if FileExists(fname) then begin sl.LoadFromFile(fname); for i := 0 to sl.Count - 1 do begin if Pos(fResPort, sl[i]) > 0 then Exit; end; // if we get here then we need to add this resource string to // our nxt.dat file sl.Add('alias' + IntToStr(sl.Count) + '=' + fResPort); sl.SaveToFile(fname); end; finally sl.Free; end; end; procedure TFantomSpirit.LookupResourceName; var name : string; i : integer; begin // lookup a resource string given this port name if fResourceNames.Count = 0 then begin name := GetInitFilename; if FileExists(name) then begin fResourceNames.LoadFromFile(name); end; end; i := fResourceNames.IndexOfName(fPort); if i <> -1 then fResPort := fResourceNames.Values[fPort]; end; function TFantomSpirit.GetVMState(var state: byte; var clump : byte; var pc : word): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetVMState); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 6, status, True); Result := status >= kStatusNoError; state := GetReplyByte(0); clump := GetReplyByte(1); pc := GetReplyWord(2); finally cmd.Free; end; end; function TFantomSpirit.SetVMStateEx(var state, clump: byte; var pc: word): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCSetVMState, state); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 6, status, True); Result := status >= kStatusNoError; state := GetReplyByte(0); clump := GetReplyByte(1); pc := GetReplyWord(2); finally cmd.Free; end; end; function TFantomSpirit.SetVMState(const state: byte): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCSetVMState, state); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status, True); Result := status >= kStatusNoError; finally cmd.Free; end; end; function TFantomSpirit.GetPropDebugging(var debugging : boolean; var pauseClump: byte; var pausePC: Word): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetProperty, kNXT_Property_Debugging); iNXT_sendDirectCommandEnhanced(fNXTHandle, 1, cmd.BytePtr, cmd.Len, dcBuffer, 6, status, True); Result := status >= kStatusNoError; debugging := Boolean(GetReplyByte(0)); pauseClump := GetReplyByte(1); pausePC := GetReplyWord(2); finally cmd.Free; end; end; function TFantomSpirit.SetPropDebugging(const debugging : boolean; const pauseClump: byte; const pausePC: Word): boolean; var cmd : TNINxtCmd; status : integer; begin Result := IsOpen; if not Result then Exit; cmd := TNINxtCmd.Create; try status := kStatusNoError; cmd.SetVal(kNXT_DirectCmdNoReply, kNXT_DCSetProperty, kNXT_Property_Debugging, Ord(debugging), pauseClump, Lo(pausePC), Hi(pausePC)); iNXT_sendDirectCommandEnhanced(fNXTHandle, 0, cmd.BytePtr, cmd.Len, nil, 0, status, True); Result := status >= kStatusNoError; finally cmd.Free; end; end; procedure TFantomSpirit.NXTUpdateResourceNames; var SL, tmpSL : TStringList; fname : string; begin SL := TStringList.Create; try SL.Sorted := True; SL.Duplicates := dupIgnore; tmpSL := TStringList.Create; try NXTListBricks(tmpSL); fname := GetInitFilename; if FileExists(fname) then SL.LoadFromFile(fname); SL.AddStrings(tmpSL); ForceDirectories(ExtractFilePath(fname)); SL.SaveToFile(fname); finally tmpSL.Free; end; finally SL.Free; end; end; procedure TFantomSpirit.LookupOffsetsIfNeeded; var modID : Cardinal; count : Word; buffer : NXTDataBuffer; res : boolean; begin // lookup our offsets if needed if (fOffsetDS = MaxInt) and (fOffsetDVA = MaxInt) then begin modID := kNXT_ModuleCmd; count := 4; buffer.Data[0] := 0; res := NXTReadIOMap(modID, CommandOffsetOffsetDS, count, buffer); if res then begin fOffsetDS := Word(BytesToCardinal(buffer.Data[0], buffer.Data[1])); fOffsetDVA := Word(BytesToCardinal(buffer.Data[2], buffer.Data[3])); end; end else if fOffsetDS = MaxInt then begin // IOMapRead CommandOffsetOffsetDS modID := kNXT_ModuleCmd; count := 2; buffer.Data[0] := 0; res := NXTReadIOMap(modID, CommandOffsetOffsetDS, count, buffer); if res then fOffsetDS := Word(BytesToCardinal(buffer.Data[0], buffer.Data[1])); end else if fOffsetDVA = MaxInt then begin // IOMapRead CommandOffsetOffsetDVA modID := kNXT_ModuleCmd; count := 2; buffer.Data[0] := 0; res := NXTReadIOMap(modID, CommandOffsetOffsetDVA, count, buffer); if res then fOffsetDVA := Word(BytesToCardinal(buffer.Data[0], buffer.Data[1])); end; end; function TFantomSpirit.GetNXTVariableHelper(aNum, aIdx, aCount, aDigits: integer): variant; var modID, cval : Cardinal; count, dvindex, dvoff, dvsize, dvcount, totalbytes, idx, dims : Word; buffer : NXTDataBuffer; offset, size, vartype, ival : integer; tmpoffset, tmpsize, tmpvartype : integer; dst : TDSType; res : boolean; buf : array of Byte; tmpVar : Variant; fval : Single; begin Result := 0; LookupOffsetsIfNeeded; if (fOffsetDS <> $FFFF) and (fOffsetDVA <> $FFFF) then begin modID := kNXT_ModuleCmd; DoGetVarInfoByID(aNum, offset, size, vartype); if (offset <> -1) and (size <> -1) and (vartype <> -1) then begin dst := TDSType(Byte(vartype)); // if vartype == scalar type then if dst in [dsUByte, dsSByte, dsUWord, dsSWord, dsULong, dsSLong, dsFloat] then begin // IOMapRead from fOffsetDS+offset, size bytes count := size; // variable size buffer.Data[0] := 0; res := NXTReadIOMap(modID, fOffsetDS+offset, count, buffer); if res then begin Result := GetVariantFromByteArray(dst, buffer.Data, 0); end; end else if dst = dsArray then begin // TODO: this code only supports 1-dimensional arrays!!!!! // Fix it to support N-dimensions dims := 0; // how many dimensions are there? // what is the base array type? idx := 1; while dst = dsArray do begin DoGetVarInfoByID(aNum+idx, tmpoffset, tmpsize, tmpvartype); if (tmpoffset <> -1) and (tmpsize <> -1) and (tmpvartype <> -1) then dst := TDSType(Byte(tmpvartype)) else break; inc(idx); inc(dims); end; if (offset <> -1) and (size <> -1) and (vartype <> -1) and (dims = 1) then begin // read aCount elements starting at aIdx // first get dope vector index count := 2; // get a UWORD for the DVIndex buffer.Data[0] := 0; res := NXTReadIOMap(modID, fOffsetDS+offset, count, buffer); if res then begin dvindex := Word(BytesToCardinal(buffer.Data[0], buffer.Data[1])); // now get this array's dope vector information count := 6; // get 3 UWORD values from the dope vector array buffer.Data[0] := 0; res := NXTReadIOMap(modID, fOffsetDVA+(10*dvindex), count, buffer); if res then begin dvoff := Word(BytesToCardinal(buffer.Data[0], buffer.Data[1])); dvsize := Word(BytesToCardinal(buffer.Data[2], buffer.Data[3])); dvcount := Word(BytesToCardinal(buffer.Data[4], buffer.Data[5])); // I can read up to ~50 bytes at a time so try to optimize this, if possible // the user has requested aCount elements (0 == 1) if aCount = 0 then aCount := 1; if (aIdx + aCount) > dvcount then aCount := dvcount-aIdx; dvoff := dvoff + aIdx*dvsize; // move the offset forward to the specified element index // number of bytes to read is dvsize*aCount but maxed out at dvsize*dvcount totalbytes := dvsize*aCount; // total number of bytes SetLength(buf, totalbytes); idx := 0; while totalbytes > 0 do begin count := Min(56, totalbytes); res := NXTReadIOMap(modID, fOffsetDS+dvoff+idx, count, buffer); if not res then Exit; Move(buffer.Data[0], buf[idx], count); inc(idx, count); dec(totalbytes, count); end; // we have filled our byte array with all the values we need Result := ''; // empty string for idx := 0 to aCount - 1 do begin if dst in [dsUByte, dsSByte, dsUWord, dsSWord, dsULong, dsSLong, dsFloat] then begin tmpVar := GetVariantFromByteArray(dst, buf, idx); case dst of dsUByte, dsSByte, dsUWord, dsSWord, dsSLong : begin ival := tmpVar; Result := Result + Format('%d ', [ival]); end; dsULong : begin cval := tmpVar; Result := Result + Format('%d ', [cval]); end; else // dsFloat fval := tmpVar; Result := Result + Format('%.4f ', [fval]); end; end else if dst = dsCluster then begin // ??? end; end; end; end; end else Result := 0; end else if dst = dsCluster then begin // output all the structure fields as a string end; end; end; end; function TFantomSpirit.GetVariantFromByteArray(dst: TDSType; buf: array of byte; idx: integer): variant; begin case dst of dsUByte : Result := Integer(buf[idx]); dsSByte : Result := Integer(Char(buf[idx])); dsUWord : Result := Integer(Word(BytesToCardinal(buf[idx*2], buf[(idx*2)+1]))); dsSWord : Result := Integer(SmallInt(BytesToCardinal(buf[idx*2], buf[(idx*2)+1]))); dsULong : Result := BytesToCardinal(buf[idx*4], buf[(idx*4)+1], buf[(idx*4)+2], buf[(idx*4)+3]); dsSLong : Result := Integer(BytesToCardinal(buf[idx*4], buf[(idx*4)+1], buf[(idx*4)+2], buf[(idx*4)+3])); dsFloat : Result := CardinalToSingle(BytesToCardinal(buf[idx*4], buf[(idx*4)+1], buf[(idx*4)+2], buf[(idx*4)+3])); else Result := 0; end; end; end. bricktools/FANTOM_CONST.INC0000644000175000017500000000741611537752657015130 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) const kBufferStandard = 0; kBufferHighSpeed = 1; kStatusNoError = 0; kStatusOffset = -142000; // 0x550 kStatusFirst = (kStatusOffset + 0); // 0x550 kStatusPairingFailed = (kStatusOffset + -5); // 0x54B kStatusBluetoothSearchFailed = (kStatusOffset + -6); // 0x54A kStatusSystemLibraryNotFound = (kStatusOffset + -7); // 0x549 kStatusUnpairingFailed = (kStatusOffset + -8); // 0x548 kStatusInvalidFilename = (kStatusOffset + -9); // 0x547 kStatusInvalidIteratorDereference = (kStatusOffset + -10); // 0x546 kStatusLockOperationFailed = (kStatusOffset + -11); // 0x545 kStatusSizeUnknown = (kStatusOffset + -12); // 0x544 kStatusDuplicateOpen = (kStatusOffset + -13); // 0x543 kStatusEmptyFile = (kStatusOffset + -14); // 0x542 kStatusFirmwareDownloadFailed = (kStatusOffset + -15); // 0x541 kStatusPortNotFound = (kStatusOffset + -16); // 0x540 kStatusNoMoreItemsFound = (kStatusOffset + -17); // 0x53F kStatusTooManyUnconfiguredDevices = (kStatusOffset + -18); // 0x53E kStatusCommandMismatch = (kStatusOffset + -19); // 0x53D kStatusIllegalOperation = (kStatusOffset + -20); // 0x53C kStatusBluetoothCacheUpdateFailed = (kStatusOffset + -21); // 0x53B kStatusNonNXTDeviceSelected = (kStatusOffset + -22); // 0x53A kStatusFeatureNotImplemented = (kStatusOffset + -99); // 0x4ED kStatusFWIllegalHandle = (kStatusOffset + -189); // 0x493 kStatusFWIllegalFileName = (kStatusOffset + -190); // 0x492 kStatusFWOutOfBounds = (kStatusOffset + -191); // 0x491 kStatusFWModuleNotFound = (kStatusOffset + -192); // 0x490 kStatusFWFileExists = (kStatusOffset + -193); // 0x48F kStatusFWFileIsFull = (kStatusOffset + -194); // 0x48E kStatusFWAppendNotPossible = (kStatusOffset + -195); // 0x48D kStatusFWNoWriteBuffers = (kStatusOffset + -196); // 0x48C kStatusFWFileIsBusy = (kStatusOffset + -197); // 0x48B kStatusFWUndefinedError = (kStatusOffset + -198); // 0x48A kStatusFWNoLinearSpace = (kStatusOffset + -199); // 0x489 kStatusFWHandleAlreadyClosed = (kStatusOffset + -200); // 0x488 kStatusFWFileNotFound = (kStatusOffset + -201); // 0x487 kStatusFWNotLinearFile = (kStatusOffset + -202); // 0x486 kStatusFWEndOfFile = (kStatusOffset + -203); // 0x485 kStatusFWEndOfFileExpected = (kStatusOffset + -204); // 0x484 kStatusFWNoMoreFiles = (kStatusOffset + -205); // 0x483 kStatusFWNoSpace = (kStatusOffset + -206); // 0x482 kStatusFWNoMoreHandles = (kStatusOffset + -207); // 0x481 kStatusFWUnknownErrorCode = (kStatusOffset + -208); // 0x480 kStatusLast = (kStatusOffset + -999); bricktools/fantomfpc.pas0000644000175000017500000024273011537752657015325 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit FANTOMFPC; interface uses {$IFDEF WIN32}Windows,{$ENDIF}libusb, BaseUnix, termio, unix, FantomDefs; {$I FANTOM_CONST.INC} function createNXT(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; function createNXTIterator(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; function iFile_getAvailableSize(fileHandle : FantomHandle; var status : integer) : Cardinal; function iFile_getSize(fileHandle : FantomHandle; var status : integer) : Cardinal; function iFileIterator_getFile(iterHandle : FantomHandle; var status : integer) : FantomHandle; function iFileIterator_getSize(fileIterHandle : FantomHandle; var status : integer) : Cardinal; function iModule_getIOMapSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; function iModule_getModuleID(moduleHandle : FantomHandle; var status : integer) : Cardinal; function iModule_getModuleSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; function iModule_readIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; function iModule_writeIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; function iModuleIterator_getModule(modIterHandle : FantomHandle; var status : integer) : FantomHandle; function iNXT_createFile(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; function iNXT_createFileIterator(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; function iNXT_createModule(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; function iNXT_createModuleIterator(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; function iNXT_pollAvailableLength(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; function iNXT_readBufferData(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; function iNXT_write(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; function iNXTIterator_getNXT(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; procedure destroyNXT(nxtHandle : FantomHandle; var status : integer); procedure destroyNXTIterator(nxtIteratorHandle : FantomHandle; var status : integer); procedure iFile_close(fileHandle : FantomHandle; var status : integer); procedure iFile_getName(fileHandle : FantomHandle; filename : PChar; var status : integer); procedure iFile_openForDataAppend(fileHandle : FantomHandle; var status : integer); procedure iFile_openForDataWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); procedure iFile_openForLinearWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); procedure iFile_openForRead(fileHandle : FantomHandle; var status : integer); procedure iFile_openForWrite(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); procedure iFile_read(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); procedure iFile_remove(fileHandle : FantomHandle; var status : integer); procedure iFile_write(fileHandle : FantomHandle; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); procedure iFileIterator_advance(iterHandle : FantomHandle; var status : integer); procedure iFileIterator_getName(iterHandle : FantomHandle; filename : PChar; var status : integer); procedure iModule_getName(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); procedure iModuleIterator_advance(modIterHandle : FantomHandle; var status : integer); procedure iModuleIterator_getName(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); procedure iNXT_bluetoothFactoryReset(nxtHandle : FantomHandle; var status : integer); procedure iNXT_bootIntoFirmwareDownloadMode(resourceName : PChar; var status : integer); procedure iNXT_destroyFile(nxtHandle : FantomHandle; fileHandle : FantomHandle; var status : integer); procedure iNXT_destroyFileIterator(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); procedure iNXT_destroyModule(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); procedure iNXT_destroyModuleIterator(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); procedure iNXT_downloadFirmware(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); procedure iNXT_eraseUserFlash(nxtHandle : FantomHandle; var status : integer); procedure iNXT_findDeviceInFirmwareDownloadMode(resString : PChar; var status : integer); procedure iNXT_getDeviceInfo(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); procedure iNXT_getFirmwareVersion(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); procedure iNXT_getResourceString(nxtHandle : FantomHandle; resString : PChar; var status : integer); procedure iNXT_read(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); procedure iNXT_sendDirectCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); procedure iNXT_setName(nxtHandle : FantomHandle; newName : PChar; var status : integer); procedure iNXTIterator_advance(NXTIterHandle : FantomHandle; var status : integer); procedure iNXTIterator_getName(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); procedure pairBluetooth(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); procedure unpairBluetooth(resourceName : PChar; var status : integer); procedure FantomSDKClose; procedure FantomSDKInit; var FantomAPILoaded: Boolean = False; procedure UnloadFantomAPI; implementation uses Classes, SysUtils, Math, rcx_cmd, rcx_constants, uCommonUtils; const MAX_SERIAL_IDX = 24; const USB_ID_VENDOR_LEGO = $0694; const USB_ID_PRODUCT_NXT = $0002; const USB_ID_VENDOR_ATMEL = $03EB; const USB_ID_PRODUCT_SAMBA = $6124; const USB_INTERFACE = 0; const USB_OUT_ENDPOINT = $01; const USB_IN_ENDPOINT = $82; const USB_TIMEOUT = 1000; const DIRECT_COMMAND = 0; const NO_RESP0NSE = $80; function LSB(w : Word) : Byte; begin Result := Byte(w and $ff); end; function MSB(w : Word) : Byte; begin Result := Byte((w shr 8) and $ff); end; function GetSerialDeviceName(idx : integer) : string; begin {$IFDEF WIN32} Result := Format('COM%d', [idx]); {$ELSE} Result := Format('/dev/rfcomm%d', [idx]); {$ENDIF} end; function TimerGTEQ(a, b : PTimeval) : boolean; begin Result := False; if a^.tv_sec < b^.tv_sec then Exit else if a^.tv_sec = b^.tv_sec then begin if a^.tv_usec < b^.tv_usec then Exit; end; Result := True; end; procedure TimerSub(a, b, result : PTimeval); begin result^.tv_sec := a^.tv_sec - b^.tv_sec; result^.tv_usec := a^.tv_usec - b^.tv_usec; if result^.tv_usec < 0 then begin dec(result^.tv_sec); result^.tv_usec := result^.tv_usec + 1000000; end; end; const FIONREAD = $541B; function ReadTO(Handle: LongInt; Buffer : Pointer; Count: LongInt; ms : LongInt) : LongInt; var cur : PChar; expire, delay : TTimeval; tz : TTimezone; rfds : TFDSet; nread, total : integer; begin // time limited read cur := PChar(Buffer); if fpGetTimeOfDay(@expire, @tz) < 0 then begin Result := -1; Exit; end; expire.tv_sec := expire.tv_sec + (ms div 1000); expire.tv_usec := expire.tv_usec + ((ms mod 1000) * 1000); rfds[0] := 0; total := 0; while Count > 0 do begin fpFD_Zero(rfds); fpFD_Set(Handle, rfds); if fpGetTimeOfDay(@delay, @tz) < 0 then begin Result := -1; Exit; end; if TimerGTEQ(@delay, @expire) then break; TimerSub(@expire, @delay, @delay); if fpSelect(Handle + 1, @rfds, nil, nil, @delay) <> 0 then begin if fpIOCtl(Handle, FIONREAD, @nread) < 0 then begin Result := -1; Exit; end; if Count < nread then nread := Count; nread := fpRead(Handle, cur, nread); if nread < 0 then begin Result := -1; Exit; end; dec(Count, nread); cur := cur + nread; inc(total, nread); end else break; end; Result := total; end; function BluetoothRead(Handle: LongInt; Buffer : Pointer; Count: LongInt; ms : LongInt): LongInt; var header : array[0..1] of Byte; packetSize : integer; actual : integer; begin Result := -1; if ReadTO(Handle, @header[0], 2, ms) <> 2 then Exit; packetSize := Integer(header[0]) + Integer(header[1]*256); if packetSize > Count then Exit; actual := ReadTO(Handle, Buffer, packetSize, ms); if actual <> packetSize then Exit; Result := actual; end; procedure BluetoothFlush(Handle: LongInt); begin fpfsync(Handle); end; function BluetoothWrite(Handle: LongInt; Buffer : Pointer; Count: LongInt): LongInt; var header : array[0..1] of Byte; begin Result := 0; header[0] := Byte(Count and $FF); header[1] := Byte(Count shr 8); fpWrite(Handle, header, 2); Result := fpWrite(Handle, Buffer^, Count); end; procedure BluetoothSetParams(Handle: LongInt; BitsPerSec: LongInt; ByteSize: byte; Parity: byte; StopBits: byte); var tios: termios; begin tios.c_oflag := 0; FillChar(tios, SizeOf(tios), #0); case BitsPerSec of 50: tios.c_cflag := B50; 75: tios.c_cflag := B75; 110: tios.c_cflag := B110; 134: tios.c_cflag := B134; 150: tios.c_cflag := B150; 200: tios.c_cflag := B200; 300: tios.c_cflag := B300; 600: tios.c_cflag := B600; 1200: tios.c_cflag := B1200; 1800: tios.c_cflag := B1800; 2400: tios.c_cflag := B2400; 4800: tios.c_cflag := B4800; 19200: tios.c_cflag := B19200; 38400: tios.c_cflag := B38400; 57600: tios.c_cflag := B57600; 115200: tios.c_cflag := B115200; 230400: tios.c_cflag := B230400; {$ifndef BSD} 460800: tios.c_cflag := B460800; {$endif} else tios.c_cflag := B9600; end; tios.c_ispeed := tios.c_cflag; tios.c_ospeed := tios.c_ispeed; tios.c_cflag := tios.c_cflag or CREAD or CLOCAL; case ByteSize of 5: tios.c_cflag := tios.c_cflag or CS5; 6: tios.c_cflag := tios.c_cflag or CS6; 7: tios.c_cflag := tios.c_cflag or CS7; else tios.c_cflag := tios.c_cflag or CS8; end; case Parity of 1: tios.c_cflag := tios.c_cflag or PARENB or PARODD; 2: tios.c_cflag := tios.c_cflag or PARENB; end; if StopBits = 2 then tios.c_cflag := tios.c_cflag or CSTOPB; tios.c_cc[VMIN] := 1; tios.c_cc[VTIME] := 0; tcsetattr(Handle, TCSAFLUSH, tios) end; function BluetoothOpen(const DeviceName: String): LongInt; begin Result := fpopen(DeviceName, O_RDWR); if Result > 0 then BluetoothSetParams(Result, 460800, 8, 0, 1); end; procedure BluetoothClose(Handle: LongInt); begin fpClose(Handle); end; function is_nxt_fw_device(dev : PUSBDevice) : boolean; begin Result := (dev^.descriptor.idVendor = USB_ID_VENDOR_ATMEL) and (dev^.descriptor.idProduct = USB_ID_PRODUCT_SAMBA); end; function is_nxt_device(dev : PUSBDevice) : boolean; begin Result := (dev^.descriptor.idVendor = USB_ID_VENDOR_LEGO) and (dev^.descriptor.idProduct = USB_ID_PRODUCT_NXT); end; function is_nxt_serial_device(tmpHandle : LongInt; ms : integer) : boolean; var cmd : TBaseCmd; len : integer; b : array[0..5] of Byte; begin Result := False; // device is an NXT if it responds to a simple system or direct command if tmpHandle <> 0 then begin cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_DirectCmd, kNXT_DCGetBatteryLevel); len := cmd.GetLength; if BluetoothWrite(tmpHandle, cmd.GetBody, len) = len then begin if BluetoothRead(tmpHandle, @b[0], 5, ms) = 5 then Result := True; end; finally cmd.Free; end; end; end; function FindNXTFirmwareDevice() : PUSBDevice; var busses : PUSBBus; bus : PUSBBus; dev : PUSBDevice; begin usb_find_busses(); usb_find_devices(); busses := usb_get_busses(); bus := busses; while bus <> nil do begin dev := bus^.devices; while dev <> nil do begin if is_nxt_fw_device(dev) then begin Result := dev; Exit; end; dev := dev^.next; end; bus := bus^.next; end; Result := nil; end; function UseUSB(const resStr : string) : boolean; begin // resource string for USB has certain format // bluetooth version must always start with BTH:: // USB version must always start with USB Result := Pos('USB', resStr) = 1; { BTH::NXT=BTH::NXT::00:16:53:01:E2:CB::5 NI-VISA-0::1=USB0::0X03EB::0X6124::NI-VISA-0::1::RAW NXT=USB0::0X0694::0X0002::00165301E2CB::RAW } end; type TNxt = class; TNxtFile = class protected fNXT : TNxt; fFilename : string; fSize : integer; fAvailableSize : integer; fHandle : byte; fOpen : boolean; public constructor Create(aNXT : TNxt; const aFilename : string); virtual; destructor Destroy; override; procedure getName(var fileName : string); function getSize(var status : integer) : Cardinal; function getAvailableSize(var status : integer) : Cardinal; procedure openForRead(var status : integer); procedure openForWrite(sizeInBytes : Cardinal; var status : integer); procedure openForLinearWrite(sizeInBytes : Cardinal; var status : integer); procedure openForDataWrite(sizeInBytes : Cardinal; var status : integer); procedure openForDataAppend(var status : integer); procedure close(var status : integer); function read(bufferPtr : PByte; numberOfBytes : Cardinal; var status : integer) : Cardinal; function write(bufferPtr : PByte; numberOfBytes : Cardinal; var status : integer) : Cardinal; procedure remove(var status : integer); end; TNxtFileIterator = class protected fNXT : TNxt; fPattern : string; fFileName : string; fSize : Cardinal; fValid : boolean; fFirstTime : boolean; fHandle : byte; procedure CloseFileHandle(var status : integer); public constructor Create(aNXT : TNxt; const aPattern : string); virtual; destructor Destroy; override; function getFile(var status : integer) : TNxtFile; procedure advance(var status : integer); procedure getName(var filename : string; var status : integer); function getSize(var status : integer) : Cardinal; end; TNxtIModule = class protected fNXT : TNxt; fModuleName : string; fModuleID : Cardinal; fSize : Cardinal; fIOMapSize : Cardinal; public constructor Create(aNXT : TNxt); virtual; destructor Destroy; override; procedure getName(var moduleName : string); function getModuleID : Cardinal; function getModuleSize : Cardinal; function getModuleIOMapSize : Cardinal; function readIOMap(offsetInBytes, numberOfBytes : Cardinal; dataBufferPtr : PByte; var status : integer) : Cardinal; function writeIOMap(offsetInBytes, numberOfBytes : Cardinal; dataBufferPtr : PByte; var status : integer) : Cardinal; end; TNxtIModuleIterator = class protected fNXT : TNxt; fPattern : string; fModuleName : string; fModuleID : Cardinal; fSize : Cardinal; fIOMapSize : Cardinal; fValid : boolean; fFirstTime : boolean; fHandle : byte; procedure CloseModuleHandle(var status : integer); public constructor Create(aNXT : TNxt; const aPattern : string); virtual; destructor Destroy; override; function getModule(var status : integer) : TNxtIModule; procedure advance(var status : integer); procedure getName(var moduleName : string; var status : integer); end; TNxtIterator = class protected fBusses : PUSBBus; fBus : PUSBBus; fDev : PUSBDevice; fDevHandle : PUSBDevHandle; fSerialHandle : LongInt; fNXTViaUSB : boolean; fCurSerialIdx : integer; fSearchBT : boolean; fBTTimeout : Cardinal; fBTSeconds : Cardinal; public constructor Create; virtual; destructor Destroy; override; function getNXT(var status : integer) : TNxt; procedure advance(var status : integer); procedure getName(var resourceName : string; var status : integer); end; TNxt = class protected fDev : PUSBDevice; fDevHandle : PUSBDevHandle; fSerialHandle : LongInt; fNXTViaUSB : boolean; fPort : string; fCheckver : boolean; fTimeout : integer; function SetResourceString(resStr : string) : integer; function CorrectDeviceFound : boolean; procedure IgnoreResponse(n : integer; var status : integer); public constructor Create; virtual; destructor Destroy; override; function createFile(const fileName : string; var status : integer) : TNxtFile; procedure destroyFile(var filePtr : TNxtFile); function createFileIterator(const fileNamePattern : string; var status : integer) : TNxtFileIterator; procedure destroyFileIterator(var fileIteratorPtr : TNxtFileIterator); function createModule(const moduleName : string; moduleID, moduleSizeInBytes, ioMapSizeInBytes : Cardinal; var status : integer) : TNxtIModule; procedure destroyModule(var modulePtr : TNxtIModule); function createModuleIterator(const moduleNamePattern : string; var status : integer) : TNxtIModuleIterator; procedure destroyModuleIterator(var moduleIteratorPtr : TNxtIModuleIterator); // API procedure getFirmwareVersion(var protocolVersionMajorRef : Byte; var protocolVersionMinorRef : Byte; var firmwareVersionMajorRef : Byte; var firmwareVersionMinorRef : Byte; var status : integer); function sendDirectCommand(requireResponse : boolean; const commandBufferPtr : PByte; commandBufferSizeInBytes : Cardinal; responseBufferPtr : PByte; responseBufferSizeInBytes : Cardinal; var status : integer) : Cardinal; procedure downloadFirmware(const firmwareBufferPtr : PByte; firmwareBufferSizeInBytes : Cardinal; var status : integer); function write(const bufferPtr : PByte; numberOfBytes : Cardinal; var status : integer) : Cardinal; function read(bufferPtr : PByte; numberOfBytes : Cardinal; var status : integer) : Cardinal; procedure bootIntoFirmwareDownloadMode(var status : integer); procedure setName(const newName : string; var status : integer); procedure getDeviceInfo(var name : string; bluetoothAddress : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); procedure eraseUserFlash(var status : integer); function pollAvailableLength(bufferSelector : byte; var status : integer) : Cardinal; function readBufferData(dataBuffer : PByte; bufferSelector : byte; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; procedure getResourceString(var resString : string; var status : integer); procedure bluetoothFactoryReset(var status : integer); class function createNXT(const resString : string; var status : integer; checkFirmwareVersion : boolean = true) : TNxt; class procedure destroyNXT(var nxtPtr : TNxt); class function createNXTIterator(searchBluetooth : boolean; bluetoothSearchTimeoutInSeconds : cardinal; var status : integer) : TNxtIterator; class procedure destroyNXTIterator(iterPtr : TNxtIterator); class procedure pairBluetooth(const resourceName : string; const passkey : string; var pairedResourceName : string; var status : integer); class procedure unpairBluetooth(const resourceName : string; var status : integer); class function isPaired(const resourceName : string; var status : integer) : boolean; class procedure findDeviceInFirmwareDownloadMode(var resourceName : string; var status : integer); end; function ConvertStatus(const fwStatus : byte) : integer; begin case fwStatus of // each of these cases corresponds to a unique status code returned by the firmware $00 : Result := kStatusNoError; $81 : Result := kStatusFWNoMoreHandles; // No more available handles $82 : Result := kStatusFWNoSpace; // No space $83 : Result := kStatusFWNoMoreFiles; // No more files $84 : Result := kStatusFWEndOfFileExpected; // End of file expected $85 : Result := kStatusFWEndOfFile; // End of file reached $86 : Result := kStatusFWNotLinearFile; // Not a linear file $87 : Result := kStatusFWFileNotFound; // File not found $88 : Result := kStatusFWHandleAlreadyClosed; // Handle is already closed $89 : Result := kStatusFWNoLinearSpace; // No linear space available $8A : Result := kStatusFWUndefinedError; // Undefined error $8B : Result := kStatusFWFileIsBusy; // File is busy $8C : Result := kStatusFWNoWriteBuffers; // No write buffers available $8D : Result := kStatusFWAppendNotPossible; // Append not possible $8E : Result := kStatusFWFileIsFull; // File is full $8F : Result := kStatusFWFileExists; // File already exists $90 : Result := kStatusFWModuleNotFound; // Module not found $91 : Result := kStatusFWOutOfBounds; // Out of module I/O map boundary $92 : Result := kStatusFWIllegalFileName; // Illegal file name $93 : Result := kStatusFWIllegalHandle; // Illegal handle else Result := kStatusFWUnknownErrorCode; end; end; function GetUSBResString(dev : PUSBDevice; handle : PUSBDevHandle) : string; var buf : PChar; begin buf := nil; GetMem(buf, 256); try with dev^.descriptor, dev^.config^ do begin if handle <> nil then usb_get_string_simple(handle, iSerialNumber, buf, 255) else StrPCopy(buf, 'NI-VISA-1::1'); // firmware mode Result := Format('USB%d::0X%4.4X::0X%4.4X::%s::RAW', [iConfiguration, idVendor, idProduct, buf]); end; finally FreeMem(buf); end; // USB0::0X03EB::0X6124::NI-VISA-1::1::RAW // USB0::0X0694::0X0002::001653FF0156::RAW end; function GetSerialResString(handle : LongInt; ms : integer) : string; var name : string; b : array[0..5] of byte; cmd : TBaseCmd; buf : array[0..32] of Byte; p : PByte; len, size, i : integer; begin result := ''; b[0] := 0; // send a GetDeviceInfo system command to the device on this port // and see if you get back a valid response. // if so, then build a resource string using the values in the response. cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCGetDeviceInfo); len := cmd.GetLength; if BluetoothWrite(handle, cmd.GetBody, len) = len then begin size := 33; len := BluetoothRead(handle, @buf[0], size, ms); if (len = size) and (buf[2] = 0) then begin name := ''; for i := 3 to 17 do if buf[i] <> 0 then name := name + Char(buf[i]); p := @buf[18]; Move(p^, b, 6); end else Exit; end; finally cmd.Free; end; Result := Format('BTH::%s::%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x::%d', [name, b[0], b[1], b[2], b[3], b[4], b[5], 5]); //BTH::NXT::00:16:53:01:E2:CB::5 end; procedure UnloadFantomAPI; begin if FantomAPILoaded then begin // unload something ? FantomAPILoaded := False; end; end; function createNXT(resString : PChar; var status : integer; checkFWversion : byte) : FantomHandle; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; tmp := TNxt.createNXT(resString, status, Boolean(checkFWversion)); Result := FantomHandle(tmp); end; function createNXTIterator(searchBluetooth : byte; bluetoothSearchTimeout : Cardinal; var status : integer) : FantomHandle; var tmp : TNxtIterator; begin Result := 0; if status < kStatusNoError then Exit; tmp := TNxt.createNXTIterator(Boolean(searchBluetooth), bluetoothSearchtimeout, status); Result := FantomHandle(tmp); end; function iFile_getAvailableSize(fileHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtFile; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); Result := tmp.getAvailableSize(status); except status := kStatusFWIllegalHandle; end; end; function iFile_getSize(fileHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtFile; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); Result := tmp.getSize(status); except status := kStatusFWIllegalHandle; end; end; function iFileIterator_getFile(iterHandle : FantomHandle; var status : integer) : FantomHandle; var tmp : TNxtFileIterator; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtFileIterator(iterHandle); Result := FantomHandle(tmp.getFile(status)); except status := kStatusFWIllegalHandle; end; end; function iFileIterator_getSize(fileIterHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtFileIterator; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtFileIterator(fileIterHandle); Result := tmp.getSize(status); except status := kStatusFWIllegalHandle; end; end; function iModule_getIOMapSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtIModule; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); Result := tmp.getModuleIOMapSize(); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; function iModule_getModuleID(moduleHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtIModule; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); Result := tmp.getModuleID(); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; function iModule_getModuleSize(moduleHandle : FantomHandle; var status : integer) : Cardinal; var tmp : TNxtIModule; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); Result := tmp.getModuleSize(); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; function iModule_readIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToRead : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; var tmp : TNxtIModule; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); Result := tmp.readIOMap(offset, numberBytesToRead, dataBuffer, status); except status := kStatusFWIllegalHandle; end; end; function iModule_writeIOMap(moduleHandle : FantomHandle; offset : Cardinal; numberBytesToWrite : Cardinal; dataBuffer : PByte; var status : integer) : Cardinal; var tmp : TNxtIModule; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); Result := tmp.writeIOMap(offset, numberBytesToWrite, dataBuffer, status); except status := kStatusFWIllegalHandle; end; end; function iModuleIterator_getModule(modIterHandle : FantomHandle; var status : integer) : FantomHandle; var tmp : TNxtIModuleIterator; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIModuleIterator(modIterHandle); Result := FantomHandle(tmp.getModule(status)); except status := kStatusFWIllegalHandle; end; end; function iNXT_createFile(nxtHandle : FantomHandle; const filename : PChar; var status : integer) : FantomHandle; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := FantomHandle(tmp.createFile(filename, status)); except status := kStatusFWIllegalHandle; end; end; function iNXT_createFileIterator(nxtHandle : FantomHandle; filePattern : PChar; var status : integer) : FantomHandle; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := FantomHandle(tmp.createFileIterator(filePattern, status)); except status := kStatusFWIllegalHandle; end; end; function iNXT_createModule(nxtHandle : FantomHandle; moduleName : PChar; moduleID : Cardinal; moduleSize : Cardinal; IOMapSize : Cardinal; var status : integer) : FantomHandle; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := FantomHandle(tmp.createModule(moduleName, moduleID, moduleSize, IOMapSize, status)); except status := kStatusFWIllegalHandle; end; end; function iNXT_createModuleIterator(nxtHandle : FantomHandle; moduleNamePattern : PChar; var status : integer) : FantomHandle; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := FantomHandle(tmp.createModuleIterator(moduleNamePattern, status)); except status := kStatusFWIllegalHandle; end; end; function iNXT_pollAvailableLength(nxtHandle : FantomHandle; bufferSelector : Cardinal; var status : integer) : Cardinal; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := tmp.pollAvailableLength(Byte(bufferSelector), status); except status := kStatusFWIllegalHandle; end; end; function iNXT_readBufferData(nxtHandle : FantomHandle; dataBuffer : PByte; bufferSelector : Cardinal; numberOfBytesToRead : Cardinal; var status : integer) : Cardinal; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := tmp.readBufferData(dataBuffer, Byte(bufferSelector), numberOfBytesToRead, status); except status := kStatusFWIllegalHandle; end; end; function iNXT_write(nxtHandle : FantomHandle; writeBuffer : PByte; writeBufferSize : Cardinal; var status : integer) : Cardinal; var tmp : TNxt; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); Result := tmp.write(writeBuffer, writeBufferSize, status); except status := kStatusFWIllegalHandle; end; end; function iNXTIterator_getNXT(nxtIterHandle : FantomHandle; var status : integer) : FantomHandle; var tmp : TNxtIterator; begin Result := 0; if status < kStatusNoError then Exit; try tmp := TNxtIterator(nxtIterHandle); Result := FantomHandle(tmp.getNXT(status)); except status := kStatusFWIllegalHandle; end; end; procedure destroyNXT(nxtHandle : FantomHandle; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); FreeAndNil(tmp); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure destroyNXTIterator(nxtIteratorHandle : FantomHandle; var status : integer); var tmp : TNxtIterator; begin if status < kStatusNoError then Exit; try tmp := TNxtIterator(nxtIteratorHandle); FreeAndNil(tmp); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure iFile_close(fileHandle : FantomHandle; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.close(status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_getName(fileHandle : FantomHandle; filename : PChar; var status : integer); var tmp : TNxtFile; tmpName : string; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmpName := ''; tmp.getName(tmpName); StrPCopy(filename, tmpName); except status := kStatusFWIllegalHandle; end; end; procedure iFile_openForDataAppend(fileHandle : FantomHandle; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.openForDataAppend(status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_openForDataWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.openForDataWrite(sizeInBytes, status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_openForLinearWrite(fileHandle : FantomHandle; sizeInBytes : Cardinal; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.openForLinearWrite(sizeInBytes, status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_openForRead(fileHandle : FantomHandle; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.openForRead(status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_openForWrite(fileHandle : FantomHandle; fileSize : Cardinal; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.openForWrite(fileSize, status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_read(fileHandle : FantomHandle; fileDataBuffer : PByte; bufferSize : Cardinal; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.read(fileDataBuffer, bufferSize, status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_remove(fileHandle : FantomHandle; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.remove(status); except status := kStatusFWIllegalHandle; end; end; procedure iFile_write(fileHandle : FantomHandle; writeBuffer : PByte; writeBufferLength : Cardinal; var status : integer); var tmp : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxtFile(fileHandle); tmp.write(writeBuffer, writeBufferLength, status); except status := kStatusFWIllegalHandle; end; end; procedure iFileIterator_advance(iterHandle : FantomHandle; var status : integer); var tmp : TNxtFileIterator; begin if status < kStatusNoError then Exit; try tmp := TNxtFileIterator(iterHandle); tmp.advance(status); except status := kStatusFWIllegalHandle; end; end; procedure iFileIterator_getName(iterHandle : FantomHandle; filename : PChar; var status : integer); var tmp : TNxtFileIterator; tmpName : string; begin if status < kStatusNoError then Exit; try tmp := TNxtFileIterator(iterHandle); tmpName := ''; tmp.getName(tmpName, status); StrPCopy(filename, tmpName); except status := kStatusFWIllegalHandle; end; end; procedure iModule_getName(moduleHandle : FantomHandle; moduleName : PChar; var status : integer); var tmp : TNxtIModule; tmpName : string; begin if status < kStatusNoError then Exit; try tmp := TNxtIModule(moduleHandle); tmpName := ''; tmp.getName(tmpName); StrPCopy(moduleName, tmpName); except status := kStatusFWIllegalHandle; end; end; procedure iModuleIterator_advance(modIterHandle : FantomHandle; var status : integer); var tmp : TNxtIModuleIterator; begin if status < kStatusNoError then Exit; try tmp := TNxtIModuleIterator(modIterHandle); tmp.advance(status); except status := kStatusFWIllegalHandle; end; end; procedure iModuleIterator_getName(modIterHandle : FantomHandle; moduleName : PChar; var status : integer); var tmp : TNxtIModuleIterator; tmpName : string; begin if status < kStatusNoError then Exit; try tmp := TNxtIModuleIterator(modIterHandle); tmpName := ''; tmp.getName(tmpName, status); StrPCopy(moduleName, tmpName); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_bluetoothFactoryReset(nxtHandle : FantomHandle; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.bluetoothFactoryReset(status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_bootIntoFirmwareDownloadMode(resourceName : PChar; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt.createNXT(resourceName, status, False); tmp.bootIntoFirmwareDownloadMode(status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_destroyFile(nxtHandle : FantomHandle; fileHandle : FantomHandle; var status : integer); var tmp : TNxt; tmpFile : TNxtFile; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpFile := TNxtFile(fileHandle); tmp.destroyFile(tmpFile); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure iNXT_destroyFileIterator(nxtHandle : FantomHandle; iterHandle : FantomHandle; var status : integer); var tmp : TNxt; tmpFileIter : TNxtFileIterator; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpFileIter := TNxtFileIterator(iterHandle); tmp.destroyFileIterator(tmpFileIter); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure iNXT_destroyModule(nxtHandle : FantomHandle; moduleHandle : FantomHandle; var status : integer); var tmp : TNxt; tmpMod : TNxtIModule; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpMod := TNxtIModule(moduleHandle); tmp.destroyModule(tmpMod); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure iNXT_destroyModuleIterator(nxtHandle : FantomHandle; modIterHandle : FantomHandle; var status : integer); var tmp : TNxt; tmpModIter : TNxtIModuleIterator; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpModIter := TNxtIModuleIterator(modIterHandle); tmp.destroyModuleIterator(tmpModIter); status := kStatusNoError; except status := kStatusFWIllegalHandle; end; end; procedure iNXT_downloadFirmware(nxtHandle : FantomHandle; firmwareBuffer : PByte; firmwareBufferSize : Cardinal; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.downloadFirmware(firmwareBuffer, firmwareBufferSize, status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_eraseUserFlash(nxtHandle : FantomHandle; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.eraseUserFlash(status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_findDeviceInFirmwareDownloadMode(resString : PChar; var status : integer); var tmpStr : string; begin if status < kStatusNoError then Exit; try tmpStr := ''; TNxt.findDeviceInFirmwareDownloadMode(tmpStr, status); StrPCopy(resString, tmpStr); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_getDeviceInfo(nxtHandle : FantomHandle; name : PChar; address : PByte; signalStrength : PByte; var availableFlash : Cardinal; var status : integer); var tmp : TNxt; tmpName : string; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpName := ''; tmp.getDeviceInfo(tmpName, address, signalStrength, availableFlash, status); StrPCopy(name, tmpName); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_getFirmwareVersion(nxtHandle : FantomHandle; var protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor : byte; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.getFirmwareVersion(protocolVersionMajor, protocolVersionMinor, firmwareVersionMajor, firmwareVersionMinor, status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_getResourceString(nxtHandle : FantomHandle; resString : PChar; var status : integer); var tmp : TNxt; tmpResString : string; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmpResString := ''; tmp.getResourceString(tmpResString, status); StrPCopy(resString, tmpResString); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_read(nxtHandle : FantomHandle; readBuffer : PByte; readBufferSize : Cardinal; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.read(readBuffer, readBufferSize, status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_sendDirectCommand(nxtHandle : FantomHandle; requireResponse : byte; inputBufferPtr : Pbyte; inputBufferSize : Cardinal; outputBufferPtr : PByte; outputBufferSize : Cardinal; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.sendDirectCommand(Boolean(requireResponse), inputBufferPtr, inputBufferSize, outputBufferPtr, outputBufferSize, status); except status := kStatusFWIllegalHandle; end; end; procedure iNXT_setName(nxtHandle : FantomHandle; newName : PChar; var status : integer); var tmp : TNxt; begin if status < kStatusNoError then Exit; try tmp := TNxt(nxtHandle); tmp.setName(newName, status); except status := kStatusFWIllegalHandle; end; end; procedure iNXTIterator_advance(NXTIterHandle : FantomHandle; var status : integer); var tmp : TNxtIterator; begin if status < kStatusNoError then Exit; try tmp := TNxtIterator(NXTIterHandle); tmp.advance(status); except status := kStatusFWIllegalHandle; end; end; procedure iNXTIterator_getName(NXTIterHandle : FantomHandle; resString : PChar; var status : integer); var tmp : TNxtIterator; tmpResName : string; begin if status < kStatusNoError then Exit; try tmp := TNxtIterator(NXTIterHandle); tmpResName := ''; tmp.getName(tmpResName, status); StrPCopy(resString, tmpResName); except status := kStatusFWIllegalHandle; end; end; procedure pairBluetooth(resourceName : PChar; passkey : PChar; pairedResourceName : PChar; var status : integer); var tmpPRN : string; begin if status < kStatusNoError then Exit; try tmpPRN := ''; TNxt.pairBluetooth(resourceName, passkey, tmpPRN, status); StrPCopy(pairedResourceName, tmpPRN); except status := kStatusFWIllegalHandle; end; end; procedure unpairBluetooth(resourceName : PChar; var status : integer); begin if status < kStatusNoError then Exit; try TNxt.unpairBluetooth(resourceName, status); except status := kStatusFWIllegalHandle; end; end; procedure FantomSDKClose; begin // uninitialize usb stuff end; procedure FantomSDKInit; begin // initialize USB stuff usb_init(); // usb_set_debug(5); FantomAPILoaded := True; end; { TNxt } procedure TNxt.bluetoothFactoryReset(var status: integer); var cmd : TBaseCmd; begin if status < kStatusNoError then Exit; // TODO: do I need to check the response or not? cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmdNoReply, kNXT_SCBTFactoryReset); write(cmd.GetBody, cmd.GetLength, status); finally cmd.Free; end; end; procedure TNxt.bootIntoFirmwareDownloadMode(var status: integer); var cmd : TNxtCmd; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeBoot(True); write(cmd.GetBody, cmd.GetLength, status); IgnoreResponse(7, status); finally cmd.Free; end; end; function TNxt.CorrectDeviceFound: boolean; var tmpStr : string; begin if fNXTViaUSB then tmpStr := GetUSBResString(fDev, fDevHandle) else tmpStr := GetSerialResString(fSerialHandle, fTimeout); Result := AnsiCompareText(fPort, tmpStr) = 0; end; constructor TNxt.Create; begin inherited Create; fDev := nil; fDevHandle := nil; fSerialHandle := 0; fNXTViaUSB := True; fPort := ''; fCheckver := False; fTimeout := USB_TIMEOUT; end; function TNxt.createFile(const fileName: string; var status: integer): TNxtFile; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxtFile.Create(self, fileName); status := kStatusNoError; end; function TNxt.createFileIterator(const fileNamePattern: string; var status: integer): TNxtFileIterator; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxtFileIterator.Create(self, fileNamePattern); Result.advance(status); end; function TNxt.createModule(const moduleName: string; moduleID, moduleSizeInBytes, ioMapSizeInBytes: Cardinal; var status: integer): TNxtIModule; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxtIModule.Create(self); Result.fModuleName := moduleName; Result.fModuleID := moduleID; Result.fSize := moduleSizeInBytes; Result.fIOMapSize := ioMapSizeInBytes; status := kStatusNoError; end; function TNxt.createModuleIterator(const moduleNamePattern: string; var status: integer): TNxtIModuleIterator; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxtIModuleIterator.Create(self, moduleNamePattern); Result.advance(status); end; class function TNxt.createNXT(const resString: string; var status: integer; checkFirmwareVersion: boolean): TNxt; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxt.Create; Result.fCheckver := checkFirmwareVersion; status := Result.SetResourceString(resString); end; class function TNxt.createNXTIterator(searchBluetooth: boolean; bluetoothSearchTimeoutInSeconds: cardinal; var status: integer): TNxtIterator; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxtIterator.Create; Result.fSearchBT := searchBluetooth; Result.fBTSeconds := bluetoothSearchTimeoutInSeconds; usb_find_busses(); usb_find_devices(); Result.fBusses := usb_get_busses(); Result.fDev := nil; Result.fBus := nil; Result.advance(status); end; destructor TNxt.Destroy; begin if fDevHandle <> nil then begin usb_release_interface(fDevHandle, USB_INTERFACE); usb_close(fDevHandle); fDevHandle := nil; end; if fSerialHandle <> 0 then begin BluetoothClose(fSerialHandle); fSerialHandle := 0; end; inherited; end; procedure TNxt.destroyFile(var filePtr: TNxtFile); begin FreeAndNil(filePtr); end; procedure TNxt.destroyFileIterator(var fileIteratorPtr: TNxtFileIterator); begin FreeAndNil(fileIteratorPtr); end; procedure TNxt.destroyModule(var modulePtr: TNxtIModule); begin FreeAndNil(modulePtr); end; procedure TNxt.destroyModuleIterator(var moduleIteratorPtr: TNxtIModuleIterator); begin FreeAndNil(moduleIteratorPtr); end; class procedure TNxt.destroyNXT(var nxtPtr: TNxt); begin FreeAndNil(nxtPtr); end; class procedure TNxt.destroyNXTIterator(iterPtr: TNxtIterator); begin FreeAndNil(iterPtr); end; procedure TNxt.downloadFirmware(const firmwareBufferPtr: PByte; firmwareBufferSizeInBytes: Cardinal; var status: integer); begin // TODO: Firmware download is not currently supported. if not Assigned(firmwareBufferPtr) then Exit; if firmwareBufferSizeInBytes = 0 then Exit; if status < kStatusNoError then Exit; status := kStatusFirmwareDownloadFailed; end; procedure TNxt.eraseUserFlash(var status: integer); var cmd : TBaseCmd; buf : array[0..2] of Byte; len, size, oldTimeout : integer; begin if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCDeleteUserFlash); write(cmd.GetBody, cmd.GetLength, status); size := 3; oldTimeout := fTimeout; try fTimeout := 3000; len := read(@buf[0], size, status); finally fTimeout := oldTimeout; end; if (len = size) and (buf[2] = 0) then begin status := kStatusNoError; end else status := ConvertStatus(buf[2]); finally cmd.Free; end; end; class procedure TNxt.findDeviceInFirmwareDownloadMode( var resourceName: string; var status: integer); var dev : PUSBDevice; begin // this always uses USB mode if status < kStatusNoError then Exit; resourceName := ''; status := kStatusNoMoreItemsFound; dev := FindNXTFirmwareDevice; if dev <> nil then begin resourceName := GetUSBResString(dev, nil); // nil means Firmware Mode status := kStatusNoError; end; end; procedure TNxt.getDeviceInfo(var name: string; bluetoothAddress, signalStrength: PByte; var availableFlash: Cardinal; var status: integer); var cmd : TBaseCmd; buf : array[0..32] of Byte; p : PByte; len, size, i : integer; begin if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCGetDeviceInfo); write(cmd.GetBody, cmd.GetLength, status); size := 33; len := read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin name := ''; for i := 3 to 17 do name := name + Char(buf[i]); p := @buf[18]; Move(p^, bluetoothAddress^, 6); inc(p, 7); Move(p^, signalStrength^, 4); availableFlash := BytesToCardinal(buf[29], buf[30], buf[31], buf[32]); status := kStatusNoError; end else status := ConvertStatus(buf[2]); finally cmd.Free; end; end; procedure TNxt.getFirmwareVersion(var protocolVersionMajorRef, protocolVersionMinorRef, firmwareVersionMajorRef, firmwareVersionMinorRef: Byte; var status: integer); var cmd : TBaseCmd; buf : array[0..6] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCGetVersions); write(cmd.GetBody, cmd.GetLength, status); size := 7; len := read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin protocolVersionMajorRef := buf[4]; protocolVersionMinorRef := buf[3]; firmwareVersionMajorRef := buf[6]; firmwareVersionMinorRef := buf[5]; status := kStatusNoError; end else status := ConvertStatus(buf[2]); finally cmd.Free; end; end; procedure TNxt.getResourceString(var resString: string; var status: integer); begin if status < kStatusNoError then Exit; resString := fPort; status := kStatusNoError; end; procedure TNxt.IgnoreResponse(n: integer; var status : integer); var buf : PByte; begin buf := nil; GetMem(buf, n); try read(buf, n, status); finally FreeMem(buf); end; end; class function TNxt.isPaired(const resourceName: string; var status: integer): boolean; begin Result := False; if resourceName = '' then Exit; if status < kStatusNoError then Exit; status := kStatusNoError; end; class procedure TNxt.pairBluetooth(const resourceName, passkey: string; var pairedResourceName: string; var status: integer); begin if resourceName = '' then Exit; if passKey = '' then Exit; if status < kStatusNoError then Exit; pairedResourceName := resourceName; // status := kStatusPairingFailed; status := kStatusNoError; end; function TNxt.pollAvailableLength(bufferSelector: byte; var status: integer): Cardinal; var cmd : TBaseCmd; buf : array[0..4] of Byte; len, size : integer; begin Result := 0; if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCPollCommandLen, bufferSelector); write(cmd.GetBody, cmd.GetLength, status); size := 5; len := read(@buf[0], size, status); if len = size then begin Result := buf[4]; status := kStatusNoError; end; finally cmd.Free; end; end; function TNxt.read(bufferPtr: PByte; numberOfBytes: Cardinal; var status: integer): Cardinal; var ret : integer; begin Result := 0; if status < kStatusNoError then Exit; if fNXTViaUSB then begin ret := usb_bulk_read(fDevHandle, USB_IN_ENDPOINT, PChar(bufferPtr), numberOfBytes, fTimeout); end else begin ret := BluetoothRead(fSerialHandle, bufferPtr, numberOfBytes, fTimeout); end; if ret < 0 then status := ret else begin status := kStatusNoError; Result := ret; end; end; function TNxt.readBufferData(dataBuffer: PByte; bufferSelector: byte; numberOfBytesToRead: Cardinal; var status: integer): Cardinal; var cmd : TBaseCmd; buf : array[0..63] of Byte; p : PByte; len, size : integer; begin Result := 0; if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmd, kNXT_SCPollCommand, bufferSelector, Byte(numberOfBytesToRead)); write(cmd.GetBody, cmd.GetLength, status); size := 64; len := read(@buf[0], size, status); if len = size then begin Result := buf[4]; p := @buf[5]; Move(p^, dataBuffer^, 59); status := kStatusNoError; end; finally cmd.Free; end; end; function TNxt.sendDirectCommand(requireResponse: boolean; const commandBufferPtr: PByte; commandBufferSizeInBytes: Cardinal; responseBufferPtr: PByte; responseBufferSizeInBytes: Cardinal; var status: integer): Cardinal; var ret : integer; BufOut, BufIn : PByte; begin Result := 0; if status < kStatusNoError then Exit; BufOut := nil; GetMem(BufOut, commandBufferSizeInBytes+1); try BufOut^ := DIRECT_COMMAND; if not requireResponse then BufOut^ := BufOut^ or NO_RESP0NSE; inc(BufOut); Move(commandBufferPtr^, BufOut^, commandBufferSizeInBytes); dec(BufOut); ret := write(BufOut, commandBufferSizeInBytes+1, status); if requireResponse and (ret >= 0) then begin BufIn := nil; GetMem(BufIn, responseBufferSizeInBytes+1); try Result := read(BufIn, responseBufferSizeInBytes+1, status); inc(BufIn); Move(BufIn^, responseBufferPtr^, responseBufferSizeInBytes); dec(BufIn); finally FreeMem(BufIn); end; end; finally FreeMem(BufOut); end; end; procedure TNxt.setName(const newName: string; var status: integer); var cmd : TNxtCmd; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeSetName(newName, False); write(cmd.GetBody, cmd.GetLength, status); // IgnoreResponse(3, status); finally cmd.Free; end; end; function TNxt.SetResourceString(resStr: string): integer; var bDone : boolean; Busses : PUSBBus; Bus : PUSBBus; i : integer; begin Result := kStatusNoError; if AnsiCompareText(resStr, fPort) <> 0 then begin fPort := resStr; // find the device and open it bDone := False; // the resource string tells us whether to // use USB or Serial to find the NXT fNXTViaUSB := UseUSB(resStr); if fNXTViaUSB then begin if fDevHandle <> nil then begin usb_close(fDevHandle); fDevHandle := nil; end; usb_find_busses(); usb_find_devices(); Busses := usb_get_busses(); Bus := Busses; while (Bus <> nil) and not bDone do begin fDev := Bus^.devices; while (fDev <> nil) and not bDone do begin if is_nxt_device(fDev) then begin // open if it is an NXT fDevHandle := usb_open(fDev); usb_reset(fDevHandle); bDone := CorrectDeviceFound; if not bDone then begin usb_close(fDevHandle); fDevHandle := nil; end; end; if bDone then Break; fDev := fDev^.next; end; if bDone then Break; Bus := Bus^.next; end; if bDone then begin Result := kStatusNoError; // usb_set_configuration(fDevHandle, 1); usb_claim_interface(fDevHandle, USB_INTERFACE); end else Result := kStatusNoMoreItemsFound; end else begin Result := kStatusNoError; // start with current serial port index // close any open port if fSerialHandle <> 0 then begin BluetoothClose(fSerialHandle); fDevHandle := nil; end; i := 0; while (i < MAX_SERIAL_IDX) and not bDone do begin fSerialHandle := BluetoothOpen(GetSerialDeviceName(i)); BluetoothFlush(fSerialHandle); if is_nxt_serial_device(fSerialHandle, fTimeout) then begin bDone := CorrectDeviceFound; if not bDone then begin BluetoothClose(fSerialHandle); fSerialHandle := 0; end; end else begin BluetoothClose(fSerialHandle); fSerialHandle := 0; end; if bDone then Break; inc(i); Sleep(100); end; if bDone then begin Result := kStatusNoError; end else begin Result := kStatusNoMoreItemsFound; end; end; end; end; class procedure TNxt.unpairBluetooth(const resourceName: string; var status: integer); begin if resourceName = '' then Exit; if status < kStatusNoError then Exit; status := kStatusNoError; end; function TNxt.write(const bufferPtr: PByte; numberOfBytes: Cardinal; var status: integer): Cardinal; var ret, chunkRet, size : integer; buf, p : PByte; begin Result := 0; if status < kStatusNoError then Exit; if fNXTViaUSB then begin if numberOfBytes > 64 then begin // size could be greater than 64. If so, divide up the write // into smaller chunks buf := nil; GetMem(buf, 64); try p := bufferPtr; ret := 0; while numberOfBytes > 0 do begin size := Integer(Min(numberOfBytes, 64)); Move(p^, buf^, size); chunkRet := usb_bulk_write(fDevHandle, USB_OUT_ENDPOINT, PChar(buf), size, fTimeout); if chunkRet < 0 then begin ret := chunkRet; Break; end; inc(p, chunkRet); inc(ret, chunkRet); dec(numberOfBytes, chunkRet); end; finally FreeMem(buf); end; end else begin ret := usb_bulk_write(fDevHandle, USB_OUT_ENDPOINT, PChar(bufferPtr), numberOfBytes, fTimeout); end; end else begin ret := BluetoothWrite(fSerialHandle, bufferPtr, numberOfBytes); end; if ret < 0 then status := ret else begin status := kStatusNoError; Result := ret; end; end; { TNxtFile } procedure TNxtFile.close(var status: integer); var cmd : TBaseCmd; // buf : array[0..3] of Byte; // len, size : integer; begin if status < kStatusNoError then Exit; if not fOpen then Exit; cmd := TBaseCmd.Create; try // TODO: do I have to check the response? cmd.SetVal(kNXT_SystemCmdNoReply, kNXT_SCClose, fHandle); fNXT.write(cmd.GetBody, cmd.GetLength, status); { size := 4; len := read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; status := kStatusNoError; end else status := ConvertStatus(buf[2]); } finally cmd.Free; end; end; constructor TNxtFile.Create(aNXT : TNxt; const aFilename : string); begin inherited Create; fNXT := aNXT; fFilename := aFilename; fHandle := 0; fOpen := False; fSize := 0; fAvailableSize := 0; end; destructor TNxtFile.Destroy; begin inherited; end; function TNxtFile.getAvailableSize(var status: integer): Cardinal; begin Result := 0; if status < kStatusNoError then Exit; if not fOpen then begin openForDataAppend(status); if status = kStatusNoError then close(status); end else status := kStatusDuplicateOpen; Result := fAvailableSize; end; procedure TNxtFile.getName(var fileName: string); begin fileName := fFilename; end; function TNxtFile.getSize(var status: integer): Cardinal; begin Result := 0; if status < kStatusNoError then Exit; if fOpen then Result := fSize else status := kStatusFWUndefinedError; end; procedure TNxtFile.openForDataAppend(var status: integer); var cmd : TNxtCmd; buf : array[0..7] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCOpenAppendData, fFilename); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 8; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; fAvailableSize := BytesToCardinal(buf[4], buf[5], buf[6], buf[7]); fOpen := True; status := kStatusNoError; end else begin status := ConvertStatus(buf[2]); fOpen := False; fHandle := 0; fAvailableSize := 0; end; finally cmd.Free; end; end; procedure TNxtFile.openForDataWrite(sizeInBytes: Cardinal; var status: integer); var cmd : TNxtCmd; buf : array[0..3] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCOpenWriteData, fFilename, sizeInBytes); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 4; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; fSize := sizeInBytes; fOpen := True; status := kStatusNoError; end else begin status := ConvertStatus(buf[2]); fOpen := False; fHandle := 0; fSize := 0; end; finally cmd.Free; end; end; procedure TNxtFile.openForLinearWrite(sizeInBytes: Cardinal; var status: integer); var cmd : TNxtCmd; buf : array[0..3] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCOpenWriteLinear, fFilename, sizeInBytes); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 4; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; fSize := sizeInBytes; fOpen := True; status := kStatusNoError; end else begin status := ConvertStatus(buf[2]); fOpen := False; fHandle := 0; fSize := 0; end; finally cmd.Free; end; end; procedure TNxtFile.openForRead(var status: integer); var cmd : TNxtCmd; buf : array[0..7] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCOpenRead, fFilename); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 8; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; fSize := BytesToCardinal(buf[4], buf[5], buf[6], buf[7]); fOpen := True; status := kStatusNoError; end else begin status := ConvertStatus(buf[2]); fHandle := 0; fSize := 0; fOpen := False; end; finally cmd.Free; end; end; procedure TNxtFile.openForWrite(sizeInBytes: Cardinal; var status: integer); var cmd : TNxtCmd; buf : array[0..3] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCOpenWrite, fFilename, sizeInBytes); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 4; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := buf[3]; fSize := sizeInBytes; fOpen := True; status := kStatusNoError; end else begin status := ConvertStatus(buf[2]); fOpen := False; fHandle := 0; fSize := 0; end; finally cmd.Free; end; end; function TNxtFile.read(bufferPtr: PByte; numberOfBytes: Cardinal; var status: integer): Cardinal; var size : Cardinal; cmd : TBaseCmd; cnt : SmallInt; rbuf : array[0..63] of Byte; len, rsize : integer; p, buf : PByte; begin Result := 0; if status < kStatusNoError then Exit; size := numberOfBytes; p := bufferPtr; cmd := TBaseCmd.Create; try while Result < size do begin cnt := SmallInt(Min(size-Result, kNXT_MaxBytes-6)); cmd.SetVal(kNXT_SystemCmd, kNXT_SCRead, fHandle, Lo(cnt), Hi(cnt)); fNXT.write(cmd.GetBody, cmd.GetLength, status); rsize := cnt + 6; len := fNXT.read(@rbuf[0], rsize, status); if (len = rsize) and (rbuf[2] = 0) then begin status := kStatusNoError; fHandle := rbuf[3]; cnt := SmallInt(BytesToCardinal(rbuf[4], rbuf[5])); buf := @rbuf[6]; Move(buf^, p^, cnt); end else begin status := ConvertStatus(rbuf[2]); break; end; inc(p, cnt); inc(Result, cnt); end; finally cmd.Free; end; end; procedure TNxtFile.remove(var status: integer); var cmd : TNxtCmd; buf : array[0..22] of Byte; len, size : integer; begin if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCDelete, fFilename); fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 23; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fHandle := 0; fSize := 0; fOpen := False; status := kStatusNoError; end else status := ConvertStatus(buf[2]); finally cmd.Free; end; end; function TNxtFile.write(bufferPtr: PByte; numberOfBytes: Cardinal; var status: integer): Cardinal; var cmd : TNxtCmd; p, buf : PByte; size : Cardinal; cnt : Word; Data : array[0..kNXT_MaxBytes-1] of Byte; b : Byte; rbuf : array[0..5] of Byte; len, rsize : integer; begin Result := 0; if status < kStatusNoError then Exit; // write in < 64 byte chunks size := numberOfBytes; p := bufferPtr; // start at the beginning buf := @Data[0]; cmd := TNxtCmd.Create; try while Result < size do begin cnt := Word(Min(size - Result, kNXT_MaxBytes-3)); // fill our buffer with the right number of bytes Move(p^, buf^, cnt); // write these bytes to the NXT if cnt = (size - Result) then b := kNXT_SystemCmd else b := kNXT_SystemCmdNoReply; cmd.MakeCmdWriteFile(b, kNXT_SCWrite, fHandle, cnt, Data); fNXT.write(cmd.GetBody, cmd.GetLength, status); if b = kNXT_SystemCmd then begin rsize := 6; len := fNXT.read(@rbuf[0], rsize, status); if (len = rsize) and (rbuf[2] = 0) then begin status := kStatusNoError; cnt := Word(BytesToCardinal(rbuf[4], rbuf[5])); end else begin status := ConvertStatus(rbuf[2]); break; end; end; inc(p, cnt); inc(Result, cnt); end; finally cmd.Free; end; end; { TNxtFileIterator } procedure TNxtFileIterator.advance(var status: integer); var cmd : TNxtCmd; buf : array[0..27] of Byte; len, size, i : integer; oldHandle : Byte; begin if status < kStatusNoError then Exit; oldHandle := $FF; cmd := TNxtCmd.Create; try if fFirstTime or fValid then begin if fFirstTime then begin // call findfirstmodule fFirstTime := False; cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCFindFirst, fPattern); end else begin // call findnextmodule oldHandle := fHandle; cmd.SetVal(kNXT_SystemCmd, kNXT_SCFindNext, fHandle); end; fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 28; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fFileName := ''; fHandle := buf[3]; for i := 4 to 23 do fFileName := fFileName + Char(buf[i]); fSize := BytesToCardinal(buf[24], buf[25], buf[26], buf[27]); status := kStatusNoError; end else begin // close the previous handle (if there was one) if oldHandle = fHandle then CloseFileHandle(status); status := ConvertStatus(buf[2]); fValid := False; fHandle := 0; end; end else status := kStatusNoMoreItemsFound; finally cmd.Free; end; end; procedure TNxtFileIterator.CloseFileHandle(var status: integer); var cmd : TBaseCmd; begin if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmdNoReply, kNXT_SCClose, fHandle); fNXT.write(cmd.GetBody, cmd.GetLength, status); finally cmd.Free; end; end; constructor TNxtFileIterator.Create(aNXT : TNxt; const aPattern : string); begin inherited Create; fNXT := aNXT; fPattern := aPattern; fValid := True; fFirstTime := True; fFileName := ''; fSize := 0; fHandle := 0; end; destructor TNxtFileIterator.Destroy; begin inherited; end; function TNxtFileIterator.getFile(var status: integer): TNxtFile; begin Result := nil; if status < kStatusNoError then Exit; if fValid then begin Result := TNxtFile.Create(fNXT, fFileName); Result.fSize := fSize; status := kStatusNoError; end else status := kStatusNoMoreItemsFound; end; procedure TNxtFileIterator.getName(var filename: string; var status: integer); begin if status < kStatusNoError then Exit; if fValid then begin filename := fFileName; status := kStatusNoError; end else begin filename := ''; status := kStatusNoMoreItemsFound; end; end; function TNxtFileIterator.getSize(var status: integer): Cardinal; begin Result := 0; if status < kStatusNoError then Exit; if fValid then begin Result := fSize; status := kStatusNoError; end else begin Result := 0; status := kStatusNoMoreItemsFound; end; end; { TNxtIModule } constructor TNxtIModule.Create(aNXT : TNxt); begin inherited Create; fNXT := aNXT; end; destructor TNxtIModule.Destroy; begin inherited; end; function TNxtIModule.getModuleID: Cardinal; begin Result := fModuleID; end; function TNxtIModule.getModuleIOMapSize: Cardinal; begin Result := fIOMapSize; end; function TNxtIModule.getModuleSize: Cardinal; begin Result := fSize; end; procedure TNxtIModule.getName(var moduleName: string); begin moduleName := fModuleName; end; function TNxtIModule.readIOMap(offsetInBytes, numberOfBytes: Cardinal; dataBufferPtr: PByte; var status: integer): Cardinal; var cmd : TNxtCmd; buf : PByte; ret : cardinal; begin Result := 0; if numberOfBytes > 64 then Exit; if not Assigned(dataBufferPtr) then Exit; if status < kStatusNoError then Exit; cmd := TNxtCmd.Create; try cmd.MakeCmdReadIOMap(kNXT_SystemCmd, kNXT_SCIOMapRead, fModuleID, offsetInBytes, numberOfBytes); fNXT.write(cmd.GetBody, cmd.GetLength, status); if status = kStatusNoError then begin GetMem(buf, 64); try ret := fNXT.read(buf, 64, status); if status = kStatusNoError then Result := ret; finally FreeMem(buf); end; end; finally cmd.Free; end; end; function TNxtIModule.writeIOMap(offsetInBytes, numberOfBytes: Cardinal; dataBufferPtr: PByte; var status: integer): Cardinal; begin Result := 0; if offsetInBytes > 64 then Exit; if numberOfBytes > 64 then Exit; if not Assigned(dataBufferPtr) then Exit; if status < kStatusNoError then Exit; (* var cmd : TNxtCmd; b : byte; len : integer; begin Result := Open; if not Result then Exit; cmd := TNxtCmd.Create; try if chkResponse then b := kNXT_SystemCmd else b := kNXT_SystemCmdNoReply; len := fLink.Send(cmd.MakeCmdWriteIOMap(b, kNXT_SCIOMapWrite, ModID, offset, count, buffer.Data)); if chkResponse then begin if len <> 6 then begin Result := False; Exit; end; ModID := fLink.GetReplyCardinal(0); // first 4 bytes count := fLink.GetReplyWord(4); // bytes 5 & 6 end; Result := len >= kRCX_OK; finally cmd.Free; if fAutoClose then Close; end; *) end; { TNxtIModuleIterator } procedure TNxtIModuleIterator.advance(var status: integer); var cmd : TNxtCmd; buf : array[0..33] of Byte; len, size, i : integer; oldHandle : Byte; begin if status < kStatusNoError then Exit; oldHandle := $FF; cmd := TNxtCmd.Create; try if fFirstTime or fValid then begin if fFirstTime then begin // call findfirstmodule fFirstTime := False; cmd.MakeCmdWithFilename(kNXT_SystemCmd, kNXT_SCFindFirstModule, fPattern); end else begin // call findnextmodule oldHandle := fHandle; cmd.SetVal(kNXT_SystemCmd, kNXT_SCFindNextModule, fHandle); end; fNXT.write(cmd.GetBody, cmd.GetLength, status); size := 34; len := fNXT.read(@buf[0], size, status); if (len = size) and (buf[2] = 0) then begin fModuleName := ''; fHandle := buf[3]; for i := 4 to 23 do fModuleName := fModuleName + Char(buf[i]); fModuleID := BytesToCardinal(buf[24], buf[25], buf[26], buf[27]); fSize := BytesToCardinal(buf[28], buf[29], buf[30], buf[31]); fIOMapSize := BytesToCardinal(buf[32], buf[33]); status := kStatusNoError; end else begin // close the previous handle if oldHandle = fHandle then CloseModuleHandle(status); status := ConvertStatus(buf[2]); fValid := False; fHandle := 0; end; end else status := kStatusNoMoreItemsFound; finally cmd.Free; end; end; procedure TNxtIModuleIterator.CloseModuleHandle(var status: integer); var cmd : TBaseCmd; begin if status < kStatusNoError then Exit; cmd := TBaseCmd.Create; try cmd.SetVal(kNXT_SystemCmdNoReply, kNXT_SCCloseModuleHandle, fHandle); fNXT.write(cmd.GetBody, cmd.GetLength, status); finally cmd.Free; end; end; constructor TNxtIModuleIterator.Create(aNXT : TNxt; const aPattern : string); begin inherited Create; fNXT := aNXT; fPattern := aPattern; fValid := True; fFirstTime := True; fModuleName := ''; fModuleID := 0; fSize := 0; fIOMapSize := 0; fHandle := 0; end; destructor TNxtIModuleIterator.Destroy; begin inherited; end; function TNxtIModuleIterator.getModule(var status: integer): TNxtIModule; begin Result := nil; if status < kStatusNoError then Exit; if fValid then begin Result := TNxtIModule.Create(fNXT); Result.fModuleName := fModuleName; Result.fModuleID := fModuleID; Result.fSize := fSize; Result.fIOMapSize := fIOMapSize; status := kStatusNoError; end else status := kStatusNoMoreItemsFound; end; procedure TNxtIModuleIterator.getName(var moduleName: string; var status: integer); begin if status < kStatusNoError then Exit; if fValid then begin moduleName := fModuleName; status := kStatusNoError; end else begin moduleName := ''; status := kStatusNoMoreItemsFound; end; end; { TNxtIterator } procedure TNxtIterator.advance(var status: integer); var bDone : boolean; begin if status < kStatusNoError then Exit; bDone := False; // iterate first through USB devices to find next NXT // and if we reach the end of that list then // iterate through serial ports to find the next if searchBluetooth is true if fNXTViaUSB then begin if fDevHandle <> nil then begin usb_close(fDevHandle); fDevHandle := nil; end; if fBus = nil then fBus := fBusses; while (fBus <> nil) and not bDone do begin if fDev = nil then fDev := fBus^.devices // start at first if nil else fDev := fDev^.next; // advance if not nil while (fDev <> nil) and not bDone do begin bDone := is_nxt_device(fDev); if bDone then Break; fDev := fDev^.next; end; if bDone then Break; fBus := fBus^.next; end; if bDone then begin status := kStatusNoError; fDevHandle := usb_open(fDev); usb_reset(fDevHandle); end else begin status := kStatusNoMoreItemsFound; fNXTViaUSB := False; end; end; if not fNXTViaUSB and fSearchBT then begin status := kStatusNoError; // start with current serial port index // close any open port if fSerialHandle <> 0 then begin BluetoothClose(fSerialHandle); fDevHandle := nil; end; while (fCurSerialIdx < MAX_SERIAL_IDX) and not bDone do begin fSerialHandle := BluetoothOpen(GetSerialDeviceName(fCurSerialIdx)); BluetoothFlush(fSerialHandle); bDone := is_nxt_serial_device(fSerialHandle, fBTTimeout); if bDone then Break; BluetoothClose(fSerialHandle); fSerialHandle := 0; Sleep(100); inc(fCurSerialIdx); end; if bDone then begin status := kStatusNoError; end else begin status := kStatusNoMoreItemsFound; BluetoothClose(fSerialHandle); fSerialHandle := 0; end; end; end; constructor TNxtIterator.Create; begin inherited Create; fBusses := nil; fBus := nil; fDev := nil; fDevHandle := nil; fNXTViaUSB := True; fSearchBT := False; fBTTimeout := 1000; fCurSerialIdx := 0; fSerialHandle := 0; end; destructor TNxtIterator.Destroy; begin if fDevHandle <> nil then begin usb_close(fDevHandle); fDevHandle := nil; end; if fSerialHandle <> 0 then begin BluetoothClose(fSerialHandle); fSerialHandle := 0; end; inherited; end; procedure TNxtIterator.getName(var resourceName: string; var status: integer); begin if status < kStatusNoError then Exit; if fNXTViaUSB then resourceName := GetUSBResString(fDev, fDevHandle) else resourceName := GetSerialResString(fSerialHandle, fBTTimeout); if resourceName <> '' then status := kStatusNoError else status := kStatusNonNXTDeviceSelected; end; function TNxtIterator.getNXT(var status: integer): TNxt; begin Result := nil; if status < kStatusNoError then Exit; Result := TNxt.Create; if fNXTViaUSB then begin Result.fPort := GetUSBResString(fDev, fDevHandle); Result.fCheckver := False; Result.fDev := fDev; Result.fDevHandle := fDevHandle; // usb_set_configuration(fDevHandle, 1); usb_claim_interface(fDevHandle, USB_INTERFACE); fDevHandle := nil; end else begin Result.fPort := GetSerialResString(fSerialHandle, fBTTimeout); Result.fCheckver := False; Result.fSerialHandle := fSerialHandle; fSerialHandle := 0; end; status := kStatusNoError; end; initialization FantomSDKInit; finalization FantomSDKClose; end. bricxcc.mak0000644000175000017500000000462111537752674012571 0ustar slavkoslavkoVER = 1.2.1.r4 NBC_SRC = NXT/nbc.dpr NXT/nbc.cfg NXT/nbc.dof NXT/nbc.res NXT/mkdata.dpr NXT/mkdata.cfg NXT/mkdata.dof NXT/NBCCommon.h NXT/NXTDefs.h NXT/NXCDefs.h NXT_SRC = NXT/uNXTClasses.pas NXT/uNXTConstants.pas NXT/uPreprocess.pas NXT/Parser10.pas NXT/P10Build.pas NXT/uRIC.pas NXT/uNXCComp.pas NXT/uRPGComp.pas NXT/uRICComp.pas NXT/uNBCCommon.pas NXT/uNBCInterface.pas CMN_SRC = uLocalizedStrings.pas uCmdLineUtils.pas uCommonUtils.pas uGenLexer.pas uNBCLexer.pas uNXCLexer.pas uVersionInfo.pas mwGenericLex.pas ParamUtils.pas uGlobals.pas uDebugLogging.pas CMN_SRC2 = FastMM4.pas FastMM4Messages.pas FastMM4Options.inc FastMove.pas FastStrings.pas FANTOM_SRC = bricktools/FANTOM.pas bricktools/FANTOM_CONST.INC bricktools/fantomfpc.pas bricktools/fantomosx.pas bricktools/libusb.pas bricktools/FantomDefs.pas BT_SRC = bricktools/FantomSpirit.pas bricktools/rcx_cmd.pas bricktools/rcx_constants.pas bricktools/uSpirit.pas RIC_SRC = png/*.pas png/obj/*.obj GIFImage.pas EXTRA_DIST = NXT/nbcunix.mak NXT/nbcdelphi.mak NXT/nbcwin32.mak NXT/nbcwincearm.mak bricxcc.mak SAMPLES = tests/struct.nxc tests/bools.nbc tests/test.nxc tests/test.npg DOCS = doc/Readme doc/Changelog MANPAGES = doc/nbc.1 DISTFILES = $(NBC_SRC) $(NXT_SRC) $(CMN_SRC) $(SAMPLES) $(BT_SRC) $(FANTOM_SRC) $(RIC_SRC) $(EXTRA_DIST) $(DOCS) UNIXFILES = $(SAMPLES) $(DOCS) $(MANPAGES) $(NBC_SRC) $(NXT_SRC) $(FANTOM_SRC) $(CMN_SRC) $(BT_SRC) BINDIST = NXT/nbc tests/struct.nxc $(DOCS) $(MANPAGES) OSXBINDIST = NXT/nxtcom_scripts.zip EXCLUDES = --exclude=*.exe --exclude=*.zip --exclude=*.o --exclude=*.~* --exclude=*.dll archivenbc:: clean tar -czf nbc-$(VER).src.tgz $(DISTFILES) $(EXCLUDES) mv nbc-$(VER).src.tgz ../nbc/beta archivenbcbin:: clean tar -czf nbc-$(VER).tgz $(BINDIST) mv nbc-$(VER).tgz ../nbc/beta archivenbcunix:: clean mv unix.mak Makefile mv NXT/nbcunix.mak NXT/Makefile tar -czf nbc-$(VER).unix-src.tgz $(UNIXFILES) Makefile NXT/Makefile mv Makefile unix.mak mv NXT/Makefile NXT/nbcunix.mak mv nbc-$(VER).unix-src.tgz ../nbc/beta archivenbcosx:: clean tar -czf nbc-$(VER).osx.tgz $(BINDIST) $(OSXBINDIST) mv nbc-$(VER).osx.tgz ../nbc/beta archiveall:: clean tar -czf bricxcc.src.tgz *.* img/*.* NXT/*.* samplerate/*.* bricktools/*.* png/*.* png/obj/*.* grep/*.* $(EXCLUDES) clean:: rm -rf *.dcu *.o *.ppu *.rst *.compiled *.bak *.~* *.ddp nbc_preproc.inc realclean:: clean rm -rf *.exe *.dll doc/0000755000175000017500000000000011676036336011216 5ustar slavkoslavkodoc/Readme0000644000175000017500000003501411537752617012344 0ustar slavkoslavko Not eXactly C ------------- Not eXactly C (NXC) is a high level programming language similar to NQC. It targets the new LEGO NXT product. Like NQC, it is available for Windows, Mac OS X, and Linux platforms. While NXC is not yet complete, it is very functional, with a large API for the NXT. The NXC language currently supports the following programming constructs: if/else, while, do-while, repeat, for, switch, until, goto, and asm {} break and continue are both supported within looping constructs. return may be used to exit a subroutine at any point, optionally returning a value to the calling routine. The NXC language supports global variables, local variables, tasks with no parameters, and functions with parameters and return values. Currently supported variable types are: int, short, long, byte, char, bool, unsigned short, unsigned long, unsigned int, float, mutex, string, and arrays of all these types except mutex. (int == short). Global variables may be initialized at the point of declaration using constants or constant expressions. Local variables may also be initialized at their declaration using any type of expression (not limited to constants). Arrays of any dimension may be declared by adding one or more pairs of square brackets after the variable name (int X[];). Global arrays of one dimension may be initialized at the point of declaration using the following syntax: int X[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // 10 elements Multi-dimensional arrays and local arrays must be initialized using the ArrayInit API function. Support for struct declarations and variables of type struct is included as of beta 28. Support for typdefs is also included as of beta 28. NXC supports the following standard C (and NQC) operators: +, -, *, /, %, & (bitwise and), | (bitwise or), ^ (bitwise xor), ! (logical not), ++ (pre and post increment), -- (pre and post decrement), <, <=, >, >=, ==, !=, =, *=, /=, %=, +=, -=, &=, |=, ^=, &&, ||, <<, >>, <<=, >>=, ||=, and +-=. The ?: operator is also supported. Here's the current list of API functions: Acquire(mutex); Release(mutex); Precedes(task1, task2, ..., taskn); Follows(task1, task2, ..., taskn); val = ButtonCount(btn, reset); val = ButtonPressed(btn, reset); ReadButtonEx(btn, reset, pressed, count); ClearSensor(port); ResetSensor(port); val = Sensor(port); val = SensorUS(port); SetSensorLight(port); SetSensorSound(port); SetSensorTouch(port); SetSensorLowspeed(port); SetSensorType(port, type); SetSensorMode(port, mode); SetInput(port, field, value); val = GetInput(port, field); val = SensorType(p); val = SensorMode(p); val = SensorRaw(p); val = SensorNormalized(p); val = SensorScaled(p); val = SensorInvalid(p); val = FirstTick(); val = CurrentTick(); Wait(ms); ResetSleepTimer(); val = IOMA(num); SetIOMA(num); val = FreeMemory(); val = BatteryLevel(); PowerDown(); RebootInFirmwareMode(); ClearScreen(); NumOut(x, y, number, cls=false); TextOut(x, y, string, cls=false); GraphicOut(x, y, filename, cls=false); GraphicOutEx(x, y, filename, vars, cls=false); CircleOut(x, y, radius, cls=false); LineOut(x1, y1, x2, y2, cls=false); PointOut(x, y, cls=false); RectOut(x, y, width, height, cls=false); ResetScreen(); Coast(ports); Float(ports); Off(ports); OnFwd(ports, power); OnRev(ports, power); OnFwdReg(ports, power, regmode); OnRevReg(ports, power, regmode); OnFwdSync(ports, power, turnpct); OnRevSync(ports, power, turnpct); CoastEx(ports, reset); OffEx(ports, reset); OnFwdEx(ports, power, reset); OnRevEx(ports, power, reset); OnFwdRegEx(ports, power, regmode, reset); OnRevRegEx(ports, power, regmode, reset); OnFwdSyncEx(ports, power, turnpct, reset); OnRevSyncEx(ports, power, turnpct, reset); RotateMotor(ports, power, angle); RotateMotorEx(ports, power, angle, turnpct, sync, stop); RotateMotorPID(ports, power, angle, p, i, d); RotateMotorExPID(ports, power, angle, turnpct, sync, stop, p, i, d); SetOutput(ports, field1, value1, ..., fieldN, valueN); val = GetOutput(port, field); val = MotorMode(p); val = MotorPower(p); val = MotorActualSpeed(p); val = MotorTachoCount(p); val = MotorTachoLimit(p); val = MotorRunState(p); val = MotorTurnRatio(p); val = MotorRegulation(p); val = MotorOverload(p); val = MotorRegPValue(p); val = MotorRegIValue(p); val = MotorRegDValue(p); val = MotorBlockTachoCount(p); val = MotorRotationCount(p); ResetTachoCount(ports); ResetBlockTachoCount(ports); ResetRotationCount(ports); ResetAllTachoCounts(ports); PlayFile(filename); PlayFileEx(filename, volume, loop); PlayTone(frequency, duration); PlayToneEx(frequency, duration, volume, loop); val = SoundFlags(); val = SoundState(); StopSound(); val = Random(); // signed word value val = Random(max); // unsigned word value start taskname; ExitTo(taskname); Stop(bvalue); val = abs(n); val = sign(n); val = StrToNum(str); val = StrLen(str); val = StrIndex(str, idx); str = NumToStr(num); str = StrCat(str1, str2, ..., strN); str = SubStr(string, idx, len); str = StrReplace(string, idx, strnew); str = Flatten(num); str = ByteArrayToStr(a); ByteArrayToStrEx(a, s); StrToByteArray(s, a); num = ArrayLen(a); ArrayInit(a, val, cnt); ArraySubset(aout, asrc, idx, len); ArrayBuild(aout, src1, ..., srcN); GetLSInputBuffer(p, offset, cnt, data); GetLSOutputBuffer(p, offset, cnt, data); GetDisplayNormal(x, line, cnt, data); GetDisplayPopup(x, line, cnt, data); GetBTInputBuffer(offset, cnt, data); GetBTOutputBuffer(offset, cnt, data); GetHSInputBuffer(offset, cnt, data); GetHSOutputBuffer(offset, cnt, data); GetUSBInputBuffer(offset, cnt, data); GetUSBOutputBuffer(offset, cnt, data); GetUSBPollBuffer(offset, cnt, data); str = BTDeviceName(p); str = BTConnectionName(p); str = BTConnectionPinCode(p); str = BrickDataName(); GetBTDeviceAddress(p, data); GetBTConnectionAddress(p, data); GetBrickDataAddress(data); val = SoundFrequency(); val = SoundDuration(); val = SoundSampleRate(); val = SoundMode(); val = SoundVolume(); val = ButtonPressCount(b); val = ButtonLongPressCount(b); val = ButtonShortReleaseCount(b); val = ButtonLongReleaseCount(b); val = ButtonReleaseCount(b); val = ButtonState(b); val = CommandFlags(); val = UIState(); val = UIButton(); val = VMRunState(); val = BatteryState(); val = BluetoothState(); val = UsbState(); val = SleepTimeout(); val = SleepTimer(); val = RechargeableBattery(); val = Volume(); val = OnBrickProgramPointer(); val = CustomSensorZeroOffset(p); val = CustomSensorPercentFullScale(p); val = CustomSensorActiveStatus(p); val = SensorBoolean(p); val = SensorDigiPinsDirection(p); val = SensorDigiPinsStatus(p); val = SensorDigiPinsOutputLevel(p); val = MotorPwnFreq(); val = LSInputBufferInPtr(p); val = LSInputBufferOutPtr(p); val = LSInputBufferBytesToRx(p); val = LSOutputBufferInPtr(p); val = LSOutputBufferOutPtr(p); val = LSOutputBufferBytesToRx(p); val = LSMode(p); val = LSChannelState(p); val = LSErrorType(p); val = LSState(); val = LSSpeed(); val = DisplayEraseMask(); val = DisplayUpdateMask(); val = DisplayDisplay(); val = DisplayFlags(); val = DisplayTextLinesCenterFlags(); val = BTDeviceClass(p); val = BTDeviceStatus(p); val = BTConnectionClass(p); val = BTConnectionHandleNum(p); val = BTConnectionStreamStatus(p); val = BTConnectionLinkQuality(p); val = BrickDataBluecoreVersion(); val = BrickDataBtStateStatus(); val = BrickDataBtHardwareStatus(); val = BrickDataTimeoutValue(); val = BTInputBufferInPtr(); val = BTInputBufferOutPtr(); val = BTOutputBufferInPtr(); val = BTOutputBufferOutPtr(); val = HSInputBufferInPtr(); val = HSInputBufferOutPtr(); val = HSOutputBufferInPtr(); val = HSOutputBufferOutPtr(); val = USBInputBufferInPtr(); val = USBInputBufferOutPtr(); val = USBOutputBufferInPtr(); val = USBOutputBufferOutPtr(); val = USBPollBufferInPtr(); val = USBPollBufferOutPtr(); val = BTDeviceCount(); val = BTDeviceNameCount(); val = HSFlags(); val = HSSpeed(); val = HSState(); val = USBState(); SetSoundFrequency(n); SetSoundDuration(n); SetSoundSampleRate(n); SetSoundFlags(n); SetSoundState(n); SetSoundMode(n); SetSoundVolume(n); SetCommandFlags(n); SetUIState(n); SetUIButton(n); SetVMRunState(n); SetBatteryState(n); SetBluetoothState(n); SetUsbState(n); SetSleepTimeout(n); SetSleepTimer(n); SetVolume(n); SetOnBrickProgramPointer(n); ForceOff(n); SetCustomSensorZeroOffset(p, n); SetCustomSensorPercentFullScale(p, n); SetCustomSensorActiveStatus(p, n); SetSensorBoolean(p, n); SetSensorDigiPinsDirection(p, n); SetSensorDigiPinsStatus(p, n); SetSensorDigiPinsOutputLevel(p, n); SetMotorPwnFreq(n); SetLSInputBuffer(p, offset, cnt, data); SetLSInputBufferInPtr(p, n); SetLSInputBufferOutPtr(p, n); SetLSInputBufferBytesToRx(p, n); SetLSOutputBuffer(p, offset, cnt, data); SetLSOutputBufferInPtr(p, n); SetLSOutputBufferOutPtr(p, n); SetLSOutputBufferBytesToRx(p, n); SetLSMode(p, n); SetLSChannelState(p, n); SetLSErrorType(p, n); SetLSState(n); SetLSSpeed(n); SetDisplayEraseMask(n); SetDisplayUpdateMask(n); SetDisplayDisplay(n); SetDisplayFlags(n); SetDisplayTextLinesCenterFlags(n); SetDisplayNormal(x, line, cnt, data); SetDisplayPopup(x, line, cnt, data); SetBTDeviceName(p, str); SetBTDeviceAddress(p, addr); SetBTConnectionName(p, str); SetBTConnectionPinCode(p, code); SetBTConnectionAddress(p, addr); SetBrickDataName(str); SetBrickDataAddress(p, addr); SetBTDeviceClass(p, n); SetBTDeviceStatus(p, n); SetBTConnectionClass(p, n); SetBTConnectionHandleNum(p, n); SetBTConnectionStreamStatus(p, n); SetBTConnectionLinkQuality(p, n); SetBrickDataBluecoreVersion(n); SetBrickDataBtStateStatus(n); SetBrickDataBtHardwareStatus(n); SetBrickDataTimeoutValue(n); SetBTInputBuffer(offset, cnt, data); SetBTInputBufferInPtr(n); SetBTInputBufferOutPtr(n); SetBTOutputBuffer(offset, cnt, data); SetBTOutputBufferInPtr(n); SetBTOutputBufferOutPtr(n); SetHSInputBuffer(offset, cnt, data); SetHSInputBufferInPtr(n); SetHSInputBufferOutPtr(n); SetHSOutputBuffer(offset, cnt, data); SetHSOutputBufferInPtr(n); SetHSOutputBufferOutPtr(n); SetUSBInputBuffer(offset, cnt, data); SetUSBInputBufferInPtr(n); SetUSBInputBufferOutPtr(n); SetUSBOutputBuffer(offset, cnt, data); SetUSBOutputBufferInPtr(n); SetUSBOutputBufferOutPtr(n); SetUSBPollBuffer(offset, cnt, data); SetUSBPollBufferInPtr(n); SetUSBPollBufferOutPtr(n); SetBTDeviceCount(n); SetBTDeviceNameCount(n); SetHSFlags(n); SetHSSpeed(n); SetHSState(n); SetUSBState(n); val = CreateFile(fname, fsize, handle); val = OpenFileAppend(fname, fsize, handle); val = OpenFileRead(fname, fsize, handle); val = CloseFile(handle); val = ResolveHandle(fname, handle, writeable); val = RenameFile(oldname, newname); val = DeleteFile(fname); val = Read(handle, n); val = ReadLn(handle, n); val = ReadBytes(handle, len, buf); val = Write(handle, n); val = WriteLn(handle, n); val = WriteString(handle, str, cnt); val = WriteLnString(handle, str, cnt); val = WriteBytes(handle, buf, cnt); val = WriteBytesEx(handle, len, buf); val = SendMessage(queue, msg); val = ReceiveMessage(queue, clear, msg); val = LowspeedStatus(port, bready); val = LowspeedBytesReady(port); val = LowspeedCheckStatus(port); val = LowspeedWrite(port, retlen, buffer); val = LowspeedRead(port, buflen, buffer); val = I2CStatus(port, bready); val = I2CBytesReady(port); val = I2CCheckStatus(port); val = I2CWrite(port, retlen, buffer); val = I2CRead(port, buflen, buffer); val = I2CBytes(port, inbuf, count, outbuf) val = BluetoothStatus(conn); val = BluetoothWrite(conn, buffer); result = ReceiveRemoteBool(queue, clear, bval); result = ReceiveRemoteNumber(queue, clear, val); result = ReceiveRemoteString(queue, clear, str); result = ReceiveRemoteMessageEx(queue, clear, str, val, bval); result = SendRemoteBool(conn, queue, bval); result = SendRemoteNumber(conn, queue, val); result = SendRemoteString(conn, queue, str); result = SendResponseBool(queue, bval); result = SendResponseNumber(queue, val); result = SendResponseString(queue, str); result = RemoteMessageRead(conn, queue); result = RemoteMessageWrite(conn, queue, msg); // alias for SendRemoteString result = RemoteStartProgram(conn, filename); result = RemoteStopProgram(conn); result = RemotePlaySoundFile(conn, filename, bloop); result = RemotePlayTone(conn, frequency, duration); result = RemoteStopSound(conn); result = RemoteKeepAlive(conn); result = RemoteResetScaledValue(conn, port); result = RemoteResetMotorPosition(conn, port, brelative); result = RemoteSetInputMode(conn, port, type, mode); result = RemoteSetOutputState(conn, port, speed, mode, regmode, turnpct, runstate, tacholimit); result = Sqrt(X); result = Sin(X); result = Cos(X); result = Asin(X); result = Acos(X); SysCall(func, args); SysFileOpenRead(FileOpenType & args); SysFileOpenWrite(FileOpenType & args); SysFileOpenAppend(FileOpenType & args); SysFileRead(FileReadWriteType & args); SysFileWrite(FileReadWriteType & args); SysFileClose(FileCloseType & args); SysFileResolveHandle(FileResolveHandleType & args); SysFileRename(FileRenameType & args); SysFileDelete(FileDeleteType & args); SysSoundPlayFile(SoundPlayFileType & args); SysSoundPlayTone(SoundPlayToneType & args); SysSoundGetState(SoundGetStateType & args); SysSoundSetState(SoundSetStateType & args); SysDrawText(DrawTextType & args); SysDrawPoint(DrawPointType & args); SysDrawLine(DrawLineType & args); SysDrawCircle(DrawCircleType & args); SysDrawRect(DrawRectType & args); SysDrawGraphic(DrawGraphicType & args); SysSetScreenMode(SetScreenModeType & args); SysReadButton(ReadButtonType & args); SysCommLSWrite(CommLSWriteType & args); SysCommLSRead(CommLSReadType & args); SysCommLSCheckStatus(CommLSCheckStatusType & args); SysRandomNumber(RandomNumberType & args); SysGetStartTick(GetStartTickType & args); SysMessageWrite(MessageWriteType & args); SysMessageRead(MessageReadType & args); SysCommBTWrite(CommBTWriteType & args); SysCommBTCheckStatus(CommBTCheckStatusType & args); SysKeepAlive(KeepAliveType & args); SysIOMapRead(IOMapReadType & args); SysIOMapWrite(IOMapWriteType & args); SysIOMapReadByID(IOMapReadByIDType & args); SysIOMapWriteByID(IOMapWriteByIDType & args); SysDisplayExecuteFunction(DisplayExecuteFunctionType & args); SysCommExecuteFunction(CommExecuteFunctionType & args); SysLoaderExecuteFunction(LoaderExecuteFunctionType & args); You can find NXC at http://bricxcc.sourceforge.net/nxc/. doc/Changelog0000644000175000017500000021313211537752617013035 0ustar slavkoslavkoNBC/NXC Release Notes ----------------- Please send bug reports to bricxcc@comcast.net. Be sure to include details about what platform you are running nbc/nxc on and a sample file that demonstrates the bug if possible. For updates and additional documentation, visit the NBC Web Site: http://bricxcc.sourceforge.net/nbc/. Send emails to bricxcc@comcast.net. Version 1.2.1.r4 (2011-03-13) ----------------------------- - Fixed a problem with using NBC keywords in NXC code. - Fixed GetBrickDataAddress defect (nested asm blocks are not supported) - Fixed HSMode offset in NBCCommon.h - Enum and switch case label fixes/changes for NXC - Fixed bug in StrReplace. - Fixed bug in FileResize subroutine - Compiler optimizer fix to work around standard firmware bug when output variable is float - Fixed small problem with negative numbers as parameter default values. - Fixed CurrentTick and FirstTick to return unsigned value - Fixed bug in bcd2dec (was using signed stack instead unsigned) - Fixed bug in switch statement containing a continue - Fixed defect with OnFwdSyncPID, OnRevSyncPID, OnFwdRegExPID, and OnRevRegExPID. - Added support for math assignment with arrays of UDTs - Added support for new enhanced firmware FileTell system call function - Added MemoryManager system call function - Added API functions for the LEGO temperature sensor, HiTechnic Magnet and Angle sensors, the Codatex RFID sensor, and the new MemoryManager system call. - Added support for setting the new BtDataMode and HsDataMode fields in the Comm module IOMap - Added support for HS multi-NXT addressing (requires latest 1.31 enhanced NBC/NXC firmware) - Added SizeOf API function and modified Read and ReadLn to use it. - Added Pos function. - API header file changes for fopen and other minor things - Moved IOCtrl module functions after Command module functions - StrCat and overloaded + operator changes (for string concatenation) - Made SetHSMode an inline function so that it checks for int-sized input parameter - Added support for escaping in character literals - Added support for optional string error message in compchk opcode. - Added support for position regulation - Updated example code for GetBrickDataAddress - Replaced the sample programs for FlattenVar and UnflattenVar. - Added example file documentation - Added examples for the Mindsensors ACCLNx device - New examples for the MemoryManager system call function and limits.h constants. - Adding examples for new API functions. - New examples for FindFirstFile and FindNextFile. - Updated doxygen comments for several functions that no longer require constant inputs - Many API additions and changes Version 1.2.1.r3 (2010-06-29) ----------------------------- - Fixed a bug with the new comma operator support when using ?: in function calls - Fixed reference count NBC optimization defect when function is defined after all its callers. - Fixed global initialization defect when the global declaration occurs after task main. - Renaming addr, reladdr, and addrex to be addressOf, reladdressOf, and addressOfEx. Version 1.2.1.r2 (2010-06-06) ----------------------------- - Reverted changes to relation expressions so you again have to use parenthesis if you want a relation on the RHS of a relation. - Fixed a bug with the precedence level of the ! operator. - Added support for comma operator. - Fixed regression in ReadSensorMSPlayStation and ReadSensorMSPlayStationEx - Added command line switch to turn off status messages. - Significant changes to expression parsing to correct operator precedence and associativity defects. - Fixed string and character literal parsing bug (for the '/' character) - Fixed NBC sizeof operator bug (it was incorrectly padding the size of byte-sized fields in structures). - Fixed compiler hang when a struct array member specifies a size. The size now simply ignored. - Fixed preprocessor defect with "." in front of a preprocessor macro - Allow for a string to be considered an array type when passing it as parameter to a function. Also return an ArrayBaseType of TOK_BYTEDEF when a string is passed in and return 1 from GetArrayDimension when a string is passed in. Version 1.2.1.r1 (2010-05-13) ----------------------------- - Added support for '\' line continuation characters in NBC source code. - Added support for initializing structs and for declaring const structs. - Added Arno van der Vegt's graphics library to the standard header files. - Added Tone type and the PlayTones and PlaySound functions. - Fixed defect in DrawGraphicType structure - Fixed some case sensitive bugs in the NXC parser. - Fixed NBC sizeof to not pad - Add compiler status message if compile failed - Fixed bug in reference parameters following an array or UDT argument - Added support for string expressions in several API functions including StrCat. - Default compiler firmware version target is now 128 (used to be 105). - Header files now contain doxygen comments - Fixed a bug in atof - Added DisplayFont, SetDisplayFont, and addr functions - Added support for assignments as expressions - Fixed a bug with asm statements passed into function call parameters - Fixed a bug in for loop initialization when declaring a local variable of type float - Added DRAW_OPT_POLYGON_POLYLINE constant to support enhanced firmware change to DrawPolygon system call - Improved support for math assignment operations with arrays and structs - Fixed defect in NXCDefs.h where float type was used outside a check for firmware > 107 - Added ClearLine API function - Fixed a bug in inline functions that return a struct - Fixed a bug passing a UDT array expression into an inline function taking a UDT arg - Added reladdr and addrex functions (requires latest enhanced NBC/NXC firmware) - Fixed memcmp function - Added support for full boolean expressions on RHS of relation Version 1.0.1.b36 ----------------- - Added support for \", \', and \\ embedded in NXC and NBC strings. - Added -ER=n maximum compiler error switch. Filtered out duplicate errors as well. - Added support for 2D scalar constant array initialization using nested brace pairs. e.g., int xyz[][] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; - Added support for global constant string initialization and subsequent usage. e.g., const string g_bar = "bar"; const string g_foo = g_bar; - Added support for constant string array initialization using comma-separated string constants within brace pairs. e.g., string msgs[] = {"hi", "there", "testing", g_bar, g_foo}; - Added support for multi-dimensional array indexing on both the LHS and RHS side of expressions. e.g., foo[i][j] = foo[i][j] + 1; - Added support for returning a struct from a function. - Added support for #download "filename" preprocessor command in NBC/NXC - Added support for import keyword in RICScript - Added support for struct "dot" notation, e.g., mydata[0].foo = 10; int x = mydata[0].foo; - Added support for "typedef struct" syntax - Added support for byte array to string assignment in NXC - Fixed bug in Random() API function - Added support for array math operation syntax in NXC, e.g., array += 2; array = !array, etc... - Fixed multi-line macro parsing bugs and problems with preprocessor directives mixed in with expressions. - Compiler is now compatible with both 1.0x firmwares and 1.2x firmwares. - Added API support for HiTechnic touch sensor multiplexer in NBC/NXC. - Added support for variadic macros. - Added support for macro redefinition (with warnings). - Added support for floats in NBC/NXC with 1.2x firmwares. - Improved support for unsigned long expressions. - Added API support for setting baud rate and mode of Hi Speed port with enhanced firmware. - Added API support for LEGO Color sensor - Fixed a preprocessor bug which broke nested #else statements - Added NXC API functions for enhanced firmware math opcodes (atan, ceil, exp, floor, tan, tanh, cosh, sinh, log, log10, atan2, pow, trunc, frac, muldiv32, cos, acos, sin, and asin) - Added NBC/NXC API support for HiTechnic EOPD sensor - Added firmware and NBC/NXC API support for reading/setting the display Contrast (SetDisplayContrast(byte contrast); and byte DisplayContrast(void);) - Added compiler optimization for constant shifts - Improved function prototype support - Added NXC API functions for enhanced firmware math opcodes (atand, tand, tanhd, acosd, cosd, coshd, asind, sind, sinhd, atan2d) - Added firmware version check when downloading compiled .rxe to NXT. - Level 2 optimization bug fixes - Cross platform fixes/64-bit support - Support for Array and UDT expressions in parameter passing. - Inline functions can now call other inline functions - const type arguments to inline functions can now be treated as a compile-time constant. - fixed a bug in the preprocessor for char type #defines (e.g., #define test 'c') - fixed a optimizer bug that was removing safecall mutexes that should not be removed - Added API support for HiTechnic IRSeeker 2 and Color 2 sensors - Added API functions to read I2C Version, VendorId, and DeviceId values - Added support for optional parameters using a not exactly C syntax (delphi-like) - fixed bug in structs containing arrays with more than one dimension. - fixed defects 2902670 & 2896265. http://sourceforge.net/tracker/?func=detail&aid=2902670&group_id=68600&atid=521776 http://sourceforge.net/tracker/?func=detail&aid=2896265&group_id=68600&atid=521776 - Added support for enum keyword - Added command-line parameter to specify preprocessor recursion max depth (default is 10) - Fixed defect 2908377. http://sourceforge.net/tracker/?func=detail&aid=2908377&group_id=68600&atid=521776 - Added support for struct member declaration using comma-separated variable names. - Fixed defect 2922394. http://sourceforge.net/tracker/?func=detail&aid=2922394&group_id=68600&atid=521776 - Added compiler status output to stdout. Version 1.0.1.b35 ----------------- - Exposed the bcd2dec API function in NXC. - Fixed a bug when whitespace separates open parenthesis and function name e.g., y = mal2 (7); - Added support for bitwise negation (complement) in NXC using the ~ operator. This requires the enhanced NBC/NXC firmware. - Added support for local array initialization in NXC. Only single dimension arrays of non-aggregate types are supported. - Fixed a bug in the symbol table output where preprocessor declarations were being erroneously stripped. - Fixed a line number reporting problem in NXC when using #include for non-system header files. - Added .ric file decompilation to the NBC compiler. - Added support for new opcodes and system calls in the latest enhanced NBC/NXC firmware. The new system calls are FileFindFirst, FileFindNext, FileOpenWriteLinear, FileOpenWriteNonLinear, FileOpenReadLinear, CommHSControl, CommHSCheckStatus, CommHSWrite, and CommHSRead. The new opcodes are arrop, acos, asin, atan, ceil, exp, fabs, floor, sqrt, tan, tanh, cos, cosh, log, log10, sin, sinh, atan2, fmod, and pow. - Added support for all the Power Function modes via the HiTechnic iRLink I2C device. See the new HTPFComboDirect, HTPFSinglePin, HTPFSingleOutputCST, HTPFSingleOutputPWM, HTPFComboPWM, HTPFTrain, HTPFRawOutput, and HTPFRepeat NBC and NXC API functions. - Added support for the IR Train receiver via the HiTechnic iRLink I2C device. See the new HTPFIRTrain NBC and NXC API functions. - Fixed bugs in unused variable removal and mutex removal. - Changed compiler to use -Z1 optimization as the default optimization level. - Added API functions to NBC and NXC for the Mindsensors pressure sensor, obstacle sensor, acceleration/tilt sensor, distance sensor, play station sensor, and the NRLink sensor with RCX, Power Function, and IR Train support. Version 1.0.1.b34 ----------------- - Fixes a typo bug in the math API functions introduced in b33. Version 1.0.1.b33 ----------------- - Fixes a bug in checking type compatibility when calling a function that has an array of struct as an argument. - Fixes a bug in asm blocks containing a structure field reference that was being improperly decorated by the compiler. - Fixes a bug in array assignment to a local array variable at the point of declaration. - Adds stopthread, fmtnum, and priority opcodes to NBC & NXC using the enhanced NBC/NXC firmware. - Fixed a typo bug in the SendRemoteString API macro. - Fixed a bug in NXC variable decoration and the NBC __I__ and __J__ substitution parameters. Case insensitivity and underscores in the decoration scheme were combining to break simple NXC int i; and int j; declarations. - Fixed a bug in deciding whether to emit a set or a mov operation in NXC. - Fixed a bug in the way NXC handled local variables going out of scope. - Fixed a bug where the left and right shift opcodes were not guarding against invalid arguments which was resulting in an access violation. - Fixed a bug with semicolons following asm blocks when used in expressions. - Fixed a bug with SetSoundState in NBC & NXC caused by macro name clashes. - Fixed a bug with SetSoundFlags in NBC & NXC caused by a size type error. - Added API functions for HiTechnic devices. - Added API functions for mindsensors devices. - Added FlattenVar and UnFlattenVar API functions to NXC. - Added ResizeFile API function to NBC and NXC. - Fixed File Error! bug in left and right shift operations if the enhanced firmware is enabled. - Fixed a shift bug where if the output variable was a smaller type it was losing precision before the shift took place. - Added bcd2dec function to NBC and NXC. - Fixed an infinite loop compiler bug when the inline keyword occurs after the void keyword. - Fixed a compiler error line number reporting bug. - Changed compiler to write errors to stderr rather than stdout - Increased compilation speed for large programs - Complete overhaul of IOMAP-based API functions to support variable-based IOMAP offsets in NXC and NBC. Version 1.0.1.b32 ----------------- - Fixes a couple NXC system call structure definition bugs. - Adds compchktype compile-time opcode for checking variable types in preprocessor macros. - Changes low-level NXC syscall inline functions to use preprocessor macros with type checking instead (for improved code efficiency). - Fixes an access violation when trying to compile user-defined type references which include invalid member names. - Allows array opcodes to take constant array arguments - Reworked low level IOMap read and write NXC API functions to allow non-constant arguments for ports, etc... - Fixed a bug in RotateMotor functions which can cause it to hang if another task changes the power level while the function is waiting for the target tacho limit to be reached. - Fixed a bug in I2CBytes and SensorUS and the NBC equivalents which made the functions not work for constant port values for ports 3 and 4. - Fixes a bug in variable and parameter name decoration which made task & function names containing an underscore not work correctly in some situations. - Fixes a bug in argument passing to array, struct, and reference type parameters. The compiler was failing to raise an error when expressions are used in these cases. Version 1.0.1.b31 ----------------- - Fixes a boolean expression bug which occurred when you used a numeric variable or constant on its own in a logical AND operation. (e.g., if (Nsamps && x < 3)). - Fixes problems with reference type arguments that are arrays or user-defined types. - Fixes problems where the compiler hangs while processing function parameters. - Fixes several other struct and array parameter passing problems. - Fixes NXTDefs.h typo bug in ResetAllTachoCounts. - Fixes NXCDefs.h typo bug in I2CStatus. - Tightened up semicolon checking so that the parser complains when they are required but they are missing. - Fixed global array initialize when a length expression is specified and an initial value is also specified. The length, in that case, is now ignored since the array is statically initialized. - Fixed a problem with initializing multi-dimensional global or local arrays where the generated nested variable type declaration was causing an NBC compiler error. - Improved parsing of open and close parenthesis so that the compiler will complain if you have an extra close parenthesis. - Added code in the NXC compiler to initialize a hidden graphic variables array and use it when calling the GraphicOut API function so that parameterized RIC files can be drawn using either GraphicOut or GraphicOutEx. - Added support in NBC for RICScript programs which can be used to create RIC files via a simple text programming language. A source file with a .rs extension will use the RICScript compiler built into NBC and the output will be a .ric file if there are no compiler errors. - Adds the "safecall" keyword to NXC. A function or subroutine declared with this keyword will automatically be wrapped in Acquire/Release with a global mutex specific to that function so that multiple threads can safely call the function without hanging. - Adds the -safecall command line switch for NXC. If a program is compiled with this switch on the command line then all function calls will use the safecall calling convention, i.e., they will be wrapped in Acquire/Release so that multiple tasks/threads can share the subroutine safely. - Fixes inline functions so that they are now thread-safe. - Added code to the parser to complain about recursive function calls since they are not supported by the NXT firmware. - Added code to the parser to complain about calling an inline function from another inline function call. - Fixed a for-loop local variable nesting level bug that made for-loop variables not work correctly if defined within the for-loop parenthesis. - Added NXC/NBC API function I2CCheckStatus and LowspeedCheckStatus which only return the status (and not bytes ready). Added I2CBytesReady and LowspeedBytesReady which only return the number of bytes ready but not the status. (NBC does not include the I2C alias versions). - Added constants and structure declarations for enhanced firmware features in lms_arm_jch.zip. If using the enhanced standard NXT firmware make sure to pass -EF on the NBC/NXC command line. - Fixes a bug in struct declarations which was causing the compiler to not support types with the "unsigned" type qualifier keyword prior to the type name. - Added several low-level syscall inline functions to NXC. - Fixed type checking of function parameters that are user-defined types. This had just been checking that the variable passed in was a UDT but it now makes sure the two types of UDT are the same. Version 1.0.1.b30 ----------------- - Fixes a bug in the RotateMotorExPID macro in NXTDefs.h that was introduced in b29. - Fixes error message line number problems in NBC that were introduced in b29. - Added NXC compiler error message when trying to use nested calls to the same function (e.g., Max(3, Max(5, 6)). - Fixes an expression optimizer bug which was intrepeting variables that looked like valid hexadecimal numbers as a constant value (e.g., xa0, x1, x03, xff). - Fixes a bug in the NXC compiler's support for function prototypes that was introduced in b29. - Adds support in NXC for the "return" statement to have optional parenthesis around the return expression when the return type is string. Scalar types already support surrounding parenthesis as part of the expression parsing. - Fixes a bug in the NBC compiler support for compif/compelse/compend where code that should have been ignored by the compiler was not being ignored. - Fixes a bug in ## handling within non-parameterized preprocessor macros. - *** NXC & NBC BREAKING CHANGE *** Changed the RotateMotorEx API functions (in b29, actually) to take an additional boolean parameter. RotateMotorExPID(ports, pwr, angle, turnpct, bsync, bStop, p, i, d) RotateMotorEx(ports, pwr, angle, turnpct, bSync, bStop) The new "bStop" parameter indicates whether you want the motors to come to a hard stop at the end of the specified angle of rotation. - Fixes NXC bug with empty strings causing a compiler error. Now empty strings work as expected. Version 1.0.1.b29 ----------------- - Fixes a bug with not setting the left hand side datatype correctly after a user defined type is used. - Fixes reading a struct out of an array of struct. - Fixes a bug in NXC switch statements that have no default case where the first case was being improperly executed. - Fixes a bug with initialized globals which was causing them to be treated as constants in math expressions. - Overhauled the I2C routines and the Motor routines. The old OUT_AB, OUT_AC, OUT_BC, and OUT_ABC array variables are now constants. The motor API functions are now thread-safe and blocking on the motor resource(s) requested. If you call RotateMotor(OUT_AB, 75, 3600) then no other thread will be able to control motors A and B until the already executing RotateMotor function finishes. But now you can safely call RotateMotor(OUT_A, 75, 3600) on one thread and RotateMotor(OUT_B, 75, 720) on another simultaneously executing thread without having program errors or erratic motor behavior. The same sort of revisions occurred for the Lowspeed (aka I2C) routines so that it is now safe to call I2C functions for a port on one thread while calling I2C functions for a different port on another thread. Since the functions do not know at compile time which port is being utilized when you use a variable as the port parameter, the RotateMotor functions acquire all three motor port resources for the duration of their operation in that case. So you can safely call RotateMotor using a variable for the port parameter on two simultaneously executing threads but one of the two calls will be blocked until the first one has completed executing. - Added GraphicOutEx for NXC which takes an array of values which can change the drawing behavior at runtime. - Changed NumOut and TextOut in NXC so they accept an optional 4th argument (cls) which controls whether the screen is cleared or not. This makes these functions consistant with the other drawing routines. - Changed NumOutEx and TextOutEx in NBC so that the cls argument is the fourth argument rather than the third argument (NumOutEx(x, y, value, cls) rather than NumOutEx(x, y, cls, value)). This change makes these two functions consistant with the other Ex drawing routines in NBC. - Changed ArrayBuild in NXC so that instead of having ArrayBuild1..ArrayBuild4 defined in the NXCDefs.h header file the function is now built into the compiler and it can take any number of source arguments. E.G., ArrayBuild(aout, src1, ..., srcN); - Fixed a problem in the NXC preprocessor where it was incorrectly handling char constants (e.g., ArrayInit(aout, 'a', 10);). - Fixed a problem in I2CBytes/ReadI2CBytes where it was returning true even when an error occurred during the write/read operation. Now these functions return false if any sort of error condition occurred during the I2C operation. - Added new NXC functions which are aliases for the LowspeedStatus, LowspeedRead, and LowspeedWrite functions. The new NXC functions are named I2CStatus, I2CRead, and I2CWrite. - Changed the behavior of the ## operator in the preprocessor. In previous versions a token such as OUT_A would be left as a literal if it was concatenated with the preceding value but in this version OUT_A will be evaluated as 0 before it is concatenated with the preceding value. E.G., myVar##port, in previous releases would have ended up as myVarOUT_A, but as of b29 it will end up as myVar0. - Changed the preprocessor to evaluate tokens until no changes occur during evaluation. As of b29 if the first preprocessor evaluation produces __rotateMotor0 as a token then it will evaluate the result again which may expand that token into a multi-line macro function expansion. This will continue until the pre- evaluation value matches the post-evaluation value. This change was required to implement the motor and I2C API changes mentioned above. - Changed the compiler to automatically include NXTDefs.h or NXCDefs.h (and NBCCommon.h) automatically just as NQC would automatically include its API header file. This can be disabled via the new -n command line switch. The header files are actually compiled into the compiler executable. The contents of the built-in header files can be extracted via the new -api command line switch. As a result of this change it is no longer necessary to start an NBC or NXC program with #include "NXTDefs.h" or #include "NXCDefs.h". - Renamed the Tamas Sorosy math functions added in b28 so that they do not conflict with the compile-time expression evaluator functions of the same names. The new function names are Sqrt, Sin, Cos, Asin, and Acos. - Added a -q command line switch which tells the compiler to not make the NXT beep at the end of a program download operation. - Changed the compiler so that, by default, it tells the NXT to beep after downloading a program. - Changed the compiler so that it stops any running program before starting to download a program. - Added compif, compelse, and compend operations to the NBC compiler so that it can determine at compile-time whether to ignore or include certain blocks of code. This compiler processing occurs after the preprocessor is finished. - Fixed the NXC function parameter parser so that if an error occurs while parsing the parameter declarations it will abort and skip to the closing parenthesis. This had been a place where the parser could get into an infinite loop prior to this change. Version 1.0.1.b28 ----------------- - Adds support for structs and typedefs. See struct.nxc for examples. - Adds Tamas Sorosy math functions (sqrt, sin, cos, asin, acos) to NBC and NXC API. - Adds a 15 ms wait in ReadSensorUS (NBC) and SensorUS (NXC) to fix a problem where when called in a tight loop a manual wait was needed to get correct readings. - Adds preprocessor support for #if, #elif, and #error. - Adds support for alternate NXT firmwares which implement the wait and waitv opcodes. Use the -EF switch to enable this feature. - Adds support for short-circuit boolean expression evaluation (for && and || operators) - Adds a workaround in NXC for a firmware bug in the "set" opcode which is triggered by setting a signed long to a negative number. - Fixes a preprocessor bug with nested #ifdefs. - Fixes a preprocessor bug with nested function macros with empty parameter lists. - Fixes an optimizer bug which was generating bad code for the sign opcode. - The NXC compiler now accepts (void) in addition to () for task declarations. - The NXC compiler now outputs an error if the routine named "main" is declared using a keyword other than "task". Version 1.0.1.b27 ----------------- - Adds pre-increment and pre-decrement (++i, --i) support. - Adds support for expressions as statements task main() { int i=23; 0x3f; +3-i; } - Adds support for pre- and post-increment/decrement within expressions (such as in array indexes). Increment/decrement used to only be allowed in a statement. - Fixes some string array indexing bugs - Adds support for string expressions within TextOut API function - *** NXC BREAKING CHANGE *** Removed the "cls" argument from the NumOut and TextOut functions. To update your code to work with beta 27 you will need to add calls to ClearScreen() wherever you previously passed "true" to this argument and remove the additional argument from each call to one of these API functions. The PointOut, CircleOut, LineOut, RectOut, and GraphicOut API functions all now take cls as an optional argument with a default value of false. Since this argument is optional it can still be used but if you are currently passing "false" to these functions you can now remove the extra argument. - *** NBC BREAKING CHANGE *** Removed the "cls" argument from the NumOut, TextOut, PointOut, CircleOut, LineOut, RectOut, and GraphicOut functions. Added NumOutEx, TextOutEx, PointOutEx, CircleOutEx, LineOutEx, RectOutEx, and GraphicOutEx API functions which all include the "cls" argument exactly as the non-Ex versions did prior to beta 27. To update your code to work with beta 27 you will need to either add calls to ClearScreen() wherever you previously passed "true" to this argument and remove the additional argument from each call to one of the non-Ex API functions OR you can replace your calls to the non-Ex version with calls to the Ex version of the API function. - Adds -w- and -w+ command line switches which let you control whether the compiler outputs warning messages or not. The default is - which means that warnings are not output. If you want to turn on warnings then add the new -w+ switch to the command line. - Fixes a mutex optimization bug which was incorrectly removing acquire/release statements and mutex variables. Version 1.0.1.b26 ----------------- - Fixes an array indexing bug introduced in b25 - Fixes a local variable declaration bug introduced in b25 - Fixes a bug in the NXC and NBC Read API functions - Fixes a bug in the NXC and NBC WriteLnString API function - Adds support for asm block statements anywhere within an NXC file (not just within a task or subroutine) - Adds a ReadLnString API function to NBC and NXC - Fixes a preprocessor bug where comments following a #include statement were breaking the include Version 1.0.1.b25 ----------------- - Fixes string whitespace bug introduced in b22 - Fixes division bug where 1st operand is negative and 2nd operand is unsigned - Fixes bugs in the NBC and NXC file I/O macros - Adds support in NXC for string indexing string msg = "test"; msg[0] = 'C'; byte x = msg[2]; - Adds support in NXC for inline functions inline int Double(const int x) { return x*2; } - Adds support in NXC for const and reference function argument types inline bool IsFooBar(int x, int &handle) { handle = 10; x = x+1; return x > 2; } - Adds support in NXC for const variable declarations const int myVar = 12; // myVar cannot be changed. - Adds support in NXC for arrays of strings string myStrings[]; ArrayInit(myStrings, "", 4); // set array of strings to a size of 4 (0..3) myStrings[0] = "please work"; myStrings[1] = "testing"; - Improves NXC parameter type checking in function calls - Adds NBC API macros to simplify NXT<->NXT bluetooth communication ReceiveRemoteBool(queue, clear, bval, result) ReceiveRemoteNumber(queue, clear, val, result) ReceiveRemoteString(queue, clear, str, result) ReceiveRemoteMessageEx(queue, clear, str, val, bval, result) SendRemoteBool(conn, queue, bval, result) SendRemoteNumber(conn, queue, val, result) SendRemoteString(conn, queue, str, result) SendResponseBool(queue, bval, result) SendResponseNumber(queue, val, result) SendResponseString(queue, msg, result) - Adds NBC API macros for sending direct commands to another NXT RemoteMessageRead(conn, queue, result) RemoteMessageWrite(conn, queue, msg, result) // alias for SendRemoteString RemoteStartProgram(conn, filename, result) RemoteStopProgram(conn, result) RemotePlaySoundFile(conn, filename, bloop, result) RemotePlayTone(conn, frequency, duration, result) RemoteStopSound(conn, result) RemoteKeepAlive(conn, result) RemoteResetScaledValue(conn, port, result) RemoteResetMotorPosition(conn, port, brelative, result) RemoteSetInputMode(conn, port, type, mode, result) RemoteSetOutputState(conn, port, speed, mode, regmode, turnpct, runstate, tacholimit, result) - Adds NXC API macros to simplify NXT<->NXT bluetooth communication result = ReceiveRemoteBool(queue, clear, bval) result = ReceiveRemoteNumber(queue, clear, val) result = ReceiveRemoteString(queue, clear, str) result = ReceiveRemoteMessageEx(queue, clear, str, val, bval) result = SendRemoteBool(conn, queue, bval) result = SendRemoteNumber(conn, queue, val) result = SendRemoteString(conn, queue, str) result = SendResponseBool(queue, bval) result = SendResponseNumber(queue, val) result = SendResponseString(queue, msg) - Adds NXC API macros for sending direct commands to another NXT result = RemoteMessageRead(conn, queue) result = RemoteMessageWrite(conn, queue, msg) // alias for SendRemoteString result = RemoteStartProgram(conn, filename) result = RemoteStopProgram(conn) result = RemotePlaySoundFile(conn, filename, bloop) result = RemotePlayTone(conn, frequency, duration) result = RemoteStopSound(conn) result = RemoteKeepAlive(conn) result = RemoteResetScaledValue(conn, port) result = RemoteResetMotorPosition(conn, port, brelative) result = RemoteSetInputMode(conn, port, type, mode) result = RemoteSetOutputState(conn, port, speed, mode, regmode, turnpct, runstate, tacholimit) Version 1.0.1.b24 ----------------- - Fixes a preprocessor bug in NBC and NXC that is triggered by not having a ')' at the end of a macro invocation (or anywhere following in the entire program). - Replaced the ResetMotor macros in NBC and NXC with the following macros: ResetTachoCount(p) ResetBlockTachoCount(p) ResetRotationCount(p) ResetAllTachoCounts(p) - Added NBC API file i/o macros Read(handle, n, result) ReadLn(handle, n, result) ReadBytes(handle, len, buf, result) Write(handle, n, result) WriteLn(handle, n, result) WriteString(handle, str, cnt, result) WriteLnString(handle, str, cnt, result) WriteBytes(handle, buf, cnt, result) WriteBytesEx(handle, len, buf, result) - Added NXC API file i/o macros result = Read(handle, n) result = ReadLn(handle, n) result = ReadBytes(handle, len, buf) result = Write(handle, n) result = WriteLn(handle, n) result = WriteString(handle, str, cnt) result = WriteLnString(handle, str, cnt) result = WriteBytes(handle, buf, cnt) result = WriteBytesEx(handle, len, buf) - Replaced the code underlying the ReadSensorUS (NBC) and SensorUS (NXC) API functions with a version which appears to be more reliable (and generic). - Added NBC and NXC API functions to give control over reseting rotation counters CoastEx(ports, reset) OffEx(ports, reset) OnFwdEx(ports, pwr, reset) OnRevEx(ports, pwr, reset) OnFwdRegEx(ports, pwr, regmode, reset) OnRevRegEx(ports, pwr, regmode, reset) OnFwdSyncEx(ports, pwr, turnpct, reset) OnRevSyncEx(ports, pwr, turnpct, reset) - Added NBC and NXC constants for the "Ex" motor functions RESET_NONE RESET_COUNT RESET_BLOCK_COUNT RESET_ROTATION_COUNT RESET_BLOCKANDTACHO RESET_ALL - Added NBC and NXC API functions which expose the PID parameters RotateMotorPID(ports, pwr, angle, p, i, d) RotateMotorExPID(ports, pwr, angle, turnpct, bsync, p, i, d) - Added NBC and NXC API function for clearing the screen ClearScreen() - Added support in the NXC SetOutput function for multiple sets of field/value pairs SetOutput(ports, const field1, value1, ..., const fieldN, valueN) - Added generic I2C read/write routine for NBC ReadI2CBytes(port, inbuf, count, outbuf, result) - Added generic I2C read/write routine for NXC result = I2CBytes(port, inbuf, count, outbuf) - Added NBC pseudo opcode to spawn a thread anywhere within the current thread start TaskName - Added NXC start statement (ala NQC) start TaskName; Version 1.0.1.b23 ----------------- - Adds support in NXC for nested switch statements - Adds support in NXC for array indexed math assignments (e.g., x[0] += 23;) - Adds support in NXC for using true and false in asm blocks - Adds support in NXC for local variable declarations anywhere within a function. Local variable declarations used to be limited to the beginning of a function block. Locals now honor nesting levels and go out of scope if they are declared within a block statement. "for" loops can now declare a local or use an existing variable: for (i = 10; i > 0; i--) {} // i must already be in scope for (int i = 0; i < 10; i++) {} // i has scope limited to for loop - Adds support in NXC for empty for loop (e.g., for ( ; ; ) ) for infinite loops - Adds support in NXC for scalar and string local (not global) variable initialization via expressions of any form (not just constants): int i = Random(10); string msg = NumToStr(i); - Adds support in NXC for single-dimension global variable array initialization using a syntax like array initialization in NBC: // initialize X to 20 elements all equal to 1. int X[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - Adds support in NXC for expression optimizations (enabled with -Z1) - Fixes indexing of local arrays (used to only work with globals) - Fixes a bug in the NBC sign, shl, and shr opcodes which was triggered by passing the same variable as the first and last arguments: sign x, x shl x, y, x shr x, y, x Version 1.0.1.b22 ----------------- - Adds support in NXC switch statements for strings, constant expressions, character constants, and the true and false keywords - Adds support in NBC for strings delimited by double quote characters - Fixes several motor macros in NBC/NXC so that they reset the block count before executing when it is appropriate for them to do so - Fixes NXC ForceOff macro in NXCDefs.h - Fixes the RotateMotor/RotateMotorEx macros so that programs no longer hang when the angle is set to zero - Fixes a problem in expressions which were not properly setting the zero flag register variable if in a sub-expression it had already been set - NOTE: the SENSOR_n macros mentioned below are not exactly the same as in NQC. They cannot be used to specify the sensor port. Instead you should use S1..S4 or IN_1..IN_4. Version 1.0.1.b21 ----------------- - Adds NXC API macro ResetMotor(ports) - Adds support in NXC for the ?: expression - Adds support in NXC for the switch statement - Adds the following NQC compatibility macros in NXCDefs.h: S1 S2 S3 S4 SENSOR_1 SENSOR_2 SENSOR_3 SENSOR_4 SENSOR_TYPE_NONE SENSOR_TYPE_TOUCH SENSOR_TYPE_TEMPERATURE SENSOR_TYPE_LIGHT SENSOR_TYPE_ROTATION SENSOR_TYPE_LIGHT_ACTIVE SENSOR_TYPE_LIGHT_INACTIVE SENSOR_TYPE_SOUND_DB SENSOR_TYPE_SOUND_DBA SENSOR_TYPE_CUSTOM SENSOR_TYPE_LOWSPEED SENSOR_TYPE_LOWSPEED_9V SENSOR_TYPE_HIGHSPEED SENSOR_MODE_RAW SENSOR_MODE_BOOL SENSOR_MODE_EDGE SENSOR_MODE_PULSE SENSOR_MODE_PERCENT SENSOR_MODE_CELSIUS SENSOR_MODE_FAHRENHEIT SENSOR_MODE_ROTATION SENSOR_TOUCH SENSOR_LIGHT SENSOR_ROTATION SENSOR_CELSIUS SENSOR_FAHRENHEIT SENSOR_PULSE SENSOR_EDGE SetSensor(sensor, tm) - Fixes an NXC shift right and shift left bug introduced in b20. - Fixes an NXC macro subsitution bug in the "until" macro. - Modifies GetOutput and GetInput API functions so that the port parameter no longer accepts an expression (must be a variable or constant value) Version 1.0.1.b20 ----------------- - Adds support in NXC for string comparisons (==, !=, <=, >=, <, >) - Adds support in NXC for function return types (int, bool, char, byte, short, long, unsigned versions of same, and string) - Adds support in NXC for "void" functions (synonymous with "sub"). - Adds support in NXC for comma-separated assignments in for loops. - Fixes an NXC bug in | and ^ expressions which was putting the parser into an infinite loop. - Fixes an NXC bug in the subroutine calling mechanism which is triggered by leaving off the () characters when calling the subroutine. It was causing an infinite parser loop. - Fixes an NXC bug in relational expressions which were not setting the main register to a boolean value. Version 1.0.1.b19 ----------------- - Fixes a command-line bug which could cause NXC source code to be overwritten with the generated NBC code. This bug is triggered in b18 and b17 if you use BricxCC to download an NXC program and you exit BricxCC without saving the contents of the editor window to its underlying source file (which has had its contents replaced with NBC assembler code). Version 1.0.1.b18 ----------------- - Fixes a bug in the GraphicOut macro in NXTDefs.h (for NBC and NXC) - Fixes a bug in the ArrayInit macro in NXCDefs.h - swapped parameter order as well ArrayInit(a, val, cnt) - Removes a few compiler hints for a cleaner compile - Adds support for multi-line macro invocation (with support for embedded comments and arbitrary whitespace) - Moves ## handling into preprocessor so that macro expansion more closely matches C - Fixes NXC preprocessor bug related to ## handling (it was causing an infinite loop) - Adds support for variable initialization via constant expression. - Improves error message line number handling (it's still not perfect but it is much better) - Adds mutex optimization (automatically removes acquire/release and mutex declarations if the application is single-threaded) Version 1.0.1.b17 ----------------- - Fixes a problem in the SetSoundState macro in NXTDefs.h and NXCDefs.h. - Fixes a few local variable and parameter decoration problems. - Fixes a missing file in the source distribution. Version 1.0.1.b16 ----------------- - Refactors the NXC API to use macros for many of the API functions (See NXCDefs.h) Macros in NXC may use an "asm" block with tokens for temporary variables of different types and return values of different types. - Fixes another bug in NBC with nested preprocessor macro function calls. (e.g., until(ButtonPressed(BTN1, true)) ; ) The fix in b15 did not completely fix the problem (it only handled single argument nested macros - or, more precisely, nested macros without any whitespace in their argument list). - Fixes a problem with BatteryLevel and FreeMemory in the NXC API where I had renamed the underlying NBC macros and failed to change the code generator in NXC. - Adds the missing '%' (modulo) operator for expressions in NXC. - Renames NXC API functions ReadSensor(p) and ReadSensorUS(p) as Sensor(p) and SensorUS(p) respectively - Renames NXC API functions GetTick() as CurrentTick() and GetFirstTick() as FirstTick(). - Renames NXC API function SetSensorUltrasonic(p) as SetSensorLowspeed(p). - Adds initial support for NXC array types. Adding [] pairs after the variable name in a variable declaration defines the variable as an array of the specified type. e.g., byte x[]; // x is an array of byte Array initialization is not yet supported. - Added NXC support for array/string subscripting (e.g., buf[0] = 23; msg[4] = "fred"; - Added NXC support for local variables and subroutine parameters (no return values yet) Local variables must be defined prior to any other statements in a task or subroutine. - Added many NXC API macros to NXCDefs.h: ByteArrayToStr(a, s) StrToByteArray(s, a) ArrayLen(a) ArrayInit(a, cnt, val) GetLSInputBuffer(p, offset, cnt, data) GetLSOutputBuffer(p, offset, cnt, data) GetDisplayNormal(x, line, cnt, data) GetDisplayPopup(x, line, cnt, data) GetBTInputBuffer(offset, cnt, data) GetBTOutputBuffer(offset, cnt, data) GetHSInputBuffer(offset, cnt, data) GetHSOutputBuffer(offset, cnt, data) GetUSBInputBuffer(offset, cnt, data) GetUSBOutputBuffer(offset, cnt, data) GetUSBPollBuffer(offset, cnt, data) BTDeviceName(p) BTConnectionName(p) BTConnectionPinCode(p) BrickDataName() GetBTDeviceAddress(p, data) GetBTConnectionAddress(p, data) GetBrickDataAddress(data) SoundFrequency() SoundDuration() SoundSampleRate() SoundMode() SoundVolume() ButtonPressCount(b) ButtonLongPressCount(b) ButtonShortReleaseCount(b) ButtonLongReleaseCount(b) ButtonReleaseCount(b) ButtonState(b) CommandFlags() UIState() UIButton() VMRunState() BatteryState() BluetoothState() UsbState() SleepTimeout() SleepTimer() RechargeableBattery() Volume() OnBrickProgramPointer() CustomSensorZeroOffset(p) CustomSensorPercentFullScale(p) CustomSensorActiveStatus(p) SensorBoolean(p) SensorDigiPinsDirection(p) SensorDigiPinsStatus(p) SensorDigiPinsOutputLevel(p) MotorPwnFreq() LSInputBufferInPtr(p) LSInputBufferOutPtr(p) LSInputBufferBytesToRx(p) LSOutputBufferInPtr(p) LSOutputBufferOutPtr(p) LSOutputBufferBytesToRx(p) LSMode(p) LSChannelState(p) LSErrorType(p) LSState() LSSpeed() DisplayEraseMask() DisplayUpdateMask() DisplayDisplay() DisplayFlags() DisplayTextLinesCenterFlags() BTDeviceClass(p) BTDeviceStatus(p) BTConnectionClass(p) BTConnectionHandleNum(p) BTConnectionStreamStatus(p) BTConnectionLinkQuality(p) BrickDataBluecoreVersion() BrickDataBtStateStatus() BrickDataBtHardwareStatus() BrickDataTimeoutValue() BTInputBufferInPtr() BTInputBufferOutPtr() BTOutputBufferInPtr() BTOutputBufferOutPtr() HSInputBufferInPtr() HSInputBufferOutPtr() HSOutputBufferInPtr() HSOutputBufferOutPtr() USBInputBufferInPtr() USBInputBufferOutPtr() USBOutputBufferInPtr() USBOutputBufferOutPtr() USBPollBufferInPtr() USBPollBufferOutPtr() BTDeviceCount() BTDeviceNameCount() HSFlags() HSSpeed() HSState() USBState() SetSoundFrequency(n) SetSoundDuration(n) SetSoundSampleRate(n) SetSoundFlags(n) SetSoundState(n) SetSoundMode(n) SetSoundVolume(n) SetButtonPressCount(b, n) SetButtonLongPressCount(b, n) SetButtonShortReleaseCount(b, n) SetButtonLongReleaseCount(b, n) SetButtonReleaseCount(b, n) SetButtonState(b, n) SetCommandFlags(n) SetUIState(n) SetUIButton(n) SetVMRunState(n) SetBatteryState(n) SetBluetoothState(n) SetUsbState(n) SetSleepTimeout(n) SetSleepTimer(n) SetVolume(n) SetOnBrickProgramPointer(n) ForceOff(n) SetInCustomZeroOffset(p, n) SetInSensorBoolean(p, n) SetInDigiPinsDirection(p, n) SetInDigiPinsStatus(p, n) SetInDigiPinsOutputLevel(p, n) SetInCustomPercentFullScale(p, n) SetInCustomActiveStatus(p, n) SetOutPwnFreq(n) SetLSInputBuffer(p, offset, cnt, data) SetLSInputBufferInPtr(p, n) SetLSInputBufferOutPtr(p, n) SetLSInputBufferBytesToRx(p, n) SetLSOutputBuffer(p, offset, cnt, data) SetLSOutputBufferInPtr(p, n) SetLSOutputBufferOutPtr(p, n) SetLSOutputBufferBytesToRx(p, n) SetLSMode(p, n) SetLSChannelState(p, n) SetLSErrorType(p, n) SetLSState(n) SetLSSpeed(n) SetDisplayEraseMask(n) SetDisplayUpdateMask(n) SetDisplayDisplay(n) SetDisplayFlags(n) SetDisplayTextLinesCenterFlags(n) SetDisplayNormal(x, line, cnt, data) SetDisplayPopup(x, line, cnt, data) SetBTDeviceName(p, str) SetBTDeviceAddress(p, addr) SetBTConnectionName(p, str) SetBTConnectionPinCode(p, code) SetBTConnectionAddress(p, addr) SetBrickDataName(str) SetBrickDataAddress(p, addr) SetBTDeviceClass(p, n) SetBTDeviceStatus(p, n) SetBTConnectionClass(p, n) SetBTConnectionHandleNum(p, n) SetBTConnectionStreamStatus(p, n) SetBTConnectionLinkQuality(p, n) SetBrickDataBluecoreVersion(n) SetBrickDataBtStateStatus(n) SetBrickDataBtHardwareStatus(n) SetBrickDataTimeoutValue(n) SetBTInputBuffer(offset, cnt, data) SetBTInputBufferInPtr(n) SetBTInputBufferOutPtr(n) SetBTOutputBuffer(offset, cnt, data) SetBTOutputBufferInPtr(n) SetBTOutputBufferOutPtr(n) SetHSInputBuffer(offset, cnt, data) SetHSInputBufferInPtr(n) SetHSInputBufferOutPtr(n) SetHSOutputBuffer(offset, cnt, data) SetHSOutputBufferInPtr(n) SetHSOutputBufferOutPtr(n) SetUSBInputBuffer(offset, cnt, data) SetUSBInputBufferInPtr(n) SetUSBInputBufferOutPtr(n) SetUSBOutputBuffer(offset, cnt, data) SetUSBOutputBufferInPtr(n) SetUSBOutputBufferOutPtr(n) SetUSBPollBuffer(offset, cnt, data) SetUSBPollBufferInPtr(n) SetUSBPollBufferOutPtr(n) SetBTDeviceCount(n) SetBTDeviceNameCount(n) SetHSFlags(n) SetHSSpeed(n) SetHSState(n) SetUSBState(n) CreateFile(fname, fsize, handle) OpenFileAppend(fname, fsize, handle) OpenFileRead(fname, fsize, handle) CloseFile(handle) ResolveHandle(fname, handle, writeable) RenameFile(oldname, newname) DeleteFile(fname) SendMessage(queue, msg) ReceiveMessage(queue, clear, msg) LowspeedStatus(port, bready) LowspeedWrite(port, retlen, buffer) LowspeedRead(port, buflen, buffer) BluetoothStatus(conn, result) BluetoothWrite(conn, buffer) Version 1.0.1.b15 ----------------- - Adds to NXC new API functions: ExitTo(task): Exit the current task immediately and start the specified task Stop(bStop): Stop the program if the boolean expression evaluates to true SetInput(port, field, value): Set an input field to the specified value SetOutput(ports, field, value): Set an output field to the specified value PowerDown(): Power down the brick immediately RebootInFirmwareMode(): Reboot the brick in firmware mode immediately BatteryLevel(): Read the current battery level (in millivolts) FreeMemory(): Read the free flash memory (in bytes) NumToStr(val): Convert the specified numeric value to a string StrCat(str1, str2, ..., strN): Concatenate the args into a single string SubStr(str, idx, len): Extract the specified portion of a string Flatten(val): Convert value into a string based on the size of scalar datatype StrReplace(str, idx, strnew): Replace characters in 'str' with those in 'strnew' StrToNum(str): Convert string into a number StrLen(str): Return the length of the string argument StrIndex(str, idx): Return the ASCII value of str[idx] - Adds to NXC the "until" loop construct and the goto label construct - Fixes a NXC parser bug in if (condition) { } else { } construct - Adds support for && and || operators in boolean expressions - Adds support for <<, >>, <<=, and >>= operators in numeric expressions - Adds to NXC new API macros: SensorType(p) SensorMode(p) SensorRaw(p) SensorNormalized(p) SensorScaled(p) SensorInvalid(p) MotorMode(p) MotorPower(p) MotorActualSpeed(p) MotorTachoCount(p) // this replaced TachometerCount(p) MotorTachoLimit(p) // this replaced TachometerLimit(p) MotorRunState(p) MotorTurnRatio(p) MotorRegulation(p) MotorOverload(p) MotorRegPValue(p) MotorRegIValue(p) MotorRegDValue(p) MotorBlockTachoCount(p) MotorRotationCount(p) - Adds to NBC many new API macros: PointOut(x, y, clear?) LineOut(x1, y1, x2, y2, clear?) RectOut(x, y, width, height, clear?) CircleOut(x, y, radius, clear?) GraphicOut(x, y, filename, varArray, clear?) PlayToneEx(frequency, duration, volume, loop?) PlayFileEx(filename, volume, loop?) GetSoundState(state, flags) SetSoundState(state, flags, result) SignedRandom(value) GetFirstTick(value) SetIOMapBytes(modName, offset, len, arrIn) SetIOMapValue(modName, offset, n) SetUIModuleValue(offset, n) SetIOCtrlModuleValue(offset, n) SetCommandModuleValue(offset, n) SetSoundModuleValue(offset, n) SetButtonModuleValue(offset, n) SetInputModuleValue(offset, n) SetOutputModuleValue(offset, n) SetLowSpeedModuleValue(offset, n) SetDisplayModuleValue(offset, n) SetCommModuleValue(offset, n) RebootInFirmwareMode PowerDown SetSoundFrequency(n) SetSoundDuration(n) SetSoundSampleRate(n) SetSoundFlags(n) SetSoundState(n) SetSoundMode(n) SetSoundVolume(n) SetButtonPressCount(b, n) SetButtonLongPressCount(b, n) SetButtonShortReleaseCount(b, n) SetButtonLongReleaseCount(b, n) SetButtonReleaseCount(b, n) SetButtonState(b, n) SetCommandFlags(n) SetUIState(n) SetUIButton(n) SetVMRunState(n) SetBatteryState(n) SetBluetoothState(n) SetUsbState(n) SetSleepTimeout(n) SetSleepTimer(n) SetVolume(level) SetOnBrickProgramPointer(idx) ForceOff(n) SetInCustomZeroOffset(p, n) SetInSensorBoolean(p, n) SetInDigiPinsDirection(p, n) SetInDigiPinsStatus(p, n) SetInDigiPinsOutputLevel(p, n) SetInCustomPercentFullScale(p, n) SetInCustomActiveStatus(p, n) SetOutPwnFreq(n) SetLSInputBuffer(p, offset, cnt, data) SetLSInputBufferInPtr(p, n) SetLSInputBufferOutPtr(p, n) setLSInputBufferBytesToRx(p, n) SetLSOutputBuffer(p, offset, cnt, data) SetLSOutputBufferInPtr(p, n) SetLSOutputBufferOutPtr(p, n) SetLSOutputBufferBytesToRx(p, n) SetLSMode(p, v) SetLSChannelState(p, v) SetLSErrorType(p, v) SetLSState(v) SetLSSpeed(v) SetDisplayEraseMask(n) SetDisplayUpdateMask(n) SetDisplayDisplay(n) SetDisplayFlags(n) SetDisplayTextLinesCenterFlags(n) setDisplayNormal(x, line, cnt, data) SetDisplayPopup(x, line, cnt, data) SetBTDeviceName(p, str) SetBTDeviceClass(p, v) SetBTDeviceAddress(p, addr) SetBTDeviceStatus(p, v) SetBTConnectionName(p, str) SetBTConnectionClass(p, v) SetBTConnectionPinCode(p, str) SetBTConnectionAddress(p, addr) SetBTConnectionHandleNum(p, v) SetBTConnectionStreamStatus(p, v) SetBTConnectionLinkQuality(p, v) SetBrickDataName(str) SetBrickDataBluecoreVersion(v) SetBrickDataAddress(addr) SetBrickDataBtStateStatus(v) SetBrickDataBtHardwareStatus(v) SetBrickDataTimeoutValue(v) SetBTInputBuffer(data) SetBTInputBufferInPtr(n) SetBTInputBufferOutPtr(n) SetBTOutputBuffer(data) SetBTOutputBufferInPtr(n) SetBTOutputBufferOutPtr(n) SetHSInputBuffer(data) SetHSInputBufferInPtr(n) SetHSInputBufferOutPtr(n) SetHSOutputBuffer(data) SetHSOutputBufferInPtr(n) SetHSOutputBufferOutPtr(n) SetUSBInputBuffer(data) SetUSBInputBufferInPtr(n) SetUSBInputBufferOutPtr(n) SetUSBOutputBuffer(data) SetUSBOutputBufferInPtr(n) SetUSBOutputBufferOutPtr(n) SetUSBPollBuffer(data) SetUSBPollBufferInPtr(n) SetUSBPollBufferOutPtr(n) SetBTDeviceCount(n) SetBTDeviceNameCount(n) SetHSFlags(n) SetHSSpeed(n) SetHSState(n) SetUSBState(n) GetIOMapBytes(modName, offset, len, arrOut) GetIOMapValue(modName, offset, n) GetUIModuleValue(offset, n) GetLoaderModuleValue(offset, n) GetCommandModuleValue(offset, n) GetSoundModuleValue(offset, n) GetButtonModuleValue(offset, n) GetInputModuleValue(offset, n) GetOutputModuleValue(offset, n) GetLowSpeedModuleValue(offset, n) GetDisplayModuleValue(offset, n) GetCommModuleValue(offset, n) GetFreeMemory(value) GetSoundFrequency(value) GetSoundDuration(value) GetSoundSampleRate(value) GetSoundFlags(value) GetSoundState(value) GetSoundMode(value) GetSoundVolume(value) GetButtonPressCount(b, value) GetButtonLongPressCount(b, value) GetButtonShortReleaseCount(b, value) GetButtonLongReleaseCount(b, value) GetButtonReleaseCount(b, value) GetButtonState(b, value) GetBatteryLevel(value) GetCommandFlags(value) GetUIState(value) GetUIButton(value) GetVMRunState(value) GetBatteryState(value) GetBluetoothState(value) GetUsbState(value) GetSleepTimeout(value) GetSleepTimer(value) GetRechargeableBattery(value) GetVolume(value) GetOnBrickProgramPointer(value) GetInCustomZeroOffset(p, v) GetInSensorBoolean(p, v) GetInDigiPinsDirection(p, v) GetInDigiPinsStatus(p, v) GetInDigiPinsOutputLevel(p, v) GetInCustomPercentFullScale(p, v) GetInCustomActiveStatus(p, v) GetOutPwnFreq(v) GetLSInputBuffer(p, offset, cnt, data) GetLSInputBufferInPtr(p, n) GetLSInputBufferOutPtr(p, n) GetLSInputBufferBytesToRx(p, n) GetLSOutputBuffer(p, offset, cnt, data) GetLSOutputBufferInPtr(p, n) GetLSOutputBufferOutPtr(p, n) GetLSOutputBufferBytesToRx(p, n) GetLSMode(p, v) GetLSChannelState(p, v) GetLSErrorType(p, v) GetLSState(v) GetLSSpeed(v) GetDisplayEraseMask(n) GetDisplayUpdateMask(n) GetDisplayDisplay(n) GetDisplayFlags(n) GetDisplayTextLinesCenterFlags(n) GetDisplayNormal(x, line, cnt, data) GetDisplayPopup(x, line, cnt, data) GetBTDeviceName(p, str) GetBTDeviceClass(p, v) GetBTDeviceAddress(p, addr) GetBTDeviceStatus(p, v) GetBTConnectionName(p, str) GetBTConnectionClass(p, v) GetBTConnectionPinCode(p, str) GetBTConnectionAddress(p, addr) GetBTConnectionHandleNum(p, v) GetBTConnectionStreamStatus(p, v) GetBTConnectionLinkQuality(p, v) GetBrickDataName(str) GetBrickDataBluecoreVersion(v) GetBrickDataAddress(addr) GetBrickDataBtStateStatus(v) GetBrickDataBtHardwareStatus(v) GetBrickDataTimeoutValue(v) GetBTInputBuffer(data) GetBTInputBufferInPtr(n) GetBTInputBufferOutPtr(n) GetBTOutputBuffer(data) GetBTOutputBufferInPtr(n) GetBTOutputBufferOutPtr(n) GetHSInputBuffer(data) GetHSInputBufferInPtr(n) GetHSInputBufferOutPtr(n) GetHSOutputBuffer(data) GetHSOutputBufferInPtr(n) GetHSOutputBufferOutPtr(n) GetUSBInputBuffer(data) GetUSBInputBufferInPtr(n) GetUSBInputBufferOutPtr(n) GetUSBOutputBuffer(data) GetUSBOutputBufferInPtr(n) GetUSBOutputBufferOutPtr(n) GetUSBPollBuffer(data) GetUSBPollBufferInPtr(n) GetUSBPollBufferOutPtr(n) GetBTDeviceCount(n) GetBTDeviceNameCount(n) GetHSFlags(n) GetHSSpeed(n) GetHSState(n) GetUSBState(n) CreateFile(fname, fsize, handle, result) OpenFileAppend(fname, fsize, handle, result) OpenFileRead(fname, fsize, handle, result) CloseFile(handle, result) ResolveHandle(fname, handle, writeable, result) RenameFile(oldname, newname, result) DeleteFile(fname, result) SendMessage(queue, msg, result) ReceiveMessage(queue, clear, msg, result) LowspeedStatus(port, bready, result) LowspeedWrite(port, retlen, buffer, result) LowspeedRead(port, buflen, buffer, result) BluetoothStatus(conn, result) BluetoothWrite(conn, buffer, result) - Adds to NBC new opcodes: strindex dest, strsrc, idx: same as index but can take a constant string strreplace strDest, strSrc, idx, strNew: same as replace but can take constant strings strlen dest, strSource: store the length of the input string into dest shr result, value, n: shift right value by 'n' bits and store in result shl result, value, n: shift left value by 'n' bits and store in result - Adds to NBC a special compile-time operator: sizeof(variable): returns the element size of the specified variable - Adds to NBC a special compile-time opcode: compchk comparecode, const1, const2: returns a compiler error if the specified expression is not true. For example: compchk EQ, sizeof(arg3), 1 - Adds '~' operator to the NBC compile-time expression evaluator (bitwise not) - Fixes a problem in NBC (and NXC) with the RotateMotor API function - Fixes a bug in NBC with nested preprocessor macro function calls (e.g., FooBar(MyMacro(x, y), 2, 4) - Fixes a bug in NBC with trailing spaces on #define values Version 1.0.1.b14 ----------------- - Adds string variables with initialization, assignment, concatenation (including +=). - Moves ReadSensor, ReadSensorUS, TextOut, NumOut, PlatTone, PlayFile, and ResetSleepTimer to function status (can be on the RHS of an assignment). - Cls is renamed as ResetScreen. Write is removed (use TextOut and NumOut instead). - PlayTone is replaced with PlayToneEx(freq, dur, vol, loop). - PlayFile is replaced with PlayFileEx(fname, vol, loop). - Renames InputFieldValue as GetInput and OutputFieldValue as GetOutput. - Reorganizes includes so that NXCDefs.h includes NBCCommon.h and NXTDefs.h includes NBCCommon.h. NXCDefs.h now defines PlayTone and PlayFile API macros. It also defines TachometerCount(port) and TachometerLimit(port) API macros (more to come). - Adds SoundState, SoundFlags, StopSound, ButtonPressed, ButtonCount, ReadButtonEx, GetFirstTick, PointOut, LineOut, CircleOut, RectOut, and GraphicOut functions. - Fixes multi-threading issues with variables used as stack and register variables. Version 1.0.1.b13 ----------------- This beta release improves support for the Not eXactly C (NXC) programming language. NXC now supports do-while and repeat loops as found in NQC. These constructs are in addition to the already supported if/else, while, and for loops. This release also enables using either single statement or block statements with all the programming constructs (the previous beta required block statements). There is also support for an "asm" block which outputs NBC code directly to the backend. This release also expands the set of API functions to include TextOut, NumOut, OnFwdReg, OnRevReg, OnFwdSync, OnRevSync, RotateMotor, RotateMotorEx, SetSensorType, SetSensorMode, ReadSensor, ReadSensorUS, ClearSensor, SetSensorTouch, SetSensorLight, SetSensorSound, SetSensorUltrasonic, ResetSensor, PlayTone, PlayFile, Acquire, Release, Precedes, Follows, ResetSleepTimer, abs, sign, Random, InputFieldValue, OutputFieldValue, IOMA, and GetTick. The last seven of these return a value and can be used on the RHS of assignment statements. The InputFieldValue and OutputFieldValue functions can be used in simple preprocessor macros (which will be formalized in a future beta NXC API header) for accessing any input or output value (such as TachoCount, SensorValue, SensorValueRaw, ActualSpeed, etc...) Variables may be initialized at the declaration point. Declarations may exist anywhere in the source outside of tasks and subroutines. Previously all declarations had to be prior to the first task or subroutine. Future releases will enable local variable declarations but they are not currently supported. Version 1.0.1.b12 ----------------- This beta release introduces support for two new languages related to NBC. The NPG language is a very simple 5 step declarative language for writing RPG (NXT Program) executables. NPG programs simple list the 5 steps with compiler support for C++-style comments interspersed. Unlike the built-in NXT menu system mechanism for writing NXT Programs which require alternating move and wait commands, programs written using NPG can sequence the 5 commands in any order except that the EndStop and EndLoop commands can only occur as the last step. See test.npg for a small sample. These programs require the RPGReader.sys program on the NXT. This executable is 14kb in size but a replacement version which nearly identical functionality will soon be available on the NBC site which is only ~2.5kb. NBC also now supports a very early version of the NXC programming language. This language is a lot like NQC syntax-wise. It is still in its infancy so it is subject to substantial change and improvement. The NBC compiler converts the NXC code to NBC code and then compiles it as it would any other NBC program. See test.nxc for a basic example. The NXTDefs.h header file has been split into NXCDefs.h and NXTDefs.h. NBC programs should still #include "NXTDefs.h" but NXC programs should #include "NXCDefs.h". This release also fixes a problem with unix-style line endings which made it so that multiline macros written on non-Windows platforms would not work correctly. Version 1.0.1.b11 ----------------- This beta release has a number of additional macros in NXTDefs.h for simplifying several aspects of programming the NXT. Version 1.0.1.b10 ---------------- This beta release implements multi-dimensional array support. It has additional macros in NXTDefs.h for motor and sensor control. It moves all forms of optimization under the control of a command-line switch (-Z, -Z1, or -Z2). The optimizations that were always executed in beta 8 are now only executed if you set the optimization level to at least level 1. -Z and -Z2 both set the optimization level to 2. Level 2 optimizations replace several different patterns of code with simplified equivalents. NBC now has special tokens that can be used in macros or elsewhere for useful purposes. The tokens are __FILE__, __LINE__, __VER__, __THREADNAME__, __I__, __J__, __ResetI__, __ResetJ__, __IncI__, __IncJ__, __DecI__, and __DecJ__. The compiler will also replace ## wherever it exists in the sourcecode with nothing (even within strings). These tokens make it possible to define preprocessor macros which can be used repeatedly in the same thread or in multiple concurrent threads without causing threading problems or producing duplicate label names. The values of __I__ and __J__ are automatically reset to zero at the start of each new thread or subroutine. Version 1.0.1.b8 ---------------- This beta release adds call, release, abs, sub, and waitv opcodes. It also makes the preprocessor operate recursively on both parameterized and non-parameterized macros. It fixes a typo in the NXTDefs.h header file and adds some standard preprocessor macros for motor control. The compiler has a major new optimization feature which removes unused variables and threads/subroutines from the compiled executable. In b7 I accidentally broke the "wait" opcode support that was added in b6 but that support has been restored in b8. Version 1.0.1.b7 ---------------- This beta release includes a new symbol table generation feature (-Y) along with a significantly faster preprocessor. A bug in processing parameterized macros which had whitespace following the last parameter was also fixed. Version 1.0.1.b6 ---------------- Fixed a bug in the binary file download code in the Win32 version. Added support for generating thread-specific wait subroutines when the compiler sees a thread try to use the wait opcode (since that opcode was not included in the standard NXT firmware). Next Byte Codes Compiler version 1.0.1.b6 (1.0.1.6, built Aug 18 2006 17:13:22) Copyright (c) 2006, John Hansen Version 1.0.1.b5 ---------------- Added support for parameterized macro functions. Added support for multi-line macros. Fixed some preprocessor bugs related to unmatched #ifdef #endif pairs and #include statements with unsupported format (must be #include "filename.extension"). Updated NXTDefs.h with additional IOMap constants. Released the Free Pascal-compliant sourcecode as part of the new BricxCC 3.3.7.15 source code release. Next Byte Codes Compiler version 1.0.1.b5 (1.0.1.5, built Aug 16 2006 17:08:56) Copyright (c) 2006, John Hansen version 0.1.4.b4 ---------------- Added a built-in preprocessor. Fixed argument checking for the 3 opcodes which take a variable number of arguments. Added a Mac OSX version of the compiler. Next Byte Codes Compiler version 0.1.4.b4 (0.1.4.1, built Jun 15 2006 13:38:46) Copyright (c) 2006, John Hansen version 0.1.3.b3 ---------------- Fixed assumptions regarding bluetooth communication and port name aliases. To use Bluetooth you must add the -BT switch to the command line. Next Byte Codes Compiler version 0.1.3.b3 (0.1.3.18, built Jun 06 2006 08:40:14) Copyright (c) 2006, John Hansen Syntax: nbc [options] filename [options] -T=: target must be NXT -S=: specify port name (COMn or usb), resource name, or alias -BT: use bluetooth -d: download program -b: treat input file as a binary file (don't compile it) -q: no sound upon download completion -x: decompile program -O= : specify output file -E= : write compiler errors to -I=: search for include files -L= : generate code listing to -help : display command line options version 0.1.3.b2 ---------------- Added support for initializing arrays of structs. Fixed a few minor bugs. Downloading programs now depends on the LEGO Mindstorms NXT Driver (Fantom). Next Byte Codes Compiler version 0.1.3.b2 (0.1.3.17, built May 17 2006 16:53:18) Copyright (c) 2006, John Hansen version 0.1.3.b1 ---------------- First official beta of NBC. NXT Bytecode Compiler version 0.1.3.b1 (0.1.3.14, built May 02 2006 13:14:50) Copyright 2006, John Hansen Syntax: nbc [options] filename [options] -T=: target must be NXT -S=: specify port (COMn or usb) -d: download program -b: treat input file as a binary file (don't compile it) -x: decompile program -q: no sound upon download completion -O= : specify output file -E= : write compiler errors to -I=: search for include files -L= : generate code listing to -help : display command line options mwGenericLex.pas0000644000175000017500000006250111537752674013561 0ustar slavkoslavko{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/NPL/NPL-1_1Final.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: mwGenericLex.pas, released April, 2001. The Initial Developer of the Original Code is Martin Waldenburg (Martin.Waldenburg@T-Online.de). Portions created by Martin Waldenburg are Copyright (C) 2001 Martin Waldenburg. All Rights Reserved. Contributor(s): _____________________________________. Last Modified: mm/dd/yyyy Current Version: 0.9 Notes: This program is a fast generic scriptable lexical analyser. Modification history: Known Issues: -----------------------------------------------------------------------------} {$A+,B-,C-,D-,E-,I+,J-,O+,Q-,R-,S-,V-} unit mwGenericLex; {$IFDEF FPC} {$MODE DELPHI} {$ENDIF} interface uses Classes; const piAtEnd = High(Word); piZero = High(Word) - 1; piUnknown = High(Word) - 2; piSymbol = 0; piSpace = 1; piLineEnd = 2; piInnerLineEnd = 3; piIdent = 4; piKeyWord = 5; piString = 6; piComment = 7; piNumber = 8; piAssembler = 9; piBadString = 10; piDirective = 11; piChar = 12; piBadChar = 13; type TAny = class; TmwGenLex = class; TmwLexInitProc = procedure(Lex: TmwGenLex); TmwLexInitMethod = procedure(Lex: TmwGenLex) of object; TmwCharClass = set of Char; PmwChars = ^TmwChars; TmwChars = record Chars: TmwCharClass; end; TAnyKind = ( pkAny, pkChar, pkCharClass, pkInnerLineEnd, pkKey, pkLineEnd, pkTillChars, pkTillKey ); TAnyStatus = ( psMultiLine, psNegative, psProcessingNeeded, psRegress ); TAnyStorage = packed record Count: Byte; Kind: TAnyKind; Status: set of TAnyStatus; Min: Byte; Id: Word; ExId: Word; Max: Word; end; PmwOptionsList = ^TmwOptionsList; TmwOptionsList = array[0..0] of TAny; TAny = class(TPersistent) private fOptionsList: PmwOptionsList; fToRegress: TAny; FKey: string; FFollow: TAny; function GetNodes(Index: Byte): TAny; function GetMultiLine: Boolean; function GetNegative: Boolean; function GetProcessingNeeded: Boolean; procedure SetMultiLine(const Value: Boolean); procedure SetNegative(const Value: Boolean); procedure SetProcessingNeeded(const Value: Boolean); procedure SetKey(const Value: string); procedure SetCharClass(const Value: TmwCharClass); function GetCharClass: TmwCharClass; function GetRegress: Boolean; procedure SetRegress(const Value: Boolean); protected Storage: TAnyStorage; ToRestore: TAny; public constructor Create(AParent: TAny); virtual; destructor Destroy; override; function AddOption(const Value: TAny): Integer; function IndexOf(const Any: TAny): Integer; property CharClass: TmwCharClass read GetCharClass write SetCharClass; property Count: Byte read Storage.Count; property Options[Index: Byte]: TAny read GetNodes; default; property ToRegress: TAny read fToRegress write FToRegress; published property ExId: Word read Storage.ExId write Storage.ExId; property Follow: TAny read FFollow write FFollow; property Id: Word read Storage.Id write Storage.Id; property Max: Word read Storage.Max write Storage.Max; property Min: Byte read Storage.Min write Storage.Min; property Key: string read FKey write SetKey; property Kind: TAnyKind read Storage.Kind write Storage.Kind; property MultiLine: Boolean read GetMultiLine write SetMultiLine; property Negative: Boolean read GetNegative write SetNegative; property ProcessingNeeded: Boolean read GetProcessingNeeded write SetProcessingNeeded; property Regress: Boolean read GetRegress write SetRegress; end; TLineEnd = class(TAny) public constructor Create(AParent: TAny); override; end; TAlpha = class(TAny) public constructor Create(AParent: TAny); override; end; TAlphaNumeric = class(TAny) public constructor Create(AParent: TAny); override; end; (* TCharAlpha = class(TAny) public constructor Create(AParent: TAny); override; end; TCharAlphaNumeric = class(TAny) public constructor Create(AParent: TAny); override; end; TCharLower = class(TAny) public constructor Create(AParent: TAny); override; end; TCharUpper = class(TAny) public constructor Create(AParent: TAny); override; end; *) TIdentifier = class(TAlpha) public constructor Create(AParent: TAny); override; end; TCRLF = class(TAny) public constructor Create(AParent: TAny); override; end; TLF = class(TAny) public constructor Create(AParent: TAny); override; end; TNotZero = class(TAny) public constructor Create(AParent: TAny); override; end; TNumeric = class(TAny) public constructor Create(AParent: TAny); override; end; TTill = class(TAny) public constructor Create(AParent: TAny); override; end; TTillChars = class(TAny) public constructor Create(AParent: TAny); override; end; TTillLineEnd = class(TAny) public constructor Create(AParent: TAny); override; end; TZero = class(TAny) public constructor Create(AParent: TAny); override; end; TmwGenLex = class(TPersistent) private FChain: TList; FCurrent: TAny; FSensitive: Boolean; FInitMethod: TmwLexInitMethod; FInitProc: TmwLexInitProc; FRange: TAny; FOrigin: PChar; FProcessingNeeded: Boolean; function ApplyAny: Boolean; function ApplyChar: Boolean; function ApplyCharClass: Boolean; function ApplyInnerLineEnd: Boolean; function ApplyKey: Boolean; function ApplyLineEnd: Boolean; function ApplyTillChars: Boolean; function ApplyTillKey: Boolean; function GetToken: string; procedure SetInitMethod(const Value: TmwLexInitMethod); procedure SetInitProc(const Value: TmwLexInitProc); procedure SetInput(const Value: string); procedure SetOrigin(const Value: PChar); function GetRunPos: Integer; procedure SetRunPos(const Value: Integer); function GetEndPos: Integer; procedure SetEndPos(const Value: Integer); function SubNext: Boolean; function GetLinePos: Integer; protected fLineCount : Longint; FExId: Word; FId: Word; Run: PChar; Start: PChar; TheEnd: PChar; InnerLineEnd: TAny; MainSelector: array[#0..#255] of TAny; Selector: array[Low(TAnyKind)..High(TAnyKind)] of function: Boolean of object; procedure AddToMainSelector(Pattern: TAny); procedure Clear; function Execute: Boolean; procedure InitMainSelector; procedure InitSelector; property Current: TAny read FCurrent write FCurrent; property Chain: TList read FChain write FChain; public constructor Create; destructor Destroy; override; procedure Add(Pattern: TAny); function AtEnd: Boolean; procedure Next; procedure SetStartData(Ptr: Pointer; aLen: Integer); property EndPos: Integer read GetEndPos write SetEndPos; property Id: Word read FId; property ExId: Word read FExId; property Input: string write SetInput; property Origin: PChar read FOrigin write SetOrigin; property ProcessingNeeded: Boolean read FProcessingNeeded; property Range: TAny read FRange write FRange; property RunPos: Integer read GetRunPos write SetRunPos; property LinePos : Integer read GetLinePos; property Sensitive: Boolean read FSensitive write FSensitive; property Token: string read GetToken; property InitProc: TmwLexInitProc read FInitProc write SetInitProc; property InitMethod: TmwLexInitMethod read FInitMethod write SetInitMethod; end; implementation uses SysUtils; var CompTable: array[#0..#255] of Char; procedure InitTables; var I: Char; begin for I := #0 to #255 do CompTable[I] := AnsiUpperCase(I)[1]; end; { TAny } function TAny.AddOption(const Value: TAny): Integer; begin Result := -1; if Assigned(Value) then begin Result := Storage.Count; inc(Storage.Count); ReallocMem(fOptionsList, Storage.Count * SizeOf(TAny)); fOptionsList^[Result] := Value; end; end; constructor TAny.Create(AParent: TAny); begin inherited Create; if Assigned(AParent) then AParent.Follow := Self; end; destructor TAny.Destroy; var I: Integer; begin if Assigned(Follow) then Follow.Free; for I := 0 to Storage.Count - 1 do fOptionsList^[I].Free; ReallocMem(fOptionsList, 0); inherited Destroy; end; function GetIt(const C): TmwCharClass; begin Result := TmwCharClass(C); end; function TAny.GetCharClass: TmwCharClass; begin Result := PmwChars(FKey).Chars; end; function TAny.GetMultiLine: Boolean; begin Result := psMultiLine in Storage.Status; end; function TAny.GetNegative: Boolean; begin Result := psNegative in Storage.Status; end; function TAny.GetNodes(Index: Byte): TAny; begin Result := nil; if Index < Storage.Count then Result := fOptionsList^[Index]; end; function TAny.GetProcessingNeeded: Boolean; begin Result := psProcessingNeeded in Storage.Status; end; function TAny.GetRegress: Boolean; begin Result := psRegress in Storage.Status; end; function TAny.IndexOf(const Any: TAny): Integer; var I: Integer; begin Result := -1; for I := 0 to Count - 1 do if FOptionsList[I] = Any then begin Result := I; break; end; end; procedure TAny.SetCharClass(const Value: TmwCharClass); begin SetLength(FKey, 32); PmwChars(FKey).Chars := Value; Storage.Kind := pkCharClass; end; procedure TAny.SetKey(const Value: string); begin FKey := Value; case Storage.Kind of pkTillChars: ; else if Length(Value) > 1 then Storage.Kind := pkKey else if Length(Value) = 1 then Storage.Kind := pkChar else Storage.Kind := pkAny; end; end; procedure TAny.SetMultiLine(const Value: Boolean); begin case Value of True: Include(Storage.Status, psMultiLine); False: Exclude(Storage.Status, psMultiLine); end; end; procedure TAny.SetNegative(const Value: Boolean); begin case Value of True: Include(Storage.Status, psNegative); False: Exclude(Storage.Status, psNegative); end; end; procedure TAny.SetProcessingNeeded(const Value: Boolean); begin case Value of True: Include(Storage.Status, psProcessingNeeded); False: Exclude(Storage.Status, psProcessingNeeded); end; end; procedure TAny.SetRegress(const Value: Boolean); begin case Value of True: Include(Storage.Status, psRegress); False: Exclude(Storage.Status, psRegress); end; end; { TLineEnd } constructor TLineEnd.Create(AParent: TAny); var Pattern, Option: TAny; begin inherited Create(AParent); Key := #13; Max := 1; Option := TAny.Create(nil); Option.Key := #10; Option.Min := 1; AddOption(Option); Pattern := TAny.Create(Self); Pattern.Key := #10; Pattern.Max := 1; end; { TCRLF } constructor TCRLF.Create(AParent: TAny); begin inherited Create(AParent); Key := #13#10; Min := 1; Max := 1; end; { TLF } constructor TLF.Create(AParent: TAny); begin inherited Create(AParent); Key := #10; Min := 1; Max := 1; end; { TNotZero } constructor TNotZero.Create(AParent: TAny); begin inherited Create(AParent); Storage.Kind := pkCharClass; CharClass := [#0]; Negative := True; end; { TTill } constructor TTill.Create(AParent: TAny); begin inherited Create(AParent); Storage.Kind := pkTillKey; end; { TTillChars } constructor TTillChars.Create(AParent: TAny); begin inherited Create(AParent); Storage.Kind := pkTillChars; end; { TTillLineEnd } constructor TTillLineEnd.Create(AParent: TAny); begin inherited Create(AParent); Storage.Kind := pkTillChars; CharClass := [#10, #13]; Negative := True; end; { TZero } constructor TZero.Create(AParent: TAny); begin inherited Create(AParent); Key := #0; Id := piZero; end; { TAlpha } constructor TAlpha.Create(AParent: TAny); begin inherited Create(AParent); Min := 1; Id := piIdent; Storage.Kind := pkCharClass; CharClass := ['_', 'A'..'Z', 'a'..'z']; end; { TAlphaNumeric } constructor TAlphaNumeric.Create(AParent: TAny); begin inherited Create(AParent); Min := 1; Id := piIdent; Storage.Kind := pkCharClass; CharClass := ['_', '0'..'9', 'A'..'Z', 'a'..'z']; end; { TNumeric } constructor TNumeric.Create(AParent: TAny); begin inherited Create(AParent); Min := 1; Storage.Kind := pkCharClass; CharClass := ['0'..'9']; end; { TIdentifier } constructor TIdentifier.Create(AParent: TAny); begin inherited Create(AParent); TAlphaNumeric.Create(Self); end; (* { TCharAlpha } constructor TCharAlpha.Create(AParent: TAny); var I: Char; begin inherited Create(AParent); Storage.Kind := pkCharClass; SetLength(FKey, 32); for I := #0 to #255 do if IsCharAlpha(I) then Include(PmwChars(FKey).Chars, I); end; { TCharAlphaNumeric } constructor TCharAlphaNumeric.Create(AParent: TAny); var I: Char; begin inherited Create(AParent); Storage.Kind := pkCharClass; SetLength(FKey, 32); for I := #0 to #255 do if IsCharAlphaNumeric(I) then Include(PmwChars(FKey).Chars, I); end; { TCharLower } constructor TCharLower.Create(AParent: TAny); var I: Char; begin inherited Create(AParent); Storage.Kind := pkCharClass; SetLength(FKey, 32); for I := #0 to #255 do if IsCharLower(I) then Include(PmwChars(FKey).Chars, I); end; { TCharUpper } constructor TCharUpper.Create(AParent: TAny); var I: Char; begin inherited Create(AParent); Storage.Kind := pkCharClass; SetLength(FKey, 32); for I := #0 to #255 do if IsCharUpper(I) then Include(PmwChars(FKey).Chars, I); end; *) { TmwGenLex } procedure TmwGenLex.Add(Pattern: TAny); var I: Integer; begin FChain.Add(Pattern); AddToMainSelector(Pattern); for I := 0 to Pattern.Count - 1 do AddToMainSelector(Pattern[Byte(I)]); end; procedure TmwGenLex.AddToMainSelector(Pattern: TAny); var I: Char; begin case Pattern.Kind of pkAny, pkTillChars, pkTillKey: raise exception.Create('pkAny, pkTillChars, pkTillKey not allowed here'); pkCharClass: for I := #0 to #255 do case Pattern.Negative of True: if not (I in Pattern.CharClass) then MainSelector[Char(I)] := Pattern; False: if I in Pattern.CharClass then MainSelector[I] := Pattern; end; pkLineEnd: begin MainSelector[#10] := Pattern; MainSelector[#13] := Pattern; end; else if Length(Pattern.Key) > 0 then MainSelector[Pattern.Key[1]] := Pattern; end; end; function TmwGenLex.ApplyAny: Boolean; begin Range := nil; Result := True; if Run >= TheEnd then begin Result := False; exit; end; inc(Run); end; function TmwGenLex.ApplyChar: Boolean; var Temp: PChar; begin Range := nil; Temp := Run; case psNegative in Current.Storage.Status of True: case Sensitive of True: if Current.Key <> Run^ then begin if Run >= TheEnd then begin Result := False; exit; end; inc(Run) end; False: if CompTable[Current.Key[1]] <> CompTable[Run^] then begin if Run >= TheEnd then begin Result := False; exit; end; inc(Run) end; end; False: case Sensitive of True: if Current.Key = Run^ then begin if Run >= TheEnd then begin Result := False; exit; end; inc(Run) end; False: if CompTable[Current.Key[1]] = CompTable[Run^] then begin if Run >= TheEnd then begin Result := False; exit; end; inc(Run) end; end; end; Result := Run - Temp = 1; end; function TmwGenLex.ApplyCharClass: Boolean; var Temp: PChar; begin Range := nil; Temp := Run; case psNegative in Current.Storage.Status of True: if Current.Max > 0 then begin if not (Run^ in PmwChars(Current.FKey).Chars) then if not AtEnd then inc(Run) end else while not (Run^ in PmwChars(Current.FKey).Chars) do begin if Run >= TheEnd then break; inc(Run); end; False: if Current.Max > 0 then begin if Run^ in PmwChars(Current.FKey).Chars then if not AtEnd then inc(Run) end else while Run^ in PmwChars(Current.FKey).Chars do begin if Run >= TheEnd then break; inc(Run); end; end; Result := Run > Temp; end; function TmwGenLex.ApplyInnerLineEnd: Boolean; begin Result := True; case Run^ of #13: begin inc(Run); if Run < TheEnd then if Run^ = #10 then inc(Run); end; #10: inc(Run); end; if Result then Inc(fLineCount); Range := Current.ToRestore; end; function TmwGenLex.ApplyKey: Boolean; var I: Integer; Temp: PChar; begin Range := nil; Temp := Run; for I := 1 to Length(Current.Key) do begin if Run >= TheEnd then break; case Sensitive of True: if Current.Key[I] = Run^ then inc(Run) else break; False: if CompTable[Current.Key[I]] = CompTable[Run^] then inc(Run) else break; end; end; Result := (Run - Temp) = Length(Current.Key); if not Result then Run := Temp; end; function TmwGenLex.ApplyLineEnd: Boolean; begin Range := nil; Result := True; case Run^ of #13: begin inc(Run); if Run < TheEnd then if Run^ = #10 then inc(Run); end; #10: inc(Run); else Result := False; end; if Result then Inc(fLineCount); end; function TmwGenLex.ApplyTillChars: Boolean; var Temp: PChar; begin Temp := Run; Result := False; while Result = False do begin if Run >= TheEnd then break; case Run^ of #10, #13: case Current.Multiline of True: begin Range := InnerLineEnd; InnerLineEnd.ToRestore := Current; Exit; end; False: begin Result := False; break; end; end; else Temp := Run; Result := ApplyCharClass; if Result = False then inc(Run); end; end; if Result then begin Range := nil; if psNegative in Current.Storage.Status then Run := Temp; end else case Current.Multiline of True: Range := Current; False: begin Range := nil; Run := Temp; end; end; end; function TmwGenLex.ApplyTillKey: Boolean; var Temp: PChar; begin Temp := Run; Result := False; while Result = False do begin if Run >= TheEnd then break; case Run^ of #10, #13: case Current.Multiline of True: begin Range := InnerLineEnd; InnerLineEnd.ToRestore := Current; Exit; end; False: begin Result := False; break; end; end; else if Run^ = Current.Key[1] then begin Result := ApplyKey; if Result = False then inc(Run); end else inc(Run) end; end; if Result then begin Range := nil; if psNegative in Current.Storage.Status then Run := Run - Length(Current.Key); end else case Current.Multiline of True: Range := Current; False: begin Range := nil; Run := Temp; end; end; end; function TmwGenLex.AtEnd: Boolean; begin Result := Run >= TheEnd; end; procedure TmwGenLex.Clear; var I: Integer; begin for I := 0 to fChain.Count - 1 do if Assigned(fChain[I]) then TObject(fChain[I]).Free; fChain.Clear; end; constructor TmwGenLex.Create; begin inherited Create; fLineCount := 0; InnerLineEnd := TAny.Create(nil); InnerLineEnd.Kind := pkInnerLineEnd; InnerLineEnd.Id := piInnerLineEnd; InitSelector; FChain := TList.Create; InitMainSelector; FId := piUnknown; FExId := piUnknown; end; destructor TmwGenLex.Destroy; begin InnerLineEnd.Free; Clear; FChain.Free; inherited Destroy; end; function TmwGenLex.Execute: Boolean; var I: Integer; Temp: PChar; begin Temp := Run; Result := True; if (Current.Max = 0) and (Current.Min = 0) then Selector[Current.Kind] else begin for I := 0 to Current.Min - 1 do Result := Selector[Current.Kind]; if not Result then Run := Temp; for I := Current.Min to Current.Max - 1 do Selector[Current.Kind]; end; end; function TmwGenLex.GetEndPos: Integer; begin Result := TheEnd - FOrigin; end; function TmwGenLex.GetLinePos: Integer; begin Result := fLineCount; end; function TmwGenLex.GetRunPos: Integer; begin Result := Run - FOrigin; end; function TmwGenLex.GetToken: string; begin SetLength(Result, Run - Start); Move(Start^, Result[1], Run - Start); end; procedure TmwGenLex.InitMainSelector; var I: Char; Default: TAny; begin Default := TAny.Create(nil); Default.Key := #0; Default.Id := piZero; FChain.Add(Default); MainSelector[#0] := Default; Default := TAny.Create(nil); FChain.Add(Default); for I := #1 to #255 do MainSelector[I] := Default; end; procedure TmwGenLex.InitSelector; begin Selector[pkAny] := ApplyAny; Selector[pkChar] := ApplyChar; Selector[pkCharClass] := ApplyCharClass; Selector[pkInnerLineEnd] := ApplyInnerLineEnd; Selector[pkKey] := ApplyKey; Selector[pkLineEnd] := ApplyLineEnd; Selector[pkTillChars] := ApplyTillChars; Selector[pkTillKey] := ApplyTillKey; end; procedure TmwGenLex.Next; var Succeed: Boolean; TempRun: PChar; begin Start := Run; if Range <> nil then Current := Range else Current := MainSelector[Run^]; while Current <> nil do begin case Current.Regress of True: begin TempRun := Run; Succeed := SubNext; if Succeed then begin Current := Current.ToRegress; Succeed := SubNext end; if Succeed then begin FId := Current.Id; FExId := Current.ExId; Current := Current.Follow; end else begin Run := TempRun; Current:= nil; end; end; False: begin Succeed := SubNext; if Succeed then begin FId := Current.Id; FExId := Current.ExId; Current := Current.Follow; end; end; end; end; end; procedure TmwGenLex.SetEndPos(const Value: Integer); begin TheEnd := FOrigin + Value; end; procedure TmwGenLex.SetInitMethod(const Value: TmwLexInitMethod); begin if Assigned(Value) then begin Clear; FInitMethod := Value; InitMainSelector; Value(Self); end; end; procedure TmwGenLex.SetInitProc(const Value: TmwLexInitProc); begin if Assigned(Value) then begin Clear; FInitProc := Value; InitMainSelector; Value(Self); end; end; procedure TmwGenLex.SetInput(const Value: string); begin FOrigin := PChar(Value); Run := FOrigin; TheEnd := FOrigin + Length(Value); end; procedure TmwGenLex.SetOrigin(const Value: PChar); begin FOrigin := Value; Run := FOrigin; Start := Value; TheEnd := FOrigin; fLineCount := 0; FId := piUnknown; FExId := piUnknown; end; procedure TmwGenLex.SetRunPos(const Value: Integer); begin Run := FOrigin + Value; Start := Run; end; procedure TmwGenLex.SetStartData(Ptr: Pointer; aLen: Integer); begin Origin := Ptr; TheEnd := PChar(Ptr) + aLen; end; function TmwGenLex.SubNext: Boolean; var I: Integer; Temp: TAny; begin Result := Execute; if not Result then if Current.Count = 0 then Current := nil else for I := 0 to Current.Count - 1 do begin Temp := Current; Current := Current[Byte(I)]; Result := Execute; if Result then break else begin Current := Temp; if I = Current.Count - 1 then begin Current := nil; break; end; end; end; end; initialization InitTables; end. NXT/0000755000175000017500000000000011676036336011122 5ustar slavkoslavkoNXT/NXTDefs.h0000644000175000017500000275100111537752673012561 0ustar slavkoslavko/* NXTDefs.h * Constants, macros, and API functions for use in NBC * * NXTDefs.h contains declarations for the NBC NXT API resources * * License: * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009-2010 John Hansen. * All Rights Reserved. * * ---------------------------------------------------------------------------- * * author John Hansen (bricxcc_at_comcast.net) * date 2011-03-15 * version 76 */ #ifndef NXTDEFS__H #define NXTDEFS__H #include "NBCCommon.h" /** @addtogroup cmpconst * @{ */ #define LT 0x00 /*!< The first value is less than the second. */ #define GT 0x01 /*!< The first value is greater than the second. */ #define LTEQ 0x02 /*!< The first value is less than or equal to the second. */ #define GTEQ 0x03 /*!< The first value is greater than or equal to the second. */ #define EQ 0x04 /*!< The first value is equal to the second. */ #define NEQ 0x05 /*!< The first value is not equal to the second. */ /** @} */ // end of cmpconst group #ifdef __DOXYGEN_DOCS // nothing to see here #else // define structures for various system calls dseg segment TLocation struct X sword Y sword TLocation ends TSize struct Width sword Height sword TSize ends // FileOpenRead, FileOpenWrite, FileOpenAppend, FileOpenWriteLinear, FileOpenWriteNonLinear, FileOpenReadLinear TFileOpen struct Result word FileHandle byte Filename byte[] Length dword TFileOpen ends // FileRead, FileWrite TFileReadWrite struct Result word FileHandle byte Buffer byte[] Length dword TFileReadWrite ends // FileClose TFileClose struct Result word FileHandle byte TFileClose ends // FileResolveHandle TFileResolveHandle struct Result word FileHandle byte WriteHandle byte Filename byte[] TFileResolveHandle ends // FileRename TFileRename struct Result word OldFilename byte[] NewFilename byte[] TFileRename ends // FileDelete TFileDelete struct Result word Filename byte[] TFileDelete ends // SoundPlayFile TSoundPlayFile struct Result sbyte Filename byte[] Loop byte Volume byte TSoundPlayFile ends // SoundPlayTone TSoundPlayTone struct Result sbyte Frequency word Duration word Loop byte Volume byte TSoundPlayTone ends // SoundGetState TSoundGetState struct State byte Flags byte TSoundGetState ends // SoundSetState TSoundSetState struct Result byte State byte Flags byte TSoundSetState ends // DrawText TDrawText struct Result sbyte Location TLocation Text byte[] Options dword TDrawText ends // DrawPoint TDrawPoint struct Result sbyte Location TLocation Options dword TDrawPoint ends // DrawLine TDrawLine struct Result sbyte StartLoc TLocation EndLoc TLocation Options dword TDrawLine ends // DrawCircle TDrawCircle struct Result sbyte Center TLocation Size byte Options dword TDrawCircle ends // DrawRect TDrawRect struct Result sbyte Location TLocation Size TSize Options dword TDrawRect ends // DrawGraphic TDrawGraphic struct Result sbyte Location TLocation Filename byte[] Variables sdword[] Options dword TDrawGraphic ends // SetScreenMode TSetScreenMode struct Result sbyte ScreenMode dword TSetScreenMode ends // ReadButton TReadButton struct Result sbyte Index byte Pressed byte Count byte Reset byte TReadButton ends // CommLSWrite TCommLSWrite struct Result sbyte Port byte Buffer byte[] ReturnLen byte TCommLSWrite ends // CommLSRead TCommLSRead struct Result sbyte Port byte Buffer byte[] BufferLen byte TCommLSRead ends // CommLSCheckStatus TCommLSCheckStatus struct Result sbyte Port byte BytesReady byte TCommLSCheckStatus ends // RandomNumber TRandomNumber struct Result sword TRandomNumber ends // GetStartTick TGetStartTick struct Result dword TGetStartTick ends // MessageWrite TMessageWrite struct Result sbyte QueueID byte Message byte[] TMessageWrite ends // MessageRead TMessageRead struct Result sbyte QueueID byte Remove byte Message byte[] TMessageRead ends // CommBTCheckStatus TCommBTCheckStatus struct Result sbyte Connection byte TCommBTCheckStatus ends // CommBTWrite TCommBTWrite struct Result sbyte Connection byte Buffer byte[] TCommBTWrite ends // CommBTRead TCommBTRead struct Result sbyte Count byte Buffer byte[] TCommBTRead ends // KeepAlive TKeepAlive struct Result dword TKeepAlive ends // IOMapRead TIOMapRead struct Result sbyte ModuleName byte[] Offset word Count word Buffer byte[] TIOMapRead ends // IOMapWrite TIOMapWrite struct Result sbyte ModuleName byte[] Offset word Buffer byte[] TIOMapWrite ends #ifdef __ENHANCED_FIRMWARE TIOMapReadByID struct Result sbyte ModuleID long Offset word Count word Buffer byte[] TIOMapReadByID ends TIOMapWriteByID struct Result sbyte ModuleID long Offset word Buffer byte[] TIOMapWriteByID ends TDisplayExecuteFunction struct Status byte Cmd byte On byte X1 byte Y1 byte X2 byte Y2 byte TDisplayExecuteFunction ends TCommExecuteFunction struct Result word Cmd byte Param1 byte Param2 byte Param3 byte Name byte[] RetVal word TCommExecuteFunction ends TLoaderExecuteFunction struct Result word Cmd byte Filename byte[] Buffer byte[] Length long TLoaderExecuteFunction ends // FileFindFirst, FileFindNext TFileFind struct Result word FileHandle byte Filename byte[] Length dword TFileFind ends TCommHSControl struct Result sbyte Command byte BaudRate byte #if __FIRMWARE_VERSION > 107 Mode word #endif TCommHSControl ends TCommHSCheckStatus struct SendingData byte DataAvailable byte TCommHSCheckStatus ends // CommHSRead, CommHSWrite TCommHSReadWrite struct Status sbyte Buffer byte[] TCommHSReadWrite ends // CommLSWriteEx TCommLSWriteEx struct Result sbyte Port byte Buffer byte[] ReturnLen byte NoRestartOnRead byte TCommLSWriteEx ends #if __FIRMWARE_VERSION > 107 //FileSeek TFileSeek struct Result word FileHandle byte Origin byte Length sdword TFileSeek ends //FileResize TFileResize struct Result word FileHandle byte NewSize word TFileResize ends // DrawGraphicArray TDrawGraphicArray struct Result sbyte Location TLocation Data byte[] Variables sdword[] Options dword TDrawGraphicArray ends // DrawPolygon TDrawPolygon struct Result sbyte Points TLocation[] Options dword TDrawPolygon ends // DrawEllipse TDrawEllipse struct Result sbyte Center TLocation SizeX byte SizeY byte Options dword TDrawEllipse ends // DrawFont TDrawFont struct Result sbyte Location TLocation Filename byte[] Text byte[] Options dword TDrawFont ends // MemoryManager TMemoryManager struct Result sbyte Compact byte PoolSize word DataspaceSize word TMemoryManager ends // ReadLastResponse TReadLastResponse struct Result sbyte Clear byte Length byte Command byte Buffer byte[] TReadLastResponse ends // FileTell TFileTell struct Result sbyte FileHandle byte Position dword TFileTell ends #endif #endif #if __FIRMWARE_VERSION > 107 // ColorSensorRead TColorSensorRead struct Result sbyte Port byte ColorValue sword RawArray word[] NormalizedArray word[] ScaledArray sword[] Invalid byte TColorSensorRead ends // DatalogWrite TDatalogWrite struct Result sbyte Message byte[] TDatalogWrite ends // DatalogGetTimes TDatalogGetTimes struct SyncTime dword SyncTick dword TDatalogGetTimes ends // SetSleepTimeout TSetSleepTimeout struct Result sbyte TheSleepTimeoutMS dword TSetSleepTimeout ends // CommBTOnOff TCommBTOnOff struct #ifdef __ENHANCED_FIRMWARE Result word #else Result sbyte #endif PowerState byte TCommBTOnOff ends // CommBTConnection TCommBTConnection struct #ifdef __ENHANCED_FIRMWARE Result word #else Result sbyte #endif Action byte Name byte[] ConnectionSlot byte TCommBTConnection ends // ReadSemData TReadSemData struct SemData byte Request byte TReadSemData ends // WriteSemData TWriteSemData struct SemData byte Request byte NewVal byte ClearBits byte TWriteSemData ends // UpdateCalibCacheInfo TUpdateCalibCacheInfo struct Result byte Name byte[] MinVal word MaxVal word TUpdateCalibCacheInfo ends // ComputeCalibValue TComputeCalibValue struct Result byte Name byte[] RawVal word TComputeCalibValue ends // ListFiles TListFiles struct Result sbyte Pattern byte[] FileList byte[][] TListFiles ends #endif #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) TOutputState struct // for use with the RemoteGetOutputState direct command response Port byte Power sbyte Mode byte RegMode byte TurnRatio sbyte RunState byte TachoLimit dword TachoCount sdword BlockTachoCount sdword RotationCount sdword TOutputState ends TInputValues struct // for use with the RemoteGetInputValues direct command response Port byte Valid byte Calibrated byte SensorType byte SensorMode byte RawValue word NormalizedValue word ScaledValue sword CalibratedValue sword TInputValues ends TInput struct CustomZeroOffset word ADRaw word SensorRaw word SensorValue sword SensorType byte SensorMode byte SensorBoolean byte DigiPinsDir byte DigiPinsIn byte DigiPinsOut byte CustomPctFullScale byte CustomActiveStatus byte InvalidData byte TInput ends // 17 bytes TOutput struct TachoCnt sdword BlockTachoCount sdword RotationCount sdword TachoLimit dword MotorRPM sword Flags byte Mode byte Speed sbyte ActualSpeed sbyte RegPParameter byte RegIParameter byte RegDParameter byte RunState byte RegMode byte Overloaded byte SyncTurnParameter sbyte Options byte TOutput ends // 30 bytes TButtonCounts struct BtnPressedCnt byte BtnLongPressCnt byte BtnShortRelCnt byte BtnLongRelCnt byte BtnRelCnt byte TButtonCounts ends // 5 bytes TBluetoothDevice struct Name byte[] ClassOfDevice byte[] BdAddr byte[] DeviceStatus byte TBluetoothDevice ends // 28 bytes TBluetoothConnection struct Name byte[] ClassOfDevice byte[] PinCode byte[] BdAddr byte[] HandleNr byte StreamStatus byte LinkQuality byte TBluetoothConnection ends // 46 bytes TBrickData struct Name byte[] BluecoreVersion byte[] BdAddr byte[] BtStateStatus byte BtHwStatus byte TimeOutValue byte TBrickData ends // 28 bytes #endif dseg ends // motor arrays (compiler will optimize these out if they are not used) dseg segment __OUT_AB byte[] OUT_A, OUT_B __OUT_AC byte[] OUT_A, OUT_C __OUT_BC byte[] OUT_B, OUT_C __OUT_ABC byte[] OUT_A, OUT_B, OUT_C __OnRev_Tmp sbyte __OnRevMutex mutex dseg ends dseg segment __rotateMutex0 mutex __rotateMutex1 mutex __rotateMutex2 mutex dseg ends dseg segment // variables for rotate motor subroutine (0) __rotate_power0 byte __rotate_angle0 slong __rotate_ports0 byte[] __rotate_firstPort0 byte __rotate_sync0 byte __rotate_stop0 byte __rotate_turnpct0 sbyte __rotate_theUF0 byte __rotate_theOM0 byte __rotate_theRM0 byte __rotate_theRS0 byte __rotate_theRVP0 byte __rotate_theRVI0 byte __rotate_theRVD0 byte __rotate_rs0 byte __rotate_OldRotCount0 sword __rotate_RotCount0 sword __rotate_thePower0 sbyte __rotate_theAngle0 ulong __rotate_theTurnPct0 sbyte __rotate_then0 dword __rotate_now0 dword dseg ends dseg segment // variables for rotate motor subroutine (1) __rotate_power1 byte __rotate_angle1 slong __rotate_ports1 byte[] __rotate_firstPort1 byte __rotate_sync1 byte __rotate_stop1 byte __rotate_turnpct1 sbyte __rotate_theUF1 byte __rotate_theOM1 byte __rotate_theRM1 byte __rotate_theRS1 byte __rotate_theRVP1 byte __rotate_theRVI1 byte __rotate_theRVD1 byte __rotate_rs1 byte __rotate_OldRotCount1 sword __rotate_RotCount1 sword __rotate_thePower1 sbyte __rotate_theAngle1 ulong __rotate_theTurnPct1 sbyte __rotate_then1 dword __rotate_now1 dword dseg ends dseg segment // variables for rotate motor subroutine (2) __rotate_power2 byte __rotate_angle2 slong __rotate_ports2 byte[] __rotate_firstPort2 byte __rotate_sync2 byte __rotate_stop2 byte __rotate_turnpct2 sbyte __rotate_theUF2 byte __rotate_theOM2 byte __rotate_theRM2 byte __rotate_theRS2 byte __rotate_theRVP2 byte __rotate_theRVI2 byte __rotate_theRVD2 byte __rotate_rs2 byte __rotate_OldRotCount2 sword __rotate_RotCount2 sword __rotate_thePower2 sbyte __rotate_theAngle2 ulong __rotate_theTurnPct2 sbyte __rotate_then2 dword __rotate_now2 dword dseg ends dseg segment // variables for rotate motor subroutine (3) __rotate_power3 byte __rotate_angle3 slong __rotate_ports3 byte[] __rotate_firstPort3 byte __rotate_sync3 byte __rotate_stop3 byte __rotate_turnpct3 sbyte __rotate_theUF3 byte __rotate_theOM3 byte __rotate_theRM3 byte __rotate_theRS3 byte __rotate_theRVP3 byte __rotate_theRVI3 byte __rotate_theRVD3 byte __rotate_rs3 byte __rotate_OldRotCount3 sword __rotate_RotCount3 sword __rotate_thePower3 sbyte __rotate_theAngle3 ulong __rotate_theTurnPct3 sbyte __rotate_then3 dword __rotate_now3 dword dseg ends dseg segment // variables for rotate motor subroutine (4) __rotate_power4 byte __rotate_angle4 slong __rotate_ports4 byte[] __rotate_firstPort4 byte __rotate_sync4 byte __rotate_stop4 byte __rotate_turnpct4 sbyte __rotate_theUF4 byte __rotate_theOM4 byte __rotate_theRM4 byte __rotate_theRS4 byte __rotate_theRVP4 byte __rotate_theRVI4 byte __rotate_theRVD4 byte __rotate_rs4 byte __rotate_OldRotCount4 sword __rotate_RotCount4 sword __rotate_thePower4 sbyte __rotate_theAngle4 ulong __rotate_theTurnPct4 sbyte __rotate_then4 dword __rotate_now4 dword dseg ends dseg segment // variables for rotate motor subroutine (5) __rotate_power5 byte __rotate_angle5 slong __rotate_ports5 byte[] __rotate_firstPort5 byte __rotate_sync5 byte __rotate_stop5 byte __rotate_turnpct5 sbyte __rotate_theUF5 byte __rotate_theOM5 byte __rotate_theRM5 byte __rotate_theRS5 byte __rotate_theRVP5 byte __rotate_theRVI5 byte __rotate_theRVD5 byte __rotate_rs5 byte __rotate_OldRotCount5 sword __rotate_RotCount5 sword __rotate_thePower5 sbyte __rotate_theAngle5 ulong __rotate_theTurnPct5 sbyte __rotate_then5 dword __rotate_now5 dword dseg ends dseg segment // variables for rotate motor subroutine (6) __rotate_power6 byte __rotate_angle6 slong __rotate_ports6 byte[] __rotate_firstPort6 byte __rotate_sync6 byte __rotate_stop6 byte __rotate_turnpct6 sbyte __rotate_theUF6 byte __rotate_theOM6 byte __rotate_theRM6 byte __rotate_theRS6 byte __rotate_theRVP6 byte __rotate_theRVI6 byte __rotate_theRVD6 byte __rotate_rs6 byte __rotate_OldRotCount6 sword __rotate_RotCount6 sword __rotate_thePower6 sbyte __rotate_theAngle6 ulong __rotate_theTurnPct6 sbyte __rotate_then6 dword __rotate_now6 dword dseg ends #define UF_UPDATE_ONFWD 0x28 // API macros #define __resetMotorCounter0(_val) setout OUT_A, UpdateFlagsField, _val #define __resetMotorCounter1(_val) setout OUT_B, UpdateFlagsField, _val #define __resetMotorCounter2(_val) setout OUT_C, UpdateFlagsField, _val #define __resetMotorCounter3(_val) setout __OUT_AB, UpdateFlagsField, _val #define __resetMotorCounter4(_val) setout __OUT_AC, UpdateFlagsField, _val #define __resetMotorCounter5(_val) setout __OUT_BC, UpdateFlagsField, _val #define __resetMotorCounter6(_val) setout __OUT_ABC, UpdateFlagsField, _val #define __resetTachoCount(_p) \ compif EQ, isconst(_p), FALSE \ setout _p, UpdateFlagsField, RESET_COUNT \ compelse \ compchk LT, _p, 0x07 \ compchk GTEQ, _p, 0x00 \ __resetMotorCounter##_p(RESET_COUNT) \ compend #define __resetBlockTachoCount(_p) \ compif EQ, isconst(_p), FALSE \ setout _p, UpdateFlagsField, RESET_BLOCK_COUNT \ compelse \ compchk LT, _p, 0x07 \ compchk GTEQ, _p, 0x00 \ __resetMotorCounter##_p(RESET_BLOCK_COUNT) \ compend #define __resetRotationCount(_p) \ compif EQ, isconst(_p), FALSE \ setout _p, UpdateFlagsField, RESET_ROTATION_COUNT \ compelse \ compchk LT, _p, 0x07 \ compchk GTEQ, _p, 0x00 \ __resetMotorCounter##_p(RESET_ROTATION_COUNT) \ compend #define __resetAllTachoCounts(_p) \ compif EQ, isconst(_p), FALSE \ setout _p, UpdateFlagsField, RESET_ALL \ compelse \ compchk LT, _p, 0x07 \ compchk GTEQ, _p, 0x00 \ __resetMotorCounter##_p(RESET_ALL) \ compend #define __onFwdExPIDAll(_ports, _pwr, _reset, _p, _i, _d) setout _ports, PowerField, _pwr, OutputModeField, OUT_MODE_MOTORON+OUT_MODE_BRAKE, RegModeField, OUT_REGMODE_IDLE, RunStateField, OUT_RUNSTATE_RUNNING, TurnRatioField, 0, TachoLimitField, 0, RegPValueField, _p, RegIValueField, _i, RegDValueField, _d, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+_reset #define __onFwdExPID0(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(OUT_A, _pwr, _reset, _p, _i, _d) #define __onFwdExPID1(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(OUT_B, _pwr, _reset, _p, _i, _d) #define __onFwdExPID2(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(OUT_C, _pwr, _reset, _p, _i, _d) #define __onFwdExPID3(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(__OUT_AB, _pwr, _reset, _p, _i, _d) #define __onFwdExPID4(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(__OUT_AC, _pwr, _reset, _p, _i, _d) #define __onFwdExPID5(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(__OUT_BC, _pwr, _reset, _p, _i, _d) #define __onFwdExPID6(_pwr, _reset, _p, _i, _d) __onFwdExPIDAll(__OUT_ABC, _pwr, _reset, _p, _i, _d) #define __coastExAll(_ports, _reset) setout _ports, PowerField, 0, OutputModeField, OUT_MODE_BRAKE, RegModeField, OUT_REGMODE_IDLE, RunStateField, OUT_RUNSTATE_IDLE, TurnRatioField, 0, TachoLimitField, 0, RegPValueField, PID_3, RegIValueField, PID_1, RegDValueField, PID_1, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+_reset #define __coastEx0(_reset) __coastExAll(OUT_A, _reset) #define __coastEx1(_reset) __coastExAll(OUT_B, _reset) #define __coastEx2(_reset) __coastExAll(OUT_C, _reset) #define __coastEx3(_reset) __coastExAll(__OUT_AB, _reset) #define __coastEx4(_reset) __coastExAll(__OUT_AC, _reset) #define __coastEx5(_reset) __coastExAll(__OUT_BC, _reset) #define __coastEx6(_reset) __coastExAll(__OUT_ABC, _reset) #define __offExAll(_ports, _reset) setout _ports, PowerField, 0, OutputModeField, OUT_MODE_MOTORON+OUT_MODE_BRAKE, RegModeField, OUT_REGMODE_IDLE, RunStateField, OUT_RUNSTATE_RUNNING, TurnRatioField, 0, TachoLimitField, 0, RegPValueField, PID_3, RegIValueField, PID_1, RegDValueField, PID_1, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+_reset #define __offEx0(_reset) __offExAll(OUT_A, _reset) #define __offEx1(_reset) __offExAll(OUT_B, _reset) #define __offEx2(_reset) __offExAll(OUT_C, _reset) #define __offEx3(_reset) __offExAll(__OUT_AB, _reset) #define __offEx4(_reset) __offExAll(__OUT_AC, _reset) #define __offEx5(_reset) __offExAll(__OUT_BC, _reset) #define __offEx6(_reset) __offExAll(__OUT_ABC, _reset) #define __onFwdRegExPIDAll(_ports, _pwr, _regmode, _reset, _p, _i, _d) setout _ports, PowerField, _pwr, OutputModeField, OUT_MODE_MOTORON+OUT_MODE_REGULATED+OUT_MODE_BRAKE, RegModeField, _regmode, RunStateField, OUT_RUNSTATE_RUNNING, TurnRatioField, 0, TachoLimitField, 0, RegPValueField, _p, RegIValueField, _i, RegDValueField, _d, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+_reset #define __onFwdRegExPID0(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(OUT_A, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID1(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(OUT_B, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID2(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(OUT_C, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID3(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(__OUT_AB, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID4(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(__OUT_AC, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID5(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(__OUT_BC, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdRegExPID6(_pwr, _regmode, _reset, _p, _i, _d) __onFwdRegExPIDAll(__OUT_ABC, _pwr, _regmode, _reset, _p, _i, _d) #define __onFwdSyncExPIDAll(_ports, _pwr, _turnpct, _reset, _p, _i, _d) setout _ports, PowerField, _pwr, OutputModeField, OUT_MODE_MOTORON+OUT_MODE_REGULATED+OUT_MODE_BRAKE, RegModeField, OUT_REGMODE_SYNC, TurnRatioField, _turnpct, RunStateField, OUT_RUNSTATE_RUNNING, TachoLimitField, 0, RegPValueField, _p, RegIValueField, _i, RegDValueField, _d, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+_reset #define __onFwdSyncExPID0(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(OUT_A, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID1(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(OUT_B, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID2(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(OUT_C, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID3(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(__OUT_AB, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID4(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(__OUT_AC, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID5(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(__OUT_BC, _pwr, _turnpct, _reset, _p, _i, _d) #define __onFwdSyncExPID6(_pwr, _turnpct, _reset, _p, _i, _d) __onFwdSyncExPIDAll(__OUT_ABC, _pwr, _turnpct, _reset, _p, _i, _d) #define __rotateMotorExPID0(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex0 \ arrbuild __rotate_ports0, OUT_A \ mov __rotate_power0, _pwr \ mov __rotate_angle0, _angle \ mov __rotate_turnpct0, _turnpct \ mov __rotate_sync0, _bSync \ mov __rotate_stop0, _bStop \ mov __rotate_theRVP0, _p \ mov __rotate_theRVI0, _i \ mov __rotate_theRVD0, _d \ call __RotateMotor0 \ release __rotateMutex0 #define __rotateMotorExPID1(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex1 \ arrbuild __rotate_ports1, OUT_B \ mov __rotate_power1, _pwr \ mov __rotate_angle1, _angle \ mov __rotate_turnpct1, _turnpct \ mov __rotate_sync1, _bSync \ mov __rotate_stop1, _bStop \ mov __rotate_theRVP1, _p \ mov __rotate_theRVI1, _i \ mov __rotate_theRVD1, _d \ call __RotateMotor1 \ release __rotateMutex1 #define __rotateMotorExPID2(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex2 \ arrbuild __rotate_ports2, OUT_C \ mov __rotate_power2, _pwr \ mov __rotate_angle2, _angle \ mov __rotate_turnpct2, _turnpct \ mov __rotate_sync2, _bSync \ mov __rotate_stop2, _bStop \ mov __rotate_theRVP2, _p \ mov __rotate_theRVI2, _i \ mov __rotate_theRVD2, _d \ call __RotateMotor2 \ release __rotateMutex2 #define __rotateMotorExPID3(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex0 \ acquire __rotateMutex1 \ mov __rotate_ports3, __OUT_AB \ mov __rotate_power3, _pwr \ mov __rotate_angle3, _angle \ mov __rotate_turnpct3, _turnpct \ mov __rotate_sync3, _bSync \ mov __rotate_stop3, _bStop \ mov __rotate_theRVP3, _p \ mov __rotate_theRVI3, _i \ mov __rotate_theRVD3, _d \ call __RotateMotor3 \ release __rotateMutex1 \ release __rotateMutex0 #define __rotateMotorExPID4(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex0 \ acquire __rotateMutex2 \ mov __rotate_ports4, __OUT_AC \ mov __rotate_power4, _pwr \ mov __rotate_angle4, _angle \ mov __rotate_turnpct4, _turnpct \ mov __rotate_sync4, _bSync \ mov __rotate_stop4, _bStop \ mov __rotate_theRVP4, _p \ mov __rotate_theRVI4, _i \ mov __rotate_theRVD4, _d \ call __RotateMotor4 \ release __rotateMutex2 \ release __rotateMutex0 #define __rotateMotorExPID5(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex1 \ acquire __rotateMutex2 \ mov __rotate_ports5, __OUT_BC \ mov __rotate_power5, _pwr \ mov __rotate_angle5, _angle \ mov __rotate_turnpct5, _turnpct \ mov __rotate_sync5, _bSync \ mov __rotate_stop5, _bStop \ mov __rotate_theRVP5, _p \ mov __rotate_theRVI5, _i \ mov __rotate_theRVD5, _d \ call __RotateMotor5 \ release __rotateMutex2 \ release __rotateMutex1 #define __rotateMotorExPID6(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex0 \ acquire __rotateMutex1 \ acquire __rotateMutex2 \ mov __rotate_ports6, __OUT_ABC \ mov __rotate_power6, _pwr \ mov __rotate_angle6, _angle \ mov __rotate_turnpct6, _turnpct \ mov __rotate_sync6, _bSync \ mov __rotate_stop6, _bStop \ mov __rotate_theRVP6, _p \ mov __rotate_theRVI6, _i \ mov __rotate_theRVD6, _d \ call __RotateMotor6 \ release __rotateMutex2 \ release __rotateMutex1 \ release __rotateMutex0 #define __rotateMotorExPIDVar(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ acquire __rotateMutex0 \ acquire __rotateMutex1 \ acquire __rotateMutex2 \ arrbuild __rotate_ports6, _ports \ mov __rotate_power6, _pwr \ mov __rotate_angle6, _angle \ mov __rotate_turnpct6, _turnpct \ mov __rotate_sync6, _bSync \ mov __rotate_stop6, _bStop \ mov __rotate_theRVP6, _p \ mov __rotate_theRVI6, _i \ mov __rotate_theRVD6, _d \ call __RotateMotorVar \ release __rotateMutex2 \ release __rotateMutex1 \ release __rotateMutex0 subroutine __RotateMotor0 brtst EQ, __rotate_Done0, __rotate_angle0 sign __rotate_thePower0, __rotate_angle0 abs __rotate_theAngle0, __rotate_angle0 mul __rotate_thePower0, __rotate_thePower0, __rotate_power0 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF0, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync0, __rotate_sync0 set __rotate_theOM0, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM0, OUT_REGMODE_SYNC mov __rotate_theTurnPct0, __rotate_turnpct0 brtst EQ, __rotate_Start0, __rotate_theTurnPct0 add __rotate_theUF0, __rotate_theUF0, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start0 __rotate_NoSync0: set __rotate_theOM0, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM0, OUT_REGMODE_IDLE set __rotate_theTurnPct0, 0 __rotate_Start0: set __rotate_theRS0, OUT_RUNSTATE_RUNNING setout __rotate_ports0, OutputModeField, __rotate_theOM0, RegModeField, __rotate_theRM0, TachoLimitField, __rotate_theAngle0, RunStateField, __rotate_theRS0, RegPValueField, __rotate_theRVP0, RegIValueField, __rotate_theRVI0, RegDValueField, __rotate_theRVD0, PowerField, __rotate_thePower0, TurnRatioField, __rotate_turnpct0, UpdateFlagsField, __rotate_theUF0 // Waits till angle reached index __rotate_firstPort0, __rotate_ports0, NA __rotate_Running0: getout __rotate_power0, __rotate_firstPort0, PowerField brtst EQ, __rotate_doneRunning0, __rotate_power0 getout __rotate_rs0, __rotate_firstPort0, RunStateField brcmp EQ, __rotate_Running0, __rotate_rs0, OUT_RUNSTATE_RUNNING __rotate_doneRunning0: brtst EQ, __rotate_Reset0, __rotate_stop0 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM0, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF0, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports0, OutputModeField, __rotate_theOM0, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS0, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF0 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount0, __rotate_firstPort0, RotationCountField __rotate_Stabilize0: mov __rotate_OldRotCount0, __rotate_RotCount0 wait 50 // check rotation getout __rotate_RotCount0, __rotate_firstPort0, RotationCountField brcmp NEQ, __rotate_Stabilize0, __rotate_OldRotCount0, __rotate_RotCount0 set __rotate_theOM0, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports0, RegModeField, __rotate_theRM0, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM0, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset0: // maybe reset the block rotation count brtst EQ, __rotate_Done0, __rotate_theTurnPct0 setout __rotate_ports0, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done0: return ends subroutine __RotateMotor1 brtst EQ, __rotate_Done1, __rotate_angle1 sign __rotate_thePower1, __rotate_angle1 abs __rotate_theAngle1, __rotate_angle1 mul __rotate_thePower1, __rotate_thePower1, __rotate_power1 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF1, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync1, __rotate_sync1 set __rotate_theOM1, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM1, OUT_REGMODE_SYNC mov __rotate_theTurnPct1, __rotate_turnpct1 brtst EQ, __rotate_Start1, __rotate_theTurnPct1 add __rotate_theUF1, __rotate_theUF1, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start1 __rotate_NoSync1: set __rotate_theOM1, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM1, OUT_REGMODE_IDLE set __rotate_theTurnPct1, 0 __rotate_Start1: set __rotate_theRS1, OUT_RUNSTATE_RUNNING setout __rotate_ports1, OutputModeField, __rotate_theOM1, RegModeField, __rotate_theRM1, TachoLimitField, __rotate_theAngle1, RunStateField, __rotate_theRS1, RegPValueField, __rotate_theRVP1, RegIValueField, __rotate_theRVI1, RegDValueField, __rotate_theRVD1, PowerField, __rotate_thePower1, TurnRatioField, __rotate_turnpct1, UpdateFlagsField, __rotate_theUF1 // Waits till angle reached index __rotate_firstPort1, __rotate_ports1, NA __rotate_Running1: getout __rotate_power1, __rotate_firstPort1, PowerField brtst EQ, __rotate_doneRunning1, __rotate_power1 getout __rotate_rs1, __rotate_firstPort1, RunStateField brcmp EQ, __rotate_Running1, __rotate_rs1, OUT_RUNSTATE_RUNNING __rotate_doneRunning1: brtst EQ, __rotate_Reset1, __rotate_stop1 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM1, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF1, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports1, OutputModeField, __rotate_theOM1, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS1, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF1 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount1, __rotate_firstPort1, RotationCountField __rotate_Stabilize1: mov __rotate_OldRotCount1, __rotate_RotCount1 wait 50 // check rotation getout __rotate_RotCount1, __rotate_firstPort1, RotationCountField brcmp NEQ, __rotate_Stabilize1, __rotate_OldRotCount1, __rotate_RotCount1 set __rotate_theOM1, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports1, RegModeField, __rotate_theRM1, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM1, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset1: // maybe reset the block rotation count brtst EQ, __rotate_Done1, __rotate_theTurnPct1 setout __rotate_ports1, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done1: return ends subroutine __RotateMotor2 brtst EQ, __rotate_Done2, __rotate_angle2 sign __rotate_thePower2, __rotate_angle2 abs __rotate_theAngle2, __rotate_angle2 mul __rotate_thePower2, __rotate_thePower2, __rotate_power2 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF2, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync2, __rotate_sync2 set __rotate_theOM2, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM2, OUT_REGMODE_SYNC mov __rotate_theTurnPct2, __rotate_turnpct2 brtst EQ, __rotate_Start2, __rotate_theTurnPct2 add __rotate_theUF2, __rotate_theUF2, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start2 __rotate_NoSync2: set __rotate_theOM2, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM2, OUT_REGMODE_IDLE set __rotate_theTurnPct2, 0 __rotate_Start2: set __rotate_theRS2, OUT_RUNSTATE_RUNNING setout __rotate_ports2, OutputModeField, __rotate_theOM2, RegModeField, __rotate_theRM2, TachoLimitField, __rotate_theAngle2, RunStateField, __rotate_theRS2, RegPValueField, __rotate_theRVP2, RegIValueField, __rotate_theRVI2, RegDValueField, __rotate_theRVD2, PowerField, __rotate_thePower2, TurnRatioField, __rotate_turnpct2, UpdateFlagsField, __rotate_theUF2 // Waits till angle reached index __rotate_firstPort2, __rotate_ports2, NA __rotate_Running2: getout __rotate_power2, __rotate_firstPort2, PowerField brtst EQ, __rotate_doneRunning2, __rotate_power2 getout __rotate_rs2, __rotate_firstPort2, RunStateField brcmp EQ, __rotate_Running2, __rotate_rs2, OUT_RUNSTATE_RUNNING __rotate_doneRunning2: brtst EQ, __rotate_Reset2, __rotate_stop2 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM2, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF2, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports2, OutputModeField, __rotate_theOM2, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS2, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF2 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount2, __rotate_firstPort2, RotationCountField __rotate_Stabilize2: mov __rotate_OldRotCount2, __rotate_RotCount2 wait 50 // check rotation getout __rotate_RotCount2, __rotate_firstPort2, RotationCountField brcmp NEQ, __rotate_Stabilize2, __rotate_OldRotCount2, __rotate_RotCount2 set __rotate_theOM2, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports2, RegModeField, __rotate_theRM2, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM2, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset2: // maybe reset the block rotation count brtst EQ, __rotate_Done2, __rotate_theTurnPct2 setout __rotate_ports2, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done2: return ends subroutine __RotateMotor3 brtst EQ, __rotate_Done3, __rotate_angle3 sign __rotate_thePower3, __rotate_angle3 abs __rotate_theAngle3, __rotate_angle3 mul __rotate_thePower3, __rotate_thePower3, __rotate_power3 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF3, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync3, __rotate_sync3 set __rotate_theOM3, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM3, OUT_REGMODE_SYNC mov __rotate_theTurnPct3, __rotate_turnpct3 brtst EQ, __rotate_Start3, __rotate_theTurnPct3 add __rotate_theUF3, __rotate_theUF3, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start3 __rotate_NoSync3: set __rotate_theOM3, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM3, OUT_REGMODE_IDLE set __rotate_theTurnPct3, 0 __rotate_Start3: set __rotate_theRS3, OUT_RUNSTATE_RUNNING setout __rotate_ports3, OutputModeField, __rotate_theOM3, RegModeField, __rotate_theRM3, TachoLimitField, __rotate_theAngle3, RunStateField, __rotate_theRS3, RegPValueField, __rotate_theRVP3, RegIValueField, __rotate_theRVI3, RegDValueField, __rotate_theRVD3, PowerField, __rotate_thePower3, TurnRatioField, __rotate_turnpct3, UpdateFlagsField, __rotate_theUF3 // Waits till angle reached index __rotate_firstPort3, __rotate_ports3, NA __rotate_Running3: getout __rotate_power3, __rotate_firstPort3, PowerField brtst EQ, __rotate_doneRunning3, __rotate_power3 getout __rotate_rs3, __rotate_firstPort3, RunStateField brcmp EQ, __rotate_Running3, __rotate_rs3, OUT_RUNSTATE_RUNNING __rotate_doneRunning3: brtst EQ, __rotate_Reset3, __rotate_stop3 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM3, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF3, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports3, OutputModeField, __rotate_theOM3, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS3, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF3 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount3, __rotate_firstPort3, RotationCountField __rotate_Stabilize3: mov __rotate_OldRotCount3, __rotate_RotCount3 wait 50 // check rotation getout __rotate_RotCount3, __rotate_firstPort3, RotationCountField brcmp NEQ, __rotate_Stabilize3, __rotate_OldRotCount3, __rotate_RotCount3 set __rotate_theOM3, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports3, RegModeField, __rotate_theRM3, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM3, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset3: // maybe reset the block rotation count brtst EQ, __rotate_Done3, __rotate_theTurnPct3 setout __rotate_ports3, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done3: return ends subroutine __RotateMotor4 brtst EQ, __rotate_Done4, __rotate_angle4 sign __rotate_thePower4, __rotate_angle4 abs __rotate_theAngle4, __rotate_angle4 mul __rotate_thePower4, __rotate_thePower4, __rotate_power4 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF4, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync4, __rotate_sync4 set __rotate_theOM4, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM4, OUT_REGMODE_SYNC mov __rotate_theTurnPct4, __rotate_turnpct4 brtst EQ, __rotate_Start4, __rotate_theTurnPct4 add __rotate_theUF4, __rotate_theUF4, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start4 __rotate_NoSync4: set __rotate_theOM4, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM4, OUT_REGMODE_IDLE set __rotate_theTurnPct4, 0 __rotate_Start4: set __rotate_theRS4, OUT_RUNSTATE_RUNNING setout __rotate_ports4, OutputModeField, __rotate_theOM4, RegModeField, __rotate_theRM4, TachoLimitField, __rotate_theAngle4, RunStateField, __rotate_theRS4, RegPValueField, __rotate_theRVP4, RegIValueField, __rotate_theRVI4, RegDValueField, __rotate_theRVD4, PowerField, __rotate_thePower4, TurnRatioField, __rotate_turnpct4, UpdateFlagsField, __rotate_theUF4 // Waits till angle reached index __rotate_firstPort4, __rotate_ports4, NA __rotate_Running4: getout __rotate_power4, __rotate_firstPort4, PowerField brtst EQ, __rotate_doneRunning4, __rotate_power4 getout __rotate_rs4, __rotate_firstPort4, RunStateField brcmp EQ, __rotate_Running4, __rotate_rs4, OUT_RUNSTATE_RUNNING __rotate_doneRunning4: brtst EQ, __rotate_Reset4, __rotate_stop4 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM4, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF4, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports4, OutputModeField, __rotate_theOM4, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS4, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF4 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount4, __rotate_firstPort4, RotationCountField __rotate_Stabilize4: mov __rotate_OldRotCount4, __rotate_RotCount4 wait 50 // check rotation getout __rotate_RotCount4, __rotate_firstPort4, RotationCountField brcmp NEQ, __rotate_Stabilize4, __rotate_OldRotCount4, __rotate_RotCount4 set __rotate_theOM4, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports4, RegModeField, __rotate_theRM4, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM4, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset4: // maybe reset the block rotation count brtst EQ, __rotate_Done4, __rotate_theTurnPct4 setout __rotate_ports4, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done4: return ends subroutine __RotateMotor5 brtst EQ, __rotate_Done5, __rotate_angle5 sign __rotate_thePower5, __rotate_angle5 abs __rotate_theAngle5, __rotate_angle5 mul __rotate_thePower5, __rotate_thePower5, __rotate_power5 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF5, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync5, __rotate_sync5 set __rotate_theOM5, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM5, OUT_REGMODE_SYNC mov __rotate_theTurnPct5, __rotate_turnpct5 brtst EQ, __rotate_Start5, __rotate_theTurnPct5 add __rotate_theUF5, __rotate_theUF5, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start5 __rotate_NoSync5: set __rotate_theOM5, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM5, OUT_REGMODE_IDLE set __rotate_theTurnPct5, 0 __rotate_Start5: set __rotate_theRS5, OUT_RUNSTATE_RUNNING setout __rotate_ports5, OutputModeField, __rotate_theOM5, RegModeField, __rotate_theRM5, TachoLimitField, __rotate_theAngle5, RunStateField, __rotate_theRS5, RegPValueField, __rotate_theRVP5, RegIValueField, __rotate_theRVI5, RegDValueField, __rotate_theRVD5, PowerField, __rotate_thePower5, TurnRatioField, __rotate_turnpct5, UpdateFlagsField, __rotate_theUF5 // Waits till angle reached index __rotate_firstPort5, __rotate_ports5, NA __rotate_Running5: getout __rotate_power5, __rotate_firstPort5, PowerField brtst EQ, __rotate_doneRunning5, __rotate_power5 getout __rotate_rs5, __rotate_firstPort5, RunStateField brcmp EQ, __rotate_Running5, __rotate_rs5, OUT_RUNSTATE_RUNNING __rotate_doneRunning5: brtst EQ, __rotate_Reset5, __rotate_stop5 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM5, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF5, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports5, OutputModeField, __rotate_theOM5, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS5, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF5 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount5, __rotate_firstPort5, RotationCountField __rotate_Stabilize5: mov __rotate_OldRotCount5, __rotate_RotCount5 wait 50 // check rotation getout __rotate_RotCount5, __rotate_firstPort5, RotationCountField brcmp NEQ, __rotate_Stabilize5, __rotate_OldRotCount5, __rotate_RotCount5 set __rotate_theOM5, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports5, RegModeField, __rotate_theRM5, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM5, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset5: // maybe reset the block rotation count brtst EQ, __rotate_Done5, __rotate_theTurnPct5 setout __rotate_ports5, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done5: return ends subroutine __RotateMotor6 brtst EQ, __rotate_Done6, __rotate_angle6 sign __rotate_thePower6, __rotate_angle6 abs __rotate_theAngle6, __rotate_angle6 mul __rotate_thePower6, __rotate_thePower6, __rotate_power6 // convert __rotate_power to negative value if __rotate_angle is negative. set __rotate_theUF6, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE+UF_UPDATE_PID_VALUES brtst EQ, __rotate_NoSync6, __rotate_sync6 set __rotate_theOM6, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theRM6, OUT_REGMODE_SYNC mov __rotate_theTurnPct6, __rotate_turnpct6 brtst EQ, __rotate_Start6, __rotate_theTurnPct6 add __rotate_theUF6, __rotate_theUF6, UF_UPDATE_RESET_BLOCK_COUNT jmp __rotate_Start6 __rotate_NoSync6: set __rotate_theOM6, OUT_MODE_MOTORON+OUT_MODE_BRAKE set __rotate_theRM6, OUT_REGMODE_IDLE set __rotate_theTurnPct6, 0 __rotate_Start6: set __rotate_theRS6, OUT_RUNSTATE_RUNNING setout __rotate_ports6, OutputModeField, __rotate_theOM6, RegModeField, __rotate_theRM6, TachoLimitField, __rotate_theAngle6, RunStateField, __rotate_theRS6, RegPValueField, __rotate_theRVP6, RegIValueField, __rotate_theRVI6, RegDValueField, __rotate_theRVD6, PowerField, __rotate_thePower6, TurnRatioField, __rotate_turnpct6, UpdateFlagsField, __rotate_theUF6 // Waits till angle reached index __rotate_firstPort6, __rotate_ports6, NA __rotate_Running6: getout __rotate_power6, __rotate_firstPort6, PowerField brtst EQ, __rotate_doneRunning6, __rotate_power6 getout __rotate_rs6, __rotate_firstPort6, RunStateField brcmp EQ, __rotate_Running6, __rotate_rs6, OUT_RUNSTATE_RUNNING __rotate_doneRunning6: brtst EQ, __rotate_Reset6, __rotate_stop6 // skip the speed regulation phase if __rotate_stop is false // Regulates for speed = 0 set __rotate_theOM6, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED set __rotate_theUF6, UF_UPDATE_TACHO_LIMIT+UF_UPDATE_SPEED+UF_UPDATE_MODE setout __rotate_ports6, OutputModeField, __rotate_theOM6, RegModeField, OUT_REGMODE_SPEED, RunStateField, __rotate_theRS6, PowerField, 0, TachoLimitField, 0, UpdateFlagsField, __rotate_theUF6 // Verifies that motor doesn't rotate for 50ms, else loops getout __rotate_RotCount6, __rotate_firstPort6, RotationCountField __rotate_Stabilize6: mov __rotate_OldRotCount6, __rotate_RotCount6 wait 50 // check rotation getout __rotate_RotCount6, __rotate_firstPort6, RotationCountField brcmp NEQ, __rotate_Stabilize6, __rotate_OldRotCount6, __rotate_RotCount6 set __rotate_theOM6, OUT_MODE_COAST+OUT_MODE_REGULATED setout __rotate_ports6, RegModeField, __rotate_theRM6, RunStateField, OUT_RUNSTATE_IDLE, OutputModeField, __rotate_theOM6, UpdateFlagsField, UF_UPDATE_MODE __rotate_Reset6: // maybe reset the block rotation count brtst EQ, __rotate_Done6, __rotate_theTurnPct6 setout __rotate_ports6, UpdateFlagsField, UF_UPDATE_RESET_BLOCK_COUNT __rotate_Done6: return ends subroutine __RotateMotorVar /* _ports should be an array but it might be an integer from 0..6 (OUT_A, OUT_B, OUT_C, OUT_AB, OUT_AC, OUT_BC, OUT_ABC) This subroutine converts, if necessary, an array containing a single byte > 2 into an array containing multiple bytes and then falls through to the RotateMotor6 subroutine. It uses __rotate_rs6 as a temporary variable */ arrsize __rotate_rs6, __rotate_ports6 // what is the size of the array? brcmp GT, __rmvCallSub, __rotate_rs6, 1 // fall through if size > 1 // only one element in the array. What is its value? index __rotate_rs6, __rotate_ports6, NA // grab the first element brcmp LT, __rmvCallSub, __rotate_rs6, 3 // if it is less than 3 just call the subroutine brcmp GT, __rmvExit, __rotate_rs6, 6 // if it is greater than 6 abort // start with 3 mov __rotate_ports6, __OUT_AB brcmp EQ, __rmvCallSub, __rotate_rs6, 3 mov __rotate_ports6, __OUT_AC brcmp EQ, __rmvCallSub, __rotate_rs6, 4 mov __rotate_ports6, __OUT_BC brcmp EQ, __rmvCallSub, __rotate_rs6, 5 mov __rotate_ports6, __OUT_ABC __rmvCallSub: call __RotateMotor6 __rmvExit: return ends dseg segment __SensorInvalidTmp byte dseg ends dseg segment __ResetSensorMutex mutex __ResetSensorPort byte __ResetSensorTmp byte dseg ends subroutine __ResetSensorSubroutine setin TRUE, __ResetSensorPort, InvalidDataField __SensorStillInvalid: getin __ResetSensorTmp, __ResetSensorPort, InvalidDataField brtst NEQ, __SensorStillInvalid, __ResetSensorTmp return ends #define __ResetSensor(_port) \ acquire __ResetSensorMutex \ mov __ResetSensorPort, _port \ call __ResetSensorSubroutine \ release __ResetSensorMutex #define __SetSensorTouch(_port) \ setin IN_TYPE_SWITCH, _port, TypeField \ setin IN_MODE_BOOLEAN, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorLight(_port) \ setin IN_TYPE_LIGHT_ACTIVE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorSound(_port) \ setin IN_TYPE_SOUND_DB, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorLowspeed(_port) \ setin IN_TYPE_LOWSPEED_9V, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #if __FIRMWARE_VERSION > 107 #define __SetSensorColorFull(_port) \ setin IN_TYPE_COLORFULL, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorColorRed(_port) \ setin IN_TYPE_COLORRED, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorColorGreen(_port) \ setin IN_TYPE_COLORGREEN, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorColorBlue(_port) \ setin IN_TYPE_COLORBLUE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorColorNone(_port) \ setin IN_TYPE_COLORNONE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #endif dseg segment // port 0 __CLSCSArgs0 TCommLSCheckStatus __CLSCSMutex0 mutex __CLSWArgs0 TCommLSWrite __CLSWMutex0 mutex __CLSRArgs0 TCommLSRead __CLSRMutex0 mutex // port 1 __CLSCSArgs1 TCommLSCheckStatus __CLSCSMutex1 mutex __CLSWArgs1 TCommLSWrite __CLSWMutex1 mutex __CLSRArgs1 TCommLSRead __CLSRMutex1 mutex // port 2 __CLSCSArgs2 TCommLSCheckStatus __CLSCSMutex2 mutex __CLSWArgs2 TCommLSWrite __CLSWMutex2 mutex __CLSRArgs2 TCommLSRead __CLSRMutex2 mutex // port 3 __CLSCSArgs3 TCommLSCheckStatus __CLSCSMutex3 mutex __CLSWArgs3 TCommLSWrite __CLSWMutex3 mutex __CLSRArgs3 TCommLSRead __CLSRMutex3 mutex dseg ends #define __lowspeedStatus(_port, _bready, _result) \ compif EQ, isconst(_port), FALSE \ acquire __CLSCSMutex0 \ acquire __CLSCSMutex1 \ acquire __CLSCSMutex2 \ acquire __CLSCSMutex3 \ mov __CLSCSArgs0.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs0 \ mov _bready, __CLSCSArgs0.BytesReady \ mov _result, __CLSCSArgs0.Result \ release __CLSCSMutex0 \ release __CLSCSMutex1 \ release __CLSCSMutex2 \ release __CLSCSMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSCSMutex##_port \ set __CLSCSArgs##_port.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs##_port \ mov _bready, __CLSCSArgs##_port.BytesReady \ mov _result, __CLSCSArgs##_port.Result \ release __CLSCSMutex##_port \ compend #define __lowspeedCheckStatus(_port, _result) \ compif EQ, isconst(_port), FALSE \ acquire __CLSCSMutex0 \ acquire __CLSCSMutex1 \ acquire __CLSCSMutex2 \ acquire __CLSCSMutex3 \ mov __CLSCSArgs0.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs0 \ mov _result, __CLSCSArgs0.Result \ release __CLSCSMutex0 \ release __CLSCSMutex1 \ release __CLSCSMutex2 \ release __CLSCSMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSCSMutex##_port \ set __CLSCSArgs##_port.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs##_port \ mov _result, __CLSCSArgs##_port.Result \ release __CLSCSMutex##_port \ compend #define __lowspeedBytesReady(_port, _bready) \ compif EQ, isconst(_port), FALSE \ acquire __CLSCSMutex0 \ acquire __CLSCSMutex1 \ acquire __CLSCSMutex2 \ acquire __CLSCSMutex3 \ mov __CLSCSArgs0.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs0 \ mov _bready, __CLSCSArgs0.BytesReady \ release __CLSCSMutex0 \ release __CLSCSMutex1 \ release __CLSCSMutex2 \ release __CLSCSMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSCSMutex##_port \ set __CLSCSArgs##_port.Port, _port \ syscall CommLSCheckStatus, __CLSCSArgs##_port \ mov _bready, __CLSCSArgs##_port.BytesReady \ release __CLSCSMutex##_port \ compend #define __lowspeedWrite(_port, _retlen, _buffer, _result) \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, _retlen \ mov __CLSWArgs0.Buffer, _buffer \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, _retlen \ mov __CLSWArgs##_port.Buffer, _buffer \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __lowspeedRead(_port, _buflen, _buffer, _result) \ compif EQ, isconst(_port), FALSE \ acquire __CLSRMutex0 \ acquire __CLSRMutex1 \ acquire __CLSRMutex2 \ acquire __CLSRMutex3 \ mov __CLSRArgs0.Port, _port \ mov __CLSRArgs0.BufferLen, _buflen \ syscall CommLSRead, __CLSRArgs0 \ mov _buffer, __CLSRArgs0.Buffer \ mov _result, __CLSRArgs0.Result \ release __CLSRMutex0 \ release __CLSRMutex1 \ release __CLSRMutex2 \ release __CLSRMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSRMutex##_port \ set __CLSRArgs##_port.Port, _port \ mov __CLSRArgs##_port.BufferLen, _buflen \ syscall CommLSRead, __CLSRArgs##_port \ mov _buffer, __CLSRArgs##_port.Buffer \ mov _result, __CLSRArgs##_port.Result \ release __CLSRMutex##_port \ compend dseg segment __TextOutMutex mutex __TextOutArgs TDrawText __BlankLine byte[] ' ' __NumOutMutex mutex __NumOutArgs TDrawText __PointOutArgs TDrawPoint __PointOutMutex mutex __LineOutArgs TDrawLine __LineOutMutex mutex __RectOutArgs TDrawRect __RectOutMutex mutex __CircleOutArgs TDrawCircle __CircleOutMutex mutex __GraphicOutArgs TDrawGraphic __GraphicOutMutex mutex __GraphicOutEmptyVars sdword[] dseg ends #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) dseg segment __GraphicArrayOutArgs TDrawGraphicArray __PolyOutArgs TDrawPolygon __PolyOutMutex mutex __EllipseOutArgs TDrawEllipse __EllipseOutMutex mutex __FontOutMutex mutex __FontOutArgs TDrawFont __MemMgrMutex mutex __MemMgrArgs TMemoryManager __ReadLastMutex mutex __ReadLastArgs TReadLastResponse dseg ends #endif #if __FIRMWARE_VERSION > 107 dseg segment __ColorSensorReadArgs TColorSensorRead __ColorSensorReadMutex mutex dseg ends #define __ReadSensorColorRaw(_port, _rawVals, _result) \ acquire __ColorSensorReadMutex \ mov __ColorSensorReadArgs.Port,_port \ syscall ColorSensorRead,__ColorSensorReadArgs \ mov _rawVals, __ColorSensorReadArgs.RawArray \ tst EQ, _result, __ColorSensorReadArgs.Result \ release __ColorSensorReadMutex #define __ReadSensorColorEx(_port, _colorval, _rawVals, _normVals, _scaledVals, _result) \ acquire __ColorSensorReadMutex \ mov __ColorSensorReadArgs.Port,_port \ syscall ColorSensorRead,__ColorSensorReadArgs \ mov _colorval, __ColorSensorReadArgs.ColorValue \ mov _rawVals, __ColorSensorReadArgs.RawArray \ mov _normVals, __ColorSensorReadArgs.NormalizedArray \ mov _scaledVals, __ColorSensorReadArgs.ScaledArray \ tst EQ, _result, __ColorSensorReadArgs.Result \ release __ColorSensorReadMutex #endif #define __OnFwdEx(_ports, _pwr, _reset) \ compif EQ, isconst(_ports), FALSE \ __onFwdExPIDAll(_ports, _pwr, _reset, PID_3, PID_1, PID_1) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdExPID##_ports(_pwr, _reset, PID_3, PID_1, PID_1) \ compend #define __OnRevEx(_ports, _pwr, _reset) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdEx(_ports, __OnRev_Tmp, _reset) \ release __OnRevMutex #define __OnFwdExPID(_ports, _pwr, _reset, _p, _i, _d) \ compif EQ, isconst(_ports), FALSE \ __onFwdExPIDAll(_ports, _pwr, _reset, _p, _i, _d) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdExPID##_ports(_pwr, _reset, _p, _i, _d) \ compend #define __OnRevExPID(_ports, _pwr, _reset, _p, _i, _d) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdExPID(_ports, __OnRev_Tmp, _reset, _p, _i, _d) \ release __OnRevMutex #define __CoastEx(_ports, _reset) \ compif EQ, isconst(_ports), FALSE \ __coastExAll(_ports, _reset) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __coastEx##_ports(_reset) \ compend #define __OffEx(_ports, _reset) \ compif EQ, isconst(_ports), FALSE \ __offExAll(_ports, _reset) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __offEx##_ports(_reset) \ compend #define __OnFwdRegEx(_ports, _pwr, _regmode, _reset) \ compif EQ, isconst(_ports), FALSE \ __onFwdRegExPIDAll(_ports, _pwr, _regmode, _reset, PID_3, PID_1, PID_1) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdRegExPID##_ports(_pwr, _regmode, _reset, PID_3, PID_1, PID_1) \ compend #define __OnRevRegEx(_ports, _pwr, _regmode, _reset) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdRegEx(_ports, __OnRev_Tmp, _regmode, _reset) \ release __OnRevMutex #define __OnFwdRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) \ compif EQ, isconst(_ports), FALSE \ __onFwdRegExPIDAll(_ports, _pwr, _regmode, _reset, _p, _i, _d) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdRegExPID##_ports(_pwr, _regmode, _reset, _p, _i, _d) \ compend #define __OnRevRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdRegExPID(_ports, __OnRev_Tmp, _regmode, _reset, _p, _i, _d) \ release __OnRevMutex #define __OnFwdSyncEx(_ports, _pwr, _turnpct, _reset) \ compif EQ, isconst(_ports), FALSE \ __onFwdSyncExPIDAll(_ports, _pwr, _turnpct, _reset, PID_3, PID_1, PID_1) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdSyncExPID##_ports(_pwr, _turnpct, _reset, PID_3, PID_1, PID_1) \ compend #define __OnRevSyncEx(_ports, _pwr, _turnpct, _reset) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdSyncEx(_ports, __OnRev_Tmp, _turnpct, _reset) \ release __OnRevMutex #define __OnFwdSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) \ compif EQ, isconst(_ports), FALSE \ __onFwdSyncExPIDAll(_ports, _pwr, _turnpct, _reset, _p, _i, _d) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __onFwdSyncExPID##_ports(_pwr, _turnpct, _reset, _p, _i, _d) \ compend #define __OnRevSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) \ acquire __OnRevMutex \ neg __OnRev_Tmp, _pwr \ __OnFwdSyncExPID(_ports, __OnRev_Tmp, _turnpct, _reset, _p, _i, _d) \ release __OnRevMutex #define __RotateMotorExPID(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ compif EQ, isconst(_ports), FALSE \ __rotateMotorExPIDVar(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ compelse \ compchk LT, _ports, 0x07 \ compchk GTEQ, _ports, 0x00 \ __rotateMotorExPID##_ports(_pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ compend #define __TextOutEx(_x,_y,_txt,_options) \ acquire __TextOutMutex \ mov __TextOutArgs.Location.X,_x \ mov __TextOutArgs.Location.Y,_y \ mov __TextOutArgs.Options,_options \ mov __TextOutArgs.Text,_txt \ syscall DrawText,__TextOutArgs \ release __TextOutMutex #define __NumOutEx(_x,_y,_num,_options) \ acquire __NumOutMutex \ mov __NumOutArgs.Location.X,_x \ mov __NumOutArgs.Location.Y,_y \ mov __NumOutArgs.Options,_options \ numtostr __NumOutArgs.Text,_num \ syscall DrawText,__NumOutArgs \ release __NumOutMutex #define __PointOutEx(_x,_y,_options) \ acquire __PointOutMutex \ mov __PointOutArgs.Location.X,_x \ mov __PointOutArgs.Location.Y,_y \ mov __PointOutArgs.Options,_options \ syscall DrawPoint,__PointOutArgs \ release __PointOutMutex #define __LineOutEx(_x1,_y1,_x2,_y2,_options) \ acquire __LineOutMutex \ mov __LineOutArgs.StartLoc.X,_x1 \ mov __LineOutArgs.StartLoc.Y,_y1 \ mov __LineOutArgs.EndLoc.X,_x2 \ mov __LineOutArgs.EndLoc.Y,_y2 \ mov __LineOutArgs.Options,_options \ syscall DrawLine,__LineOutArgs \ release __LineOutMutex #define __RectOutEx(_x,_y,_w,_h,_options) \ acquire __RectOutMutex \ mov __RectOutArgs.Location.X,_x \ mov __RectOutArgs.Location.Y,_y \ mov __RectOutArgs.Size.Width,_w \ mov __RectOutArgs.Size.Height,_h \ mov __RectOutArgs.Options,_options \ syscall DrawRect,__RectOutArgs \ release __RectOutMutex #define __CircleOutEx(_x,_y,_r,_options) \ acquire __CircleOutMutex \ mov __CircleOutArgs.Center.X,_x \ mov __CircleOutArgs.Center.Y,_y \ mov __CircleOutArgs.Size,_r \ mov __CircleOutArgs.Options,_options \ syscall DrawCircle,__CircleOutArgs \ release __CircleOutMutex #define __GraphicOutEx(_x,_y,_file,_vars,_options) \ acquire __GraphicOutMutex \ mov __GraphicOutArgs.Location.X,_x \ mov __GraphicOutArgs.Location.Y,_y \ mov __GraphicOutArgs.Filename,_file \ mov __GraphicOutArgs.Variables,_vars \ mov __GraphicOutArgs.Options,_options \ syscall DrawGraphic,__GraphicOutArgs \ release __GraphicOutMutex #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define __GraphicArrayOutEx(_x,_y,_data,_vars,_options) \ acquire __GraphicOutMutex \ mov __GraphicArrayOutArgs.Location.X,_x \ mov __GraphicArrayOutArgs.Location.Y,_y \ mov __GraphicArrayOutArgs.Data,_data \ mov __GraphicArrayOutArgs.Variables,_vars \ mov __GraphicArrayOutArgs.Options,_options \ syscall DrawGraphicArray,__GraphicArrayOutArgs \ release __GraphicOutMutex #define __PolyOutEx(_points,_options) \ acquire __PolyOutMutex \ mov __PolyOutArgs.Points,_points \ mov __PolyOutArgs.Options,_options \ syscall DrawPolygon,__PolyOutArgs \ release __PolyOutMutex #define __EllipseOutEx(_x,_y,_rX,_rY,_options) \ acquire __EllipseOutMutex \ mov __EllipseOutArgs.Center.X,_x \ mov __EllipseOutArgs.Center.Y,_y \ mov __EllipseOutArgs.SizeX,_rX \ mov __EllipseOutArgs.SizeY,_rY \ mov __EllipseOutArgs.Options,_options \ syscall DrawEllipse,__EllipseOutArgs \ release __EllipseOutMutex #define __FontTextOutEx(_x,_y,_fnt,_txt,_options) \ acquire __FontOutMutex \ mov __FontOutArgs.Location.X,_x \ mov __FontOutArgs.Location.Y,_y \ mov __FontOutArgs.Options,_options \ mov __FontOutArgs.Filename,_fnt \ mov __FontOutArgs.Text,_txt \ syscall DrawFont,__FontOutArgs \ release __FontOutMutex #define __FontNumOutEx(_x,_y,_fnt,_num,_options) \ acquire __FontOutMutex \ mov __FontOutArgs.Location.X,_x \ mov __FontOutArgs.Location.Y,_y \ mov __FontOutArgs.Options,_options \ mov __FontOutArgs.Filename,_fnt \ numtostr __FontOutArgs.Text,_num \ syscall DrawFont,__FontOutArgs \ release __FontOutMutex #define __GetMemoryInfo(_Compact,_PoolSize,_DataspaceSize,_Result) \ acquire __MemMgrMutex \ mov __MemMgrArgs.Compact,_Compact \ syscall MemoryManager,__MemMgrArgs \ mov _PoolSize, __MemMgrArgs.PoolSize \ mov _DataspaceSize, __MemMgrArgs.DataspaceSize \ mov _Result, __MemMgrArgs.Result \ release __MemMgrMutex #define __GetLastResponseInfo(_Clear,_Length,_Command,_Buffer,_Result) \ acquire __ReadLastMutex \ mov __ReadLastArgs.Clear,_Clear \ syscall ReadLastResponse,__ReadLastArgs \ mov _Buffer, __ReadLastArgs.Buffer \ mov _Length, __ReadLastArgs.Length \ mov _Command, __ReadLastArgs.Command \ mov _Result, __ReadLastArgs.Result \ release __ReadLastMutex #endif dseg segment __RLSBbufLSWrite1 byte[] 0x02, 0x42 __RSEMeterLSBuf byte[] 0x04, 0x0A __RSTempConfigLSBuf byte[] 0x98, 0x01, 0x60 __RSTempLSBuf byte[] 0x98, 0x00 __RSTempRaw slong dseg ends #define __ReadI2CBytes(_port, _inbuf, _count, _outbuf, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, _inbuf \ mov __RLSBytesCountVar, _count \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ mov _count, __RLSBytesCountVar \ mov _outbuf, __RLSReadBufVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, _inbuf \ mov __RLSBytesCount##_port, _count \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ mov _count, __RLSBytesCount##_port \ mov _outbuf, __RLSReadBuf##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorUS(_port, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 1 \ wait 15 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 1 \ wait 15 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __ReadSensorUSEx(_port, _values, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 8 \ wait 15 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ mov _values, __RLSReadBufVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 8 \ wait 15 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ mov _values, __RLSReadBuf##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorEMeter(_port, _vIn, _aIn, _vOut, _aOut, _joules, _wIn, _wOut, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RSEMeterLSBuf \ set __RLSBytesCountVar, 14 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index __RLSBytesCountVar, __RLSReadBufVar, NA \ index _vIn, __RLSReadBufVar, 1 \ mul _vIn, _vIn, 256 \ add _vIn, _vIn, __RLSBytesCountVar \ div _vIn, _vIn, 1000 \ index __RLSBytesCountVar, __RLSReadBufVar, 2 \ index _aIn, __RLSReadBufVar, 3 \ mul _aIn, _aIn, 256 \ add _aIn, _aIn, __RLSBytesCountVar \ div _aIn, _aIn, 1000 \ index __RLSBytesCountVar, __RLSReadBufVar, 4 \ index _vOut, __RLSReadBufVar, 5 \ mul _vOut, _vOut, 256 \ add _vOut, _vOut, __RLSBytesCountVar \ div _vOut, _vOut, 1000 \ index __RLSBytesCountVar, __RLSReadBufVar, 6 \ index _aOut, __RLSReadBufVar, 7 \ mul _aOut, _aOut, 256 \ add _aOut, _aOut, __RLSBytesCountVar \ div _aOut, _aOut, 1000 \ index __RLSBytesCountVar, __RLSReadBufVar, 8 \ index _joules, __RLSReadBufVar, 9 \ mul _joules, _joules, 256 \ add _joules, _joules, __RLSBytesCountVar \ index __RLSBytesCountVar, __RLSReadBufVar, 10 \ index _wIn, __RLSReadBufVar, 11 \ mul _wIn, _wIn, 256 \ add _wIn, _wIn, __RLSBytesCountVar \ div _wIn, _wIn, 1000 \ index __RLSBytesCountVar, __RLSReadBufVar, 12 \ index _wOut, __RLSReadBufVar, 13 \ mul _wOut, _wOut, 256 \ add _wOut, _wOut, __RLSBytesCountVar \ div _wOut, _wOut, 1000 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RSEMeterLSBuf \ set __RLSBytesCount##_port, 14 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index __RLSBytesCount##_port, __RLSReadBuf##_port, NA \ index _vIn, __RLSReadBuf##_port, 1 \ mul _vIn, _vIn, 256 \ add _vIn, _vIn, __RLSBytesCount##_port \ div _vIn, _vIn, 1000 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 2 \ index _aIn, __RLSReadBuf##_port, 3 \ mul _aIn, _aIn, 256 \ add _aIn, _aIn, __RLSBytesCount##_port \ div _aIn, _aIn, 1000 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 4 \ index _vOut, __RLSReadBuf##_port, 5 \ mul _vOut, _vOut, 256 \ add _vOut, _vOut, __RLSBytesCount##_port \ div _vOut, _vOut, 1000 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 6 \ index _aOut, __RLSReadBuf##_port, 7 \ mul _aOut, _aOut, 256 \ add _aOut, _aOut, __RLSBytesCount##_port \ div _aOut, _aOut, 1000 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 8 \ index _joules, __RLSReadBuf##_port, 9 \ mul _joules, _joules, 256 \ add _joules, _joules, __RLSBytesCount##_port \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 10 \ index _wIn, __RLSReadBuf##_port, 11 \ mul _wIn, _wIn, 256 \ add _wIn, _wIn, __RLSBytesCount##_port \ div _wIn, _wIn, 1000 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 12 \ index _wOut, __RLSReadBuf##_port, 13 \ mul _wOut, _wOut, 256 \ add _wOut, _wOut, __RLSBytesCount##_port \ div _wOut, _wOut, 1000 \ release __RLSBmutex##_port \ compend #define __ReadSensorTemperature(_port, _temp) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RSTempLSBuf \ set __RLSBytesCountVar, 2 \ call __ReadLSBytesVar \ index __RSTempRaw, __RLSReadBufVar, NA \ index __RLSBytesCountVar, __RLSReadBufVar, 1 \ mul __RSTempRaw, __RSTempRaw, 256 \ add __RSTempRaw, __RSTempRaw, __RLSBytesCountVar \ mul __RSTempRaw, __RSTempRaw, 10 \ div __RSTempRaw, __RSTempRaw, 16 \ div _temp, __RSTempRaw, 16 \ brcmp LTEQ, __RRT_EndIf##__I__, __RSTempRaw, 20470 \ sub _temp, _temp, 2560 \ __RRT_EndIf##__I__: \ __IncI__ \ compif EQ, typeof(_temp), 10 \ div _temp, _temp, 10 \ compend \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RSTempLSBuf \ set __RLSBytesCount##_port, 2 \ call __ReadLSBytes##_port \ index __RSTempRaw, __RLSReadBuf##_port, NA \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 1 \ mul __RSTempRaw, __RSTempRaw, 256 \ add __RSTempRaw, __RSTempRaw, __RLSBytesCount##_port \ mul __RSTempRaw, __RSTempRaw, 10 \ div __RSTempRaw, __RSTempRaw, 16 \ div _temp, __RSTempRaw, 16 \ brcmp LTEQ, __RRT_EndIf##__I__, __RSTempRaw, 20470 \ sub _temp, _temp, 2560 \ __RRT_EndIf##__I__: \ __IncI__ \ compif EQ, typeof(_temp), 10 \ div _temp, _temp, 10 \ compend \ release __RLSBmutex##_port \ compend subroutine __ReadLSBytes0 dseg segment __RLSBmutex0 mutex __RLSLastGoodRead0 byte[] 0x00 __RLSBResult0 sbyte __RLSBytesCount0 byte __RLSBIterations0 byte __RLSReadBuf0 byte[] dseg ends __lowspeedWrite(0, __RLSBytesCount0, __RLSReadBuf0, __RLSBResult0) brtst EQ, __RLSBReturn0, __RLSBytesCount0 // terminate if zero bytes to read arrinit __RLSReadBuf0, 0, __RLSBytesCount0 brtst NEQ, __RLSBError0, __RLSBResult0 // terminate if not NO_ERR set __RLSBIterations0, 4 __RLSBDoCheckStatus0: __lowspeedStatus(0, __RLSBytesCount0, __RLSBResult0) sub __RLSBIterations0, __RLSBIterations0, 1 brtst LTEQ, __RLSBError0, __RLSBIterations0 brtst LT, __RLSBError0, __RLSBResult0 // negative results are absolute errors brtst EQ, __RLSBReadyToRead0, __RLSBResult0 // if STAT_COMM_PENDING then wait a bit and then try again (up to 4 times) wait 15 jmp __RLSBDoCheckStatus0 __RLSBReadyToRead0: // Try reading now __lowspeedRead(0, __RLSBytesCount0, __RLSReadBuf0, __RLSBResult0) brtst NEQ, __RLSBError0, __RLSBResult0 // terminate if not NO_ERR mov __RLSLastGoodRead0, __RLSReadBuf0 jmp __RLSBDone0 __RLSBError0: mov __RLSReadBuf0, __RLSLastGoodRead0 __RLSBDone0: arrsize __RLSBytesCount0, __RLSReadBuf0 __RLSBReturn0: return ends subroutine __ReadLSBytes1 dseg segment __RLSBmutex1 mutex __RLSLastGoodRead1 byte[] 0x00 __RLSBResult1 sbyte __RLSBytesCount1 byte __RLSBIterations1 byte __RLSReadBuf1 byte[] dseg ends __lowspeedWrite(1, __RLSBytesCount1, __RLSReadBuf1, __RLSBResult1) brtst EQ, __RLSBReturn1, __RLSBytesCount1 // terminate if zero bytes to read arrinit __RLSReadBuf1, 0, __RLSBytesCount1 brtst NEQ, __RLSBError1, __RLSBResult1 // terminate if not NO_ERR set __RLSBIterations1, 4 __RLSBDoCheckStatus1: __lowspeedStatus(1, __RLSBytesCount1, __RLSBResult1) sub __RLSBIterations1, __RLSBIterations1, 1 brtst LTEQ, __RLSBError1, __RLSBIterations1 brtst LT, __RLSBError1, __RLSBResult1 // negative results are absolute errors brtst EQ, __RLSBReadyToRead1, __RLSBResult1 // if STAT_COMM_PENDING then wait a bit and then try again (up to 4 times) wait 15 jmp __RLSBDoCheckStatus1 __RLSBReadyToRead1: // Try reading now __lowspeedRead(1, __RLSBytesCount1, __RLSReadBuf1, __RLSBResult1) brtst NEQ, __RLSBError1, __RLSBResult1 // terminate if not NO_ERR mov __RLSLastGoodRead1, __RLSReadBuf1 jmp __RLSBDone1 __RLSBError1: mov __RLSReadBuf1, __RLSLastGoodRead1 __RLSBDone1: arrsize __RLSBytesCount1, __RLSReadBuf1 __RLSBReturn1: return ends subroutine __ReadLSBytes2 dseg segment __RLSBmutex2 mutex __RLSLastGoodRead2 byte[] 0x00 __RLSBResult2 sbyte __RLSBytesCount2 byte __RLSBIterations2 byte __RLSReadBuf2 byte[] dseg ends __lowspeedWrite(2, __RLSBytesCount2, __RLSReadBuf2, __RLSBResult2) brtst EQ, __RLSBReturn2, __RLSBytesCount2 // terminate if zero bytes to read arrinit __RLSReadBuf2, 0, __RLSBytesCount2 brtst NEQ, __RLSBError2, __RLSBResult2 // terminate if not NO_ERR set __RLSBIterations2, 4 __RLSBDoCheckStatus2: __lowspeedStatus(2, __RLSBytesCount2, __RLSBResult2) sub __RLSBIterations2, __RLSBIterations2, 1 brtst LTEQ, __RLSBError2, __RLSBIterations2 brtst LT, __RLSBError2, __RLSBResult2 // negative results are absolute errors brtst EQ, __RLSBReadyToRead2, __RLSBResult2 // if STAT_COMM_PENDING then wait a bit and then try again (up to 4 times) wait 15 jmp __RLSBDoCheckStatus2 __RLSBReadyToRead2: // Try reading now __lowspeedRead(2, __RLSBytesCount2, __RLSReadBuf2, __RLSBResult2) brtst NEQ, __RLSBError2, __RLSBResult2 // terminate if not NO_ERR mov __RLSLastGoodRead2, __RLSReadBuf2 jmp __RLSBDone2 __RLSBError2: mov __RLSReadBuf2, __RLSLastGoodRead2 __RLSBDone2: arrsize __RLSBytesCount2, __RLSReadBuf2 __RLSBReturn2: return ends subroutine __ReadLSBytes3 dseg segment __RLSBmutex3 mutex __RLSLastGoodRead3 byte[] 0x00 __RLSBResult3 sbyte __RLSBytesCount3 byte __RLSBIterations3 byte __RLSReadBuf3 byte[] dseg ends __lowspeedWrite(3, __RLSBytesCount3, __RLSReadBuf3, __RLSBResult3) brtst EQ, __RLSBReturn3, __RLSBytesCount3 // terminate if zero bytes to read arrinit __RLSReadBuf3, 0, __RLSBytesCount3 brtst NEQ, __RLSBError3, __RLSBResult3 // terminate if not NO_ERR set __RLSBIterations3, 4 __RLSBDoCheckStatus3: __lowspeedStatus(3, __RLSBytesCount3, __RLSBResult3) sub __RLSBIterations3, __RLSBIterations3, 1 brtst LTEQ, __RLSBError3, __RLSBIterations3 brtst LT, __RLSBError3, __RLSBResult3 // negative results are absolute errors brtst EQ, __RLSBReadyToRead3, __RLSBResult3 // if STAT_COMM_PENDING then wait a bit and then try again (up to 4 times) wait 15 jmp __RLSBDoCheckStatus3 __RLSBReadyToRead3: // Try reading now __lowspeedRead(3, __RLSBytesCount3, __RLSReadBuf3, __RLSBResult3) brtst NEQ, __RLSBError3, __RLSBResult3 // terminate if not NO_ERR mov __RLSLastGoodRead3, __RLSReadBuf3 jmp __RLSBDone3 __RLSBError3: mov __RLSReadBuf3, __RLSLastGoodRead3 __RLSBDone3: arrsize __RLSBytesCount3, __RLSReadBuf3 __RLSBReturn3: return ends subroutine __ReadLSBytesVar dseg segment __RLSLastGoodReadVar byte[] 0x00 __RLSBResultVar sbyte __RLSBytesCountVar byte __RLSBIterationsVar byte __RLSReadBufVar byte[] __RLSReadPort byte dseg ends __lowspeedWrite(__RLSReadPort, __RLSBytesCountVar, __RLSReadBufVar, __RLSBResultVar) brtst EQ, __RLSBReturnVar, __RLSBytesCountVar // terminate if zero bytes to read arrinit __RLSReadBufVar, 0, __RLSBytesCountVar brtst NEQ, __RLSBErrorVar, __RLSBResultVar // terminate if not NO_ERR set __RLSBIterationsVar, 4 __RLSBDoCheckStatusVar: __lowspeedStatus(__RLSReadPort, __RLSBytesCountVar, __RLSBResultVar) sub __RLSBIterationsVar, __RLSBIterationsVar, 1 brtst LTEQ, __RLSBErrorVar, __RLSBIterationsVar brtst LT, __RLSBErrorVar, __RLSBResultVar // negative results are absolute errors brtst EQ, __RLSBReadyToReadVar, __RLSBResultVar // if STAT_COMM_PENDING then wait a bit and then try again (up to 4 times) wait 15 jmp __RLSBDoCheckStatusVar __RLSBReadyToReadVar: // Try reading now __lowspeedRead(__RLSReadPort, __RLSBytesCountVar, __RLSReadBufVar, __RLSBResultVar) brtst NEQ, __RLSBErrorVar, __RLSBResultVar // terminate if not NO_ERR mov __RLSLastGoodReadVar, __RLSReadBufVar jmp __RLSBDoneVar __RLSBErrorVar: mov __RLSReadBufVar, __RLSLastGoodReadVar __RLSBDoneVar: arrsize __RLSBytesCountVar, __RLSReadBufVar __RLSBReturnVar: return ends dseg segment __PlayToneTmp TSoundPlayTone __PlayFileTmp TSoundPlayFile __PlayFileMutex mutex __PlayToneMutex mutex __SGSMutex mutex __SGSArgs TSoundGetState __SSSMutex mutex __SSSArgs TSoundSetState __RandomTmp dword __RandomArgs TRandomNumber __RandomMutex mutex __KeepAliveArgs TKeepAlive __KeepAliveMutex mutex __GSTArgs TGetStartTick __GSTMutex mutex __RBtnMutex mutex __RBtnArgs TReadButton __IOMRMutex mutex __IOMRArgs TIOMapRead __IOMRUnflattenErr byte __IOMRUnflattenBuf byte[] dseg ends #define __PlayToneEx(_freq,_dur,_vol,_loop) \ acquire __PlayToneMutex \ mov __PlayToneTmp.Frequency, _freq \ mov __PlayToneTmp.Duration, _dur \ mov __PlayToneTmp.Volume, _vol \ mov __PlayToneTmp.Loop, _loop \ syscall SoundPlayTone, __PlayToneTmp \ release __PlayToneMutex #define __PlayFileEx(_file,_vol,_loop) \ acquire __PlayFileMutex \ mov __PlayFileTmp.Filename, _file \ mov __PlayFileTmp.Volume, _vol \ mov __PlayFileTmp.Loop, _loop \ syscall SoundPlayFile, __PlayFileTmp \ release __PlayFileMutex #define __setSoundState(_state, _flags, _result) \ acquire __SSSMutex \ mov __SSSArgs.State, _state \ mov __SSSArgs.Flags, _flags \ syscall SoundSetState, __SSSArgs \ mov _result, __SSSArgs.Result \ release __SSSMutex #define __GetSoundState(_state, _flags) \ acquire __SGSMutex \ syscall SoundGetState, __SGSArgs \ mov _state, __SGSArgs.State \ mov _flags, __SGSArgs.Flags \ release __SGSMutex #define __Random(_arg,_max) \ acquire __RandomMutex \ syscall RandomNumber, __RandomArgs \ mov __RandomTmp, __RandomArgs.Result \ add __RandomTmp, __RandomTmp, 32768 \ mul __RandomTmp, __RandomTmp, _max \ div __RandomTmp, __RandomTmp, 65536 \ mov _arg, __RandomTmp \ release __RandomMutex #define __SignedRandom(_arg) \ acquire __RandomMutex \ syscall RandomNumber, __RandomArgs \ mov _arg, __RandomArgs.Result \ release __RandomMutex #define __GetFirstTick(_value) \ compchk EQ, sizeof(_value), 4 \ acquire __GSTMutex \ syscall GetStartTick, __GSTArgs \ mov _value, __GSTArgs.Result \ release __GSTMutex #define __ReadButtonEx(_idx, _reset, _pressed, _count, _result) \ acquire __RBtnMutex \ mov __RBtnArgs.Index, _idx \ mov __RBtnArgs.Reset, _reset \ syscall ReadButton, __RBtnArgs \ mov _pressed, __RBtnArgs.Pressed \ mov _count, __RBtnArgs.Count \ mov _result, __RBtnArgs.Result \ release __RBtnMutex #define __getIOMapBytes(_modName, _offset, _cnt, _arrOut) \ acquire __IOMRMutex \ mov __IOMRArgs.ModuleName, _modName \ mov __IOMRArgs.Offset, _offset \ mov __IOMRArgs.Count, _cnt \ syscall IOMapRead, __IOMRArgs \ mov _arrOut, __IOMRArgs.Buffer \ release __IOMRMutex #define __getIOMapValue(_modName, _offset, _n) \ acquire __IOMRMutex \ mov __IOMRArgs.ModuleName, _modName \ mov __IOMRArgs.Offset, _offset \ set __IOMRArgs.Count, sizeof(_n) \ syscall IOMapRead, __IOMRArgs \ arrtostr __IOMRUnflattenBuf, __IOMRArgs.Buffer \ unflatten _n, __IOMRUnflattenErr, __IOMRUnflattenBuf, _n \ release __IOMRMutex #ifdef __ENHANCED_FIRMWARE dseg segment __IOMRBIArgs TIOMapReadByID dseg ends #define __getIOMapBytesByID(_modID, _offset, _cnt, _arrOut) \ acquire __IOMRMutex \ mov __IOMRBIArgs.ModuleID, _modID \ mov __IOMRBIArgs.Offset, _offset \ mov __IOMRBIArgs.Count, _cnt \ syscall IOMapReadByID, __IOMRBIArgs \ mov _arrOut, __IOMRBIArgs.Buffer \ release __IOMRMutex #define __getIOMapValueByID(_modID, _offset, _n) \ acquire __IOMRMutex \ mov __IOMRBIArgs.ModuleID, _modID \ mov __IOMRBIArgs.Offset, _offset \ set __IOMRBIArgs.Count, sizeof(_n) \ syscall IOMapReadByID, __IOMRBIArgs \ arrtostr __IOMRUnflattenBuf, __IOMRBIArgs.Buffer \ unflatten _n, __IOMRUnflattenErr, __IOMRUnflattenBuf, _n \ release __IOMRMutex #define __getLowSpeedModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytesByID(LowSpeedModuleID, _offset, _cnt, _arrOut) #define __getDisplayModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytesByID(DisplayModuleID, _offset, _cnt, _arrOut) #define __getCommModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytesByID(CommModuleID, _offset, _cnt, _arrOut) #define __getCommandModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytesByID(CommandModuleID, _offset, _cnt, _arrOut) #else #define __getLowSpeedModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytes(LowSpeedModuleName, _offset, _cnt, _arrOut) #define __getDisplayModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytes(DisplayModuleName, _offset, _cnt, _arrOut) #define __getCommModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytes(CommModuleName, _offset, _cnt, _arrOut) #define __getCommandModuleBytes(_offset, _cnt, _arrOut) __getIOMapBytes(CommandModuleName, _offset, _cnt, _arrOut) #endif #define __GetFreeMemory(_value) \ compchk EQ, sizeof(_value), 4 \ GetLoaderModuleValue(LoaderOffsetFreeUserFlash, _value) #define __GetSoundFrequency(_n) \ compchk EQ, sizeof(_n), 2 \ GetSoundModuleValue(SoundOffsetFreq, _n) #define __GetSoundDuration(_n) \ compchk EQ, sizeof(_n), 2 \ GetSoundModuleValue(SoundOffsetDuration, _n) #define __GetSoundSampleRate(_n) \ compchk EQ, sizeof(_n), 2 \ GetSoundModuleValue(SoundOffsetSampleRate, _n) #define __GetSoundMode(_n) \ compchk EQ, sizeof(_n), 1 \ GetSoundModuleValue(SoundOffsetMode, _n) #define __GetSoundVolume(_n) \ compchk EQ, sizeof(_n), 1 \ GetSoundModuleValue(SoundOffsetVolume, _n) dseg segment __btnModuleOffsetMutex mutex __btnModuleOffset word dseg ends #define __GetButtonPressCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetPressedCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetButtonLongPressCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetLongPressCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 1 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetButtonShortReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetShortRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 2 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetButtonLongReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetLongRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 3 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetButtonReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 4 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetButtonState(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ GetButtonModuleValue(ButtonOffsetState(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ add __btnModuleOffset, _b, 32 \ GetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __GetBatteryLevel(_n) \ compchk EQ, sizeof(_n), 2 \ GetUIModuleValue(UIOffsetBatteryVoltage, _n) #define __GetCommandFlags(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetFlags, _n) #define __GetUIState(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetState, _n) #define __GetUIButton(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetButton, _n) #define __GetVMRunState(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetRunState, _n) #define __GetBatteryState(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetBatteryState, _n) #define __GetBluetoothState(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetBluetoothState, _n) #define __GetUsbState(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetUsbState, _n) #define __GetSleepTimeout(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetSleepTimeout, _n) #define __GetSleepTimer(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetSleepTimer, _n) #define __GetRechargeableBattery(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetRechargeable, _n) #define __GetVolume(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetVolume, _n) #define __GetOnBrickProgramPointer(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetOBPPointer, _n) #define __GetAbortFlag(_n) \ compchk EQ, sizeof(_n), 1 \ GetUIModuleValue(UIOffsetAbortFlag, _n) dseg segment __inputModuleOffsetMutex mutex __inputModuleOffset word __inputModuleOffsetTmp word dseg ends #define __GetInCustomZeroOffset(_p, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetCustomZeroOffset(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInSensorBoolean(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetSensorBoolean(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 10 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInDigiPinsDirection(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetDigiPinsDir(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 11 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInDigiPinsStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetDigiPinsIn(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 12 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInDigiPinsOutputLevel(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetDigiPinsOut(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 13 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInCustomPercentFullScale(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetCustomPctFullScale(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 14 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInCustomActiveStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetCustomActiveStatus(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 15 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #if __FIRMWARE_VERSION > 107 #define __GetInColorCalibration(_p, _np, _nc, _n) \ compchk EQ, sizeof(_n), 4 \ compif EQ, isconst(_p+_np+_nc), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _np, INPUT_NO_OF_POINTS \ compchk GTEQ, _np, 0x00 \ compchk LT, _nc, INPUT_NO_OF_COLORS \ compchk GTEQ, _nc, 0x00 \ GetInputModuleValue(InputOffsetColorCalibration(_p, _np, _nc), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _np, 16 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ mul __inputModuleOffsetTmp, _nc, 4 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 80 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorCalLimits(_p, _np, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p+_np), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _np, 0x02 \ compchk GTEQ, _np, 0x00 \ GetInputModuleValue(InputOffsetColorCalLimits(_p, _np), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _np, 2 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 128 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorADRaw(_p, _nc, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p+_nc), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _nc, INPUT_NO_OF_COLORS \ compchk GTEQ, _nc, 0x00 \ GetInputModuleValue(InputOffsetColorADRaw(_p, _nc), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _nc, 2 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 132 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorSensorRaw(_p, _nc, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p+_nc), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _nc, INPUT_NO_OF_COLORS \ compchk GTEQ, _nc, 0x00 \ GetInputModuleValue(InputOffsetColorSensorRaw(_p, _nc), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _nc, 2 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 140 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorSensorValue(_p, _nc, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p+_nc), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _nc, INPUT_NO_OF_COLORS \ compchk GTEQ, _nc, 0x00 \ GetInputModuleValue(InputOffsetColorSensorValue(_p, _nc), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _nc, 2 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 148 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorBoolean(_p, _nc, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p+_nc), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ compchk LT, _nc, INPUT_NO_OF_COLORS \ compchk GTEQ, _nc, 0x00 \ GetInputModuleValue(InputOffsetColorBoolean(_p, _nc), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ mul __inputModuleOffsetTmp, _nc, 2 \ add __inputModuleOffset, __inputModuleOffset, __inputModuleOffsetTmp \ add __inputModuleOffset, __inputModuleOffset, 156 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __GetInColorCalibrationState(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetInputModuleValue(InputOffsetColorCalibrationState(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 84 \ add __inputModuleOffset, __inputModuleOffset, 160 \ GetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #endif #define __GetOutPwnFreq(_n) \ compchk EQ, sizeof(_n), 1 \ GetOutputModuleValue(OutputOffsetRegulationTime, _n) #define __GetOutRegulationTime(_n) \ compchk EQ, sizeof(_n), 1 \ GetOutputModuleValue(OutputOffsetRegulationTime, _n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define __GetOutRegulationOptions(_n) \ compchk EQ, sizeof(_n), 1 \ GetOutputModuleValue(OutputOffsetRegulationOptions, _n) #endif dseg segment __lsModuleOffsetMutex mutex __lsModuleOffset word dseg ends #define __getLSInputBuffer(_p, _offset, _cnt, _data) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleBytes(LowSpeedOffsetInBufBuf(_p)+_offset, _cnt, _data) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, _offset \ GetLowSpeedModuleBytes(__lsModuleOffset, _cnt, _data) \ release __lsModuleOffsetMutex \ compend #define __GetLSInputBufferInPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetInBufInPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 16 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSInputBufferOutPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetInBufOutPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 17 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSInputBufferBytesToRx(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetInBufBytesToRx(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 18 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __getLSOutputBuffer(_p, _offset, _cnt, _data) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleBytes(LowSpeedOffsetOutBufBuf(_p)+_offset, _cnt, _data) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 76 \ add __lsModuleOffset, __lsModuleOffset, _offset \ GetLowSpeedModuleBytes(__lsModuleOffset, _cnt, _data) \ release __lsModuleOffsetMutex \ compend #define __GetLSOutputBufferInPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetOutBufInPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 92 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSOutputBufferOutPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetOutBufOutPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 93 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSOutputBufferBytesToRx(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetOutBufBytesToRx(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 94 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSMode(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetMode(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 152 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSChannelState(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetChannelState(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 156 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSErrorType(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetLowSpeedModuleValue(LowSpeedOffsetErrorType(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 160 \ GetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __GetLSState(_n) \ compchk EQ, sizeof(_n), 1 \ GetLowSpeedModuleValue(LowSpeedOffsetState, _n) #define __GetLSSpeed(_n) \ compchk EQ, sizeof(_n), 1 \ GetLowSpeedModuleValue(LowSpeedOffsetSpeed, _n) #ifdef __ENHANCED_FIRMWARE #define __GetLSNoRestartOnRead(_n) \ compchk EQ, sizeof(_n), 1 \ GetLowSpeedModuleValue(LowSpeedOffsetNoRestartOnRead, _n) #endif #define __GetDisplayEraseMask(_n) \ compchk EQ, sizeof(_n), 4 \ GetDisplayModuleValue(DisplayOffsetEraseMask, _n) #define __GetDisplayUpdateMask(_n) \ compchk EQ, sizeof(_n), 4 \ GetDisplayModuleValue(DisplayOffsetUpdateMask, _n) #define __GetDisplayFont(_n) \ compchk EQ, sizeof(_n), 4 \ GetDisplayModuleValue(DisplayOffsetPFont, _n) #define __GetDisplayDisplay(_n) \ compchk EQ, sizeof(_n), 4 \ GetDisplayModuleValue(DisplayOffsetDisplay, _n) #define __GetDisplayFlags(_n) \ compchk EQ, sizeof(_n), 1 \ GetDisplayModuleValue(DisplayOffsetFlags, _n) #define __GetDisplayTextLinesCenterFlags(_n) \ compchk EQ, sizeof(_n), 1 \ GetDisplayModuleValue(DisplayOffsetTextLinesCenterFlags, _n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define __GetDisplayContrast(_n) \ compchk EQ, sizeof(_n), 1 \ GetDisplayModuleValue(DisplayOffsetContrast, _n) #endif dseg segment __displayModuleOffsetMutex mutex __displayModuleOffset word dseg ends #define __getDisplayNormal(_x, _line, _cnt, _data) \ compif EQ, isconst(_line+_x), TRUE \ compchk LT, _line, 0x08 \ compchk GTEQ, _line, 0x00 \ GetDisplayModuleBytes(DisplayOffsetNormal(_line,_x), _cnt, _data) \ compelse \ acquire __displayModuleOffsetMutex \ mul __displayModuleOffset, _line, 100 \ add __displayModuleOffset, __displayModuleOffset, _x \ add __displayModuleOffset, __displayModuleOffset, 119 \ GetDisplayModuleBytes(__displayModuleOffset, _cnt, _data) \ release __displayModuleOffsetMutex \ compend #define __getDisplayPopup(_x, _line, _cnt, _data) \ compif EQ, isconst(_line+_x), TRUE \ compchk LT, _line, 0x08 \ compchk GTEQ, _line, 0x00 \ GetDisplayModuleBytes(DisplayOffsetPopup(_line,_x), _cnt, _data) \ compelse \ acquire __displayModuleOffsetMutex \ mul __displayModuleOffset, _line, 100 \ add __displayModuleOffset, __displayModuleOffset, _x \ add __displayModuleOffset, __displayModuleOffset, 919 \ GetDisplayModuleBytes(__displayModuleOffset, _cnt, _data) \ release __displayModuleOffsetMutex \ compend dseg segment __commModuleOffsetMutex mutex __commModuleOffset word dseg ends #define __GetBTDeviceName(_p, _str) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleBytes(CommOffsetBtDeviceTableName(_p), 16, _str) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 8 \ GetCommModuleBytes(__commModuleOffset, 16, _str) \ release __commModuleOffsetMutex \ compend #define __GetBTDeviceClass(_p, _n) \ compchk EQ, sizeof(_n), 4 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtDeviceTableClassOfDevice(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 24 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __getBTDeviceAddress(_p, _btaddr) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleBytes(CommOffsetBtDeviceTableBdAddr(_p), 7, _btaddr) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 28 \ GetCommModuleBytes(__commModuleOffset, 7, _btaddr) \ release __commModuleOffsetMutex \ compend #define __GetBTDeviceStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtDeviceTableDeviceStatus(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 35 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionName(_p, _str) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleBytes(CommOffsetBtConnectTableName(_p), 16, _str) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 938 \ GetCommModuleBytes(__commModuleOffset, 16, _str) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionClass(_p, _n) \ compchk EQ, sizeof(_n), 4 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtConnectTableClassOfDevice(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 954 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionPinCode(_p, _code) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleBytes(CommOffsetBtConnectTablePinCode(_p), 16, _code) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 958 \ GetCommModuleBytes(__commModuleOffset, 16, _code) \ release __commModuleOffsetMutex \ compend #define __getBTConnectionAddress(_p, _btaddr) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleBytes(CommOffsetBtConnectTableBdAddr(_p), 7, _btaddr) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 974 \ GetCommModuleBytes(__commModuleOffset, 7, _btaddr) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionHandleNum(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtConnectTableHandleNr(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 981 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionStreamStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtConnectTableStreamStatus(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 982 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __GetBTConnectionLinkQuality(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ GetCommModuleValue(CommOffsetBtConnectTableLinkQuality(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 983 \ GetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __getBTInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetBtInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetBtInBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getBTOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetBtOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetBtOutBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getHSInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetHsInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetHsInBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getHSOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetHsOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetHsOutBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getUSBInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetUsbInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbInBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getUSBOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetUsbOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbOutBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __getUSBPollBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ GetCommModuleBytes(CommOffsetUsbPollBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbPollBufBuf \ GetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend dseg segment __IOMWArgs TIOMapWrite __IOMWMutex mutex __IOMWFlattenBuf byte[] dseg ends #define __SetIOMapBytes(_modName, _offset, _cnt, _arrIn) \ acquire __IOMWMutex \ mov __IOMWArgs.ModuleName, _modName \ mov __IOMWArgs.Offset, _offset \ arrsubset __IOMWArgs.Buffer, _arrIn, NA, _cnt \ syscall IOMapWrite, __IOMWArgs \ release __IOMWMutex #define __SetIOMapValue(_modName, _offset, _n) \ acquire __IOMWMutex \ mov __IOMWArgs.ModuleName, _modName \ mov __IOMWArgs.Offset, _offset \ flatten __IOMWFlattenBuf, _n \ strtoarr __IOMWArgs.Buffer, __IOMWFlattenBuf \ syscall IOMapWrite, __IOMWArgs \ release __IOMWMutex #ifdef __ENHANCED_FIRMWARE dseg segment __IOMWBIArgs TIOMapWriteByID dseg ends #define __SetIOMapBytesByID(_modID, _offset, _cnt, _arrIn) \ acquire __IOMWMutex \ mov __IOMWBIArgs.ModuleID, _modID \ mov __IOMWBIArgs.Offset, _offset \ arrsubset __IOMWBIArgs.Buffer, _arrIn, NA, _cnt \ syscall IOMapWriteByID, __IOMWBIArgs \ release __IOMWMutex #define __SetIOMapValueByID(_modID, _offset, _n) \ acquire __IOMWMutex \ mov __IOMWBIArgs.ModuleID, _modID \ mov __IOMWBIArgs.Offset, _offset \ flatten __IOMWFlattenBuf, _n \ strtoarr __IOMWBIArgs.Buffer, __IOMWFlattenBuf \ syscall IOMapWriteByID, __IOMWBIArgs \ release __IOMWMutex #endif #define __setLSInputBuffer(_p, _offset, _cnt, _data) \ compif EQ, isconst(_p+_offset), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleBytes(LowSpeedOffsetInBufBuf(_p)+_offset, _cnt, _data) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, _offset \ SetLowSpeedModuleBytes(__lsModuleOffset, _cnt, _data) \ release __lsModuleOffsetMutex \ compend #define __setLSOutputBuffer(_p, _offset, _cnt, _data) \ compif EQ, isconst(_p+_offset), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleBytes(LowSpeedOffsetInBufBuf(_p)+_offset, _cnt, _data) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 76 \ add __lsModuleOffset, __lsModuleOffset, _offset \ SetLowSpeedModuleBytes(__lsModuleOffset, _cnt, _data) \ release __lsModuleOffsetMutex \ compend #ifdef __ENHANCED_FIRMWARE #define __spawnProgram(_fname) \ acquire __IOMWMutex \ mov __IOMWBIArgs.ModuleID, CommandModuleID \ mov __IOMWBIArgs.Offset, CommandOffsetActivateFlag \ arrsubset __IOMWFlattenBuf, _fname, NA, 20 \ arrbuild __IOMWBIArgs.Buffer, 1, 0, __IOMWFlattenBuf \ syscall IOMapWriteByID, __IOMWBIArgs \ release __IOMWMutex \ stop NA #else #define __spawnProgram(_fname) \ acquire __IOMWMutex \ mov __IOMWArgs.ModuleName, CommandModuleName \ mov __IOMWArgs.Offset, CommandOffsetActivateFlag \ arrsubset __IOMWFlattenBuf, _fname, NA, 20 \ arrbuild __IOMWArgs.Buffer, 1, 0, __IOMWFlattenBuf \ syscall IOMapWrite, __IOMWArgs \ release __IOMWMutex \ stop NA #endif #define __setDisplayNormal(_x, _line, _cnt, _data) \ compif EQ, isconst(_line+_x), TRUE \ compchk LT, _line, 0x08 \ compchk GTEQ, _line, 0x00 \ SetDisplayModuleBytes(DisplayOffsetNormal(_line,_x), _cnt, _data) \ compelse \ acquire __displayModuleOffsetMutex \ mul __displayModuleOffset, _line, 100 \ add __displayModuleOffset, __displayModuleOffset, _x \ add __displayModuleOffset, __displayModuleOffset, 119 \ SetDisplayModuleBytes(__displayModuleOffset, _cnt, _data) \ release __displayModuleOffsetMutex \ compend #define __setDisplayPopup(_x, _line, _cnt, _data) \ compif EQ, isconst(_line+_x), TRUE \ compchk LT, _line, 0x08 \ compchk GTEQ, _line, 0x00 \ SetDisplayModuleBytes(DisplayOffsetPopup(_line,_x), _cnt, _data) \ compelse \ acquire __displayModuleOffsetMutex \ mul __displayModuleOffset, _line, 100 \ add __displayModuleOffset, __displayModuleOffset, _x \ add __displayModuleOffset, __displayModuleOffset, 919 \ SetDisplayModuleBytes(__displayModuleOffset, _cnt, _data) \ release __displayModuleOffsetMutex \ compend #define __setBTDeviceName(_p, _str) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleBytes(CommOffsetBtDeviceTableName(_p), 16, _str) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 8 \ SetCommModuleBytes(__commModuleOffset, 16, _str) \ release __commModuleOffsetMutex \ compend #define __setBTDeviceAddress(_p, _btaddr) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleBytes(CommOffsetBtDeviceTableBdAddr(_p), 7, _btaddr) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 28 \ SetCommModuleBytes(__commModuleOffset, 7, _btaddr) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionName(_p, _str) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleBytes(CommOffsetBtConnectTableName(_p), 16, _str) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 938 \ SetCommModuleBytes(__commModuleOffset, 16, _str) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionPinCode(_p, _code) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleBytes(CommOffsetBtConnectTablePinCode(_p), 16, _code) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 958 \ SetCommModuleBytes(__commModuleOffset, 16, _code) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionAddress(_p, _btaddr) \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleBytes(CommOffsetBtConnectTableBdAddr(_p), 7, _btaddr) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 974 \ SetCommModuleBytes(__commModuleOffset, 7, _btaddr) \ release __commModuleOffsetMutex \ compend #define __setBTInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetBtInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetBtInBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setBTOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetBtOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetBtOutBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setHSInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetHsInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetHsInBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setHSOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetHsOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetHsOutBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setUSBInputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetUsbInBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbInBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setUSBOutputBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetUsbOutBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbOutBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setUSBPollBuffer(_offset, _cnt, _data) \ compif EQ, isconst(_offset), TRUE \ SetCommModuleBytes(CommOffsetUsbPollBufBuf+_offset, _cnt, _data) \ compelse \ acquire __commModuleOffsetMutex \ add __commModuleOffset, _offset, CommOffsetUsbPollBufBuf \ SetCommModuleBytes(__commModuleOffset, _cnt, _data) \ release __commModuleOffsetMutex \ compend #define __setSoundFrequency(_n) \ compchk EQ, sizeof(_n), 2 \ SetSoundModuleValue(SoundOffsetFreq, _n) #define __setSoundDuration(_n) \ compchk EQ, sizeof(_n), 2 \ SetSoundModuleValue(SoundOffsetDuration, _n) #define __setSoundSampleRate(_n) \ compchk EQ, sizeof(_n), 2 \ SetSoundModuleValue(SoundOffsetSampleRate, _n) #define __setSoundFlags(_n) \ compchk EQ, sizeof(_n), 1 \ SetSoundModuleValue(SoundOffsetFlags, _n) #define __setSoundModuleState(_n) \ compchk EQ, sizeof(_n), 1 \ SetSoundModuleValue(SoundOffsetState, _n) #define __setSoundMode(_n) \ compchk EQ, sizeof(_n), 1 \ SetSoundModuleValue(SoundOffsetMode, _n) #define __setSoundVolume(_n) \ compchk EQ, sizeof(_n), 1 \ SetSoundModuleValue(SoundOffsetVolume, _n) #define __setButtonPressCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetPressedCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __setButtonLongPressCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetLongPressCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 1 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __setButtonShortReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetShortRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 2 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __setButtonLongReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetLongRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 3 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __setButtonReleaseCount(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetRelCnt(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ mul __btnModuleOffset, _b, 8 \ add __btnModuleOffset, __btnModuleOffset, 4 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ compend #define __setButtonState(_b, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_b), TRUE \ compchk LT, _b, 0x04 \ compchk GTEQ, _b, 0x00 \ SetButtonModuleValue(ButtonOffsetState(_b), _n) \ compelse \ acquire __btnModuleOffsetMutex \ add __btnModuleOffset, _b, 32 \ SetButtonModuleValue(__btnModuleOffset, _n) \ release __btnModuleOffsetMutex \ Compend #define __setCommandFlags(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetFlags, _n) #define __setUIState(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetState, _n) #define __setUIButton(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetButton, _n) #define __setVMRunState(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetRunState, _n) #define __setBatteryState(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetBatteryState, _n) #define __setBluetoothState(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetBluetoothState, _n) #define __setUsbState(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetUsbState, _n) #define __setSleepTimeout(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetSleepTimeout, _n) #define __setSleepTimer(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetSleepTimer, _n) #define __setVolume(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetVolume, _n) #define __setOnBrickProgramPointer(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetOBPPointer, _n) #define __forceOff(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetForceOff, _n) #define __setAbortFlag(_n) \ compchk EQ, sizeof(_n), 1 \ SetUIModuleValue(UIOffsetAbortFlag, _n) #define __setInCustomZeroOffset(_p, _n) \ compchk EQ, sizeof(_n), 2 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetCustomZeroOffset(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInSensorBoolean(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetSensorBoolean(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 10 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInDigiPinsDirection(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetDigiPinsDir(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 11 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInDigiPinsStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetDigiPinsIn(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 12 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInDigiPinsOutputLevel(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetDigiPinsOut(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 13 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInCustomPercentFullScale(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetCustomPctFullScale(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 14 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setInCustomActiveStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetInputModuleValue(InputOffsetCustomActiveStatus(_p), _n) \ compelse \ acquire __inputModuleOffsetMutex \ mul __inputModuleOffset, _p, 20 \ add __inputModuleOffset, __inputModuleOffset, 15 \ SetInputModuleValue(__inputModuleOffset, _n) \ release __inputModuleOffsetMutex \ compend #define __setOutPwnFreq(_n) \ compchk EQ, sizeof(_n), 1 \ SetOutputModuleValue(OutputOffsetRegulationTime, _n) #define __setOutRegulationTime(_n) \ compchk EQ, sizeof(_n), 1 \ SetOutputModuleValue(OutputOffsetRegulationTime, _n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define __setOutRegulationOptions(_n) \ compchk EQ, sizeof(_n), 1 \ SetOutputModuleValue(OutputOffsetRegulationOptions, _n) #endif #define __setLSInputBufferInPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetInBufInPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 16 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSInputBufferOutPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetInBufOutPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 17 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSInputBufferBytesToRx(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetInBufBytesToRx(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 18 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSOutputBufferInPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetOutBufInPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 92 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSOutputBufferOutPtr(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetOutBufOutPtr(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 93 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSOutputBufferBytesToRx(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetOutBufBytesToRx(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ mul __lsModuleOffset, _p, 19 \ add __lsModuleOffset, __lsModuleOffset, 94 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSMode(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetMode(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 152 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSChannelState(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetChannelState(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 156 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSErrorType(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetLowSpeedModuleValue(LowSpeedOffsetErrorType(_p), _n) \ compelse \ acquire __lsModuleOffsetMutex \ add __lsModuleOffset, _p, 160 \ SetLowSpeedModuleValue(__lsModuleOffset, _n) \ release __lsModuleOffsetMutex \ compend #define __setLSState(_n) \ compchk EQ, sizeof(_n), 1 \ SetLowSpeedModuleValue(LowSpeedOffsetState, _n) #define __setLSSpeed(_n) \ compchk EQ, sizeof(_n), 1 \ SetLowSpeedModuleValue(LowSpeedOffsetSpeed, _n) #ifdef __ENHANCED_FIRMWARE #define __setLSNoRestartOnRead(_n) \ compchk EQ, sizeof(_n), 1 \ SetLowSpeedModuleValue(LowSpeedOffsetNoRestartOnRead, _n) #endif #define __setDisplayEraseMask(_n) \ compchk EQ, sizeof(_n), 4 \ SetDisplayModuleValue(DisplayOffsetEraseMask, _n) #define __setDisplayUpdateMask(_n) \ compchk EQ, sizeof(_n), 4 \ SetDisplayModuleValue(DisplayOffsetUpdateMask, _n) #define __setDisplayFont(_n) \ compchk EQ, sizeof(_n), 4 \ SetDisplayModuleValue(DisplayOffsetPFont, _n) #define __setDisplayDisplay(_n) \ compchk EQ, sizeof(_n), 4 \ SetDisplayModuleValue(DisplayOffsetDisplay, _n) #define __setDisplayFlags(_n) \ compchk EQ, sizeof(_n), 1 \ SetDisplayModuleValue(DisplayOffsetFlags, _n) #define __setDisplayTextLinesCenterFlags(_n) \ compchk EQ, sizeof(_n), 1 \ SetDisplayModuleValue(DisplayOffsetTextLinesCenterFlags, _n) #define __setDisplayContrast(_n) \ compchk EQ, sizeof(_n), 1 \ SetDisplayModuleValue(DisplayOffsetContrast, _n) #define __setBTDeviceClass(_p, _n) \ compchk EQ, sizeof(_n), 4 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtDeviceTableClassOfDevice(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 24 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBTDeviceStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtDeviceTableDeviceStatus(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 31 \ add __commModuleOffset, __commModuleOffset, 35 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionClass(_p, _n) \ compchk EQ, sizeof(_n), 4 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtConnectTableClassOfDevice(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 954 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionHandleNum(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtConnectTableHandleNr(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 981 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionStreamStatus(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtConnectTableStreamStatus(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 982 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBTConnectionLinkQuality(_p, _n) \ compchk EQ, sizeof(_n), 1 \ compif EQ, isconst(_p), TRUE \ compchk LT, _p, 0x04 \ compchk GTEQ, _p, 0x00 \ SetCommModuleValue(CommOffsetBtConnectTableLinkQuality(_p), _n) \ compelse \ acquire __commModuleOffsetMutex \ mul __commModuleOffset, _p, 47 \ add __commModuleOffset, __commModuleOffset, 983 \ SetCommModuleValue(__commModuleOffset, _n) \ release __commModuleOffsetMutex \ compend #define __setBrickDataBluecoreVersion(_n) \ compchk EQ, sizeof(_n), 2 \ SetCommModuleValue(CommOffsetBrickDataBluecoreVersion, _n) #define __setBrickDataBtStateStatus(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBrickDataBtStateStatus, _n) #define __setBrickDataBtHardwareStatus(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBrickDataBtHwStatus, _n) #define __setBrickDataTimeoutValue(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBrickDataTimeOutValue, _n) #define __setBTInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtInBufInPtr, _n) #define __setBTInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtInBufOutPtr, _n) #define __setBTOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtOutBufInPtr, _n) #define __setBTOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtOutBufOutPtr, _n) #define __setHSInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsInBufInPtr, _n) #define __setHSInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsInBufOutPtr, _n) #define __setHSOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsOutBufInPtr, _n) #define __setHSOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsOutBufOutPtr, _n) #define __setUSBInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbInBufInPtr, _n) #define __setUSBInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbInBufOutPtr, _n) #define __setUSBOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbOutBufInPtr, _n) #define __setUSBOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbOutBufOutPtr, _n) #define __setUSBPollBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbPollBufInPtr, _n) #define __setUSBPollBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbPollBufOutPtr, _n) #define __setBTDeviceCount(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtDeviceCnt, _n) #define __setBTDeviceNameCount(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetBtDeviceNameCnt, _n) #define __setHSFlags(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsFlags, _n) #define __setHSSpeed(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsSpeed, _n) #define __setHSState(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetHsState, _n) #define __setUSBState(_n) \ compchk EQ, sizeof(_n), 1 \ SetCommModuleValue(CommOffsetUsbState, _n) #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) #define __setHSMode(_n) \ compchk EQ, sizeof(_n), 2 \ SetCommModuleValue(CommOffsetHsMode, _n) #define __setBTDataMode(_n) \ compchk EQ, sizeof(_n), 1 \ compchk EQ, isconst(_n), 1 \ SetCommModuleValue(CommOffsetBtDataMode, _n|DATA_MODE_UPDATE) \ wait 1 #define __setHSDataMode(_n) \ compchk EQ, sizeof(_n), 1 \ compchk EQ, isconst(_n), 1 \ SetCommModuleValue(CommOffsetHsDataMode, _n|DATA_MODE_UPDATE) \ wait 1 #endif dseg segment __FOMutex mutex __FOArgs TFileOpen __FCMutex mutex __FCArgs TFileClose __FRHMutex mutex __FRHArgs TFileResolveHandle __FRMutex mutex __FRArgs TFileRename __FDMutex mutex __FDArgs TFileDelete __FFMutex mutex dseg ends #ifdef __ENHANCED_FIRMWARE dseg segment __FFArgs TFileFind dseg ends #endif subroutine __fileResizeSub dseg segment __frsMutex mutex __frsNewSize dword __frsOldName byte[] __frsTmpName byte[] __frsFOReadArgs TFileOpen __frsFOWriteArgs TFileOpen __frsFReadArgs TFileReadWrite __frsFWriteArgs TFileReadWrite __frsFRArgs TFileRename __frsFCArgs TFileClose __frsFDArgs TFileDelete __frsResult word dseg ends strcat __frsFRArgs.NewFilename, '_tmp', __frsOldName mov __frsFRArgs.OldFilename, __frsOldName syscall FileRename, __frsFRArgs mov __frsResult, __frsFRArgs.Result brtst NEQ, __frsEnd, __frsResult // old file has been renamed successfully mov __frsFOReadArgs.Filename, __frsFRArgs.NewFilename syscall FileOpenRead, __frsFOReadArgs mov __frsResult, __frsFOReadArgs.Result brtst NEQ, __frsOpenReadFailed, __frsResult // renamed file is open for reading mov __frsFOWriteArgs.Filename, __frsOldName mov __frsFOWriteArgs.Length, __frsNewSize syscall FileOpenWrite, __frsFOWriteArgs mov __frsResult, __frsFOWriteArgs.Result brtst NEQ, __frsOpenWriteFailed, __frsResult // both files are open mov __frsFReadArgs.FileHandle, __frsFOReadArgs.FileHandle mov __frsFWriteArgs.FileHandle, __frsFOWriteArgs.FileHandle __frsCopyLoop: set __frsFReadArgs.Length, 1024 syscall FileRead, __frsFReadArgs brtst LTEQ, __frsEndLoop, __frsFReadArgs.Length mov __frsFWriteArgs.Buffer, __frsFReadArgs.Buffer mov __frsFWriteArgs.Length, __frsFReadArgs.Length syscall FileWrite, __frsFWriteArgs brtst NEQ, __frsEndLoop, __frsFWriteArgs.Result brtst NEQ, __frsEndLoop, __frsFReadArgs.Result jmp __frsCopyLoop __frsEndLoop: // close read file mov __frsFCArgs.FileHandle, __frsFOReadArgs.FileHandle syscall FileClose, __frsFCArgs // close write file mov __frsFCArgs.FileHandle, __frsFOWriteArgs.FileHandle syscall FileClose, __frsFCArgs // delete read file mov __frsFDArgs.Filename, __frsFOReadArgs.Filename syscall FileDelete, __frsFDArgs jmp __frsEnd __frsOpenWriteFailed: // close read file mov __frsFCArgs.FileHandle, __frsFOReadArgs.FileHandle syscall FileClose, __frsFCArgs jmp __frsEnd __frsOpenReadFailed: // if the open read failed rename tmp back to original and exit mov __frsFRArgs.OldFilename, __frsFRArgs.NewFilename mov __frsFRArgs.NewFilename, __frsOldName syscall FileRename, __frsFRArgs __frsEnd: return ends #define __fileResize(_fname, _newsize, _result) \ acquire __frsMutex \ mov __frsOldName, _fname \ mov __frsNewSize, _newsize \ call __fileResizeSub \ mov _result, __frsResult \ release __frsMutex #define __createFile(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ mov __FOArgs.Length, _fsize \ syscall FileOpenWrite, __FOArgs \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __createFileLinear(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ mov __FOArgs.Length, _fsize \ syscall FileOpenWriteLinear, __FOArgs \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __createFileNonLinear(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ mov __FOArgs.Length, _fsize \ syscall FileOpenWriteNonLinear, __FOArgs \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __openFileAppend(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ syscall FileOpenAppend, __FOArgs \ mov _fsize, __FOArgs.Length \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __openFileRead(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ syscall FileOpenRead, __FOArgs \ mov _fsize, __FOArgs.Length \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __openFileReadLinear(_fname, _fsize, _handle, _result) \ acquire __FOMutex \ mov __FOArgs.Filename, _fname \ syscall FileOpenReadLinear, __FOArgs \ mov _fsize, __FOArgs.Length \ mov _handle, __FOArgs.FileHandle \ mov _result, __FOArgs.Result \ release __FOMutex #define __closeFile(_handle, _result) \ acquire __FCMutex \ mov __FCArgs.FileHandle, _handle \ syscall FileClose, __FCArgs \ mov _result, __FCArgs.Result \ release __FCMutex #define __resolveHandle(_fname, _handle, _writeable, _result) \ acquire __FRHMutex \ mov __FRHArgs.Filename, _fname \ syscall FileResolveHandle, __FRHArgs \ mov _handle, __FRHArgs.FileHandle \ mov _writeable, __FRHArgs.WriteHandle \ mov _result, __FRHArgs.Result \ release __FRHMutex #define __renameFile(_oldname, _newname, _result) \ acquire __FRMutex \ mov __FRArgs.OldFilename, _oldname \ mov __FRArgs.NewFilename, _newname \ syscall FileRename, __FRArgs \ mov _result, __FRArgs.Result \ release __FRMutex #define __deleteFile(_fname, _result) \ acquire __FDMutex \ mov __FDArgs.Filename, _fname \ syscall FileDelete, __FDArgs \ mov _result, __FDArgs.Result \ release __FDMutex #ifdef __ENHANCED_FIRMWARE #define __findFirstFile(_fname, _handle, _result) \ acquire __FFMutex \ mov __FFArgs.Filename, _fname \ syscall FileFindFirst, __FFArgs \ mov _result, __FFArgs.Result \ mov _handle, __FFArgs.FileHandle \ mov _fname, __FFArgs.Filename \ release __FFMutex #define __findNextFile(_fname, _handle, _result) \ acquire __FFMutex \ mov __FFArgs.FileHandle, _handle \ syscall FileFindNext, __FFArgs \ mov _result, __FFArgs.Result \ mov _handle, __FFArgs.FileHandle \ mov _fname, __FFArgs.Filename \ release __FFMutex #endif dseg segment __FReadArgs TFileReadWrite __FReadTmpByte byte __FReadMutex mutex __RLSBuffer byte[] __RLSOutput byte[] __RLSReturn word __RLSReturnAddress byte __RLSMaxBytes word __RLSByteCount word __soTmpBuf byte[] __soMutex mutex dseg ends #define __sizeOF(_n, _result) \ compif EQ, ((typeof(_n)>=1)&&(typeof(_n)<=6))||(typeof(_n)==10), TRUE \ set _result, sizeof(_n) \ compelse \ acquire __soMutex \ flatten __soTmpBuf, _n \ arrsize _result, __soTmpBuf \ sub _result, _result, 1 \ release __soMutex \ compend #define __readBytes(_handle, _len, _buf, _result) \ acquire __FReadMutex \ mov __FReadArgs.FileHandle, _handle \ mov __FReadArgs.Length, _len \ syscall FileRead, __FReadArgs \ mov _result, __FReadArgs.Result \ strtoarr _buf, __FReadArgs.Buffer \ mov _len, __FReadArgs.Length \ release __FReadMutex #define __readValue(_handle, _n, _result) \ acquire __FReadMutex \ mov __FReadArgs.FileHandle, _handle \ __sizeOF(_n, __FReadArgs.Length) \ syscall FileRead, __FReadArgs \ mov _result, __FReadArgs.Result \ unflatten _n, __FReadTmpByte, __FReadArgs.Buffer, _n \ release __FReadMutex #define __readLnValue(_handle, _n, _result) \ acquire __FReadMutex \ mov __FReadArgs.FileHandle, _handle \ __sizeOF(_n, __FReadArgs.Length) \ syscall FileRead, __FReadArgs \ unflatten _n, __FReadTmpByte, __FReadArgs.Buffer, _n \ set __FReadArgs.Length, 2 \ syscall FileRead, __FReadArgs \ mov _result, __FReadArgs.Result \ release __FReadMutex #define __readLnStringEx(_handle, _output, _max, _result) \ acquire __FReadMutex \ mov __FReadArgs.FileHandle, _handle \ mov __RLSMaxBytes, _max \ subcall __readStringLine, __RLSReturnAddress \ mov _result, __RLSReturn \ mov _output, __RLSOutput \ release __FReadMutex \ #define __readLnString(_handle, _output, _result) __readLnStringEx(_handle, _output, 0xFFFF, _result) subroutine __readStringLine arrinit __RLSOutput, 0, 1 set __RLSByteCount, 0 __RLSStringLoop: set __FReadArgs.Length, 1 mov __RLSBuffer, __RLSOutput syscall FileRead, __FReadArgs mov __RLSReturn, __FReadArgs.Result brtst NEQ, __RLSStringDone, __RLSReturn index __FReadTmpByte, __FReadArgs.Buffer, NA brcmp EQ, __RLSStringDone, __FReadTmpByte, 0x0A brcmp EQ, __RLSStringSkip, __FReadTmpByte, 0x0D strcat __RLSOutput, __RLSBuffer, __FReadArgs.Buffer add __RLSByteCount, __RLSByteCount, 1 brcmp GTEQ, __RLSStringDone, __RLSByteCount, __RLSMaxBytes __RLSStringSkip: jmp __RLSStringLoop __RLSStringDone: subret __RLSReturnAddress ends dseg segment __FWriteArgs TFileReadWrite __FWriteFlattenBuf byte[] __FWriteMutex mutex __FWriteLn byte[] {0x0D, 0x0A} dseg ends #define __writeBytes(_handle, _buf, _len, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ mov __FWriteArgs.Buffer, _buf \ arrsize __FWriteArgs.Length, __FWriteArgs.Buffer \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ mov _len, __FWriteArgs.Length \ release __FWriteMutex #define __writeString(_handle, _str, _len, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ strtoarr __FWriteArgs.Buffer, _str \ arrsize __FWriteArgs.Length, __FWriteArgs.Buffer \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ mov _len, __FWriteArgs.Length \ release __FWriteMutex #define __writeLnString(_handle, _str, _len, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ strtoarr __FWriteFlattenBuf, _str \ arrbuild __FWriteArgs.Buffer, __FWriteFlattenBuf, __FWriteLn \ arrsize __FWriteArgs.Length, __FWriteArgs.Buffer \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ mov _len, __FWriteArgs.Length \ release __FWriteMutex #define __writeBytesEx(_handle, _len, _buf, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ mov __FWriteArgs.Length, _len \ mov __FWriteArgs.Buffer, _buf \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ mov _len, __FWriteArgs.Length \ release __FWriteMutex #define __writeValue(_handle, _n, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ flatten __FWriteFlattenBuf, _n \ strtoarr __FWriteArgs.Buffer, __FWriteFlattenBuf \ arrsize __FWriteArgs.Length, __FWriteArgs.Buffer \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ release __FWriteMutex #define __writeLnValue(_handle, _n, _result) \ acquire __FWriteMutex \ mov __FWriteArgs.FileHandle, _handle \ flatten __FWriteFlattenBuf, _n \ strtoarr __FWriteArgs.Buffer, __FWriteFlattenBuf \ arrbuild __FWriteFlattenBuf, __FWriteArgs.Buffer, __FWriteLn \ mov __FWriteArgs.Buffer, __FWriteFlattenBuf \ arrsize __FWriteArgs.Length, __FWriteArgs.Buffer \ syscall FileWrite, __FWriteArgs \ mov _result, __FWriteArgs.Result \ release __FWriteMutex dseg segment __MWMutex mutex __MWArgs TMessageWrite __MRMutex mutex __MRArgs TMessageRead __SRNTmpVal sdword __RRNTmpVal sdword __RRNErr byte dseg ends #define __sendMessage(_queue, _msg, _result) \ acquire __MWMutex \ mov __MWArgs.QueueID, _queue \ mov __MWArgs.Message, _msg \ syscall MessageWrite, __MWArgs \ mov _result, __MWArgs.Result \ release __MWMutex #define __receiveMessage(_queue, _clear, _msg, _result) \ acquire __MRMutex \ mov __MRArgs.QueueID, _queue \ mov __MRArgs.Remove, _clear \ syscall MessageRead, __MRArgs \ mov _msg, __MRArgs.Message \ mov _result, __MRArgs.Result \ release __MRMutex #define __receiveRemoteBool(_queue, _clear, _bval, _result) \ acquire __MRMutex \ mov __MRArgs.QueueID, _queue \ mov __MRArgs.Remove, _clear \ set _bval, 0 \ syscall MessageRead, __MRArgs \ brtst NEQ, __RRB_Err##__I__, __MRArgs.Result \ index _bval, __MRArgs.Message, NA \ __RRB_Err##__I__: \ __IncI__ \ mov _result, __MRArgs.Result \ release __MRMutex #define __receiveRemoteNumber(_queue, _clear, _val, _result) \ acquire __MRMutex \ mov __MRArgs.QueueID, _queue \ mov __MRArgs.Remove, _clear \ set __RRNTmpVal, 0 \ syscall MessageRead, __MRArgs \ unflatten __RRNTmpVal, __RRNErr, __MRArgs.Message, __RRNTmpVal \ mov _val, __RRNTmpVal \ mov _result, __MRArgs.Result \ release __MRMutex #define __receiveRemoteMessageEx(_queue, _clear, _str, _val, _bval, _result) \ acquire __MRMutex \ mov __MRArgs.QueueID, _queue \ mov __MRArgs.Remove, _clear \ set __RRNTmpVal, 0 \ set _bval, 0 \ syscall MessageRead, __MRArgs \ brtst NEQ, __RRM_Err##__I__, __MRArgs.Result \ index _bval, __MRArgs.Message, NA \ unflatten __RRNTmpVal, __RRNErr, __MRArgs.Message, __RRNTmpVal \ __RRM_Err##__I__: \ __IncI__ \ mov _val, __RRNTmpVal \ mov _str, __MRArgs.Message \ mov _result, __MRArgs.Result \ release __MRMutex #define __sendResponseBool(_queue, _bval, _result) \ acquire __MWMutex \ add __MWArgs.QueueID, _queue, 10 \ arrbuild __MWArgs.Message, _bval, 0 \ syscall MessageWrite, __MWArgs \ mov _result, __MWArgs.Result \ release __MWMutex #define __sendResponseNumber(_queue, _val, _result) \ acquire __MWMutex \ add __MWArgs.QueueID, _queue, 10 \ mov __SRNTmpVal, _val \ flatten __MWArgs.Message, __SRNTmpVal \ syscall MessageWrite, __MWArgs \ mov _result, __MWArgs.Result \ release __MWMutex #define __sendResponseString(_queue, _msg, _result) \ acquire __MWMutex \ add __MWArgs.QueueID, _queue, 10 \ mov __MWArgs.Message, _msg \ syscall MessageWrite, __MWArgs \ mov _result, __MWArgs.Result \ release __MWMutex dseg segment __CBTCSArgs TCommBTCheckStatus __CBTCSMutex mutex __CBTWArgs TCommBTWrite __CBTWMutex mutex __SRSTmpBuf byte[] __SRSSendBuf byte[] __SRSTmpLongVal sdword __SRSTmpWordVal sword __SRSTmpByteVal sbyte __SRSFlattenBuf byte[] __RemoteMutex mutex dseg ends dseg segment __GenericCmdFilenamePacket byte[] {0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} __GenericCreateFilePacket byte[] {0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF} __GenericIOMapPacket byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // direct commands __DCStartProgramPacket byte[] {0x80, 0x00} __DCStopProgramPacket byte[] {0x80, 0x01} __DCPlaySoundFilePacket byte[] {0x80, 0x02, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} __DCPlayTonePacket byte[] {0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF} __DCSetOutputStatePacket byte[] {0x80, 0x04} __DCSetInputModePacket byte[] {0x80, 0x05} __DCGetOutputStatePacket byte[] {0x00, 0x06} __DCGetInputValuesPacket byte[] {0x00, 0x07} __DCResetScaledValuePacket byte[] {0x80, 0x08} __DCMessageWritePacket byte[] {0x80, 0x09, 0xFF, 0xFF} __DCResetMotorPosPacket byte[] {0x80, 0x0a} __DCGetBatteryLevelPacket byte[] {0x00, 0x0b} __DCStopSoundPacket byte[] {0x80, 0x0c} __DCKeepAlivePacket byte[] {0x80, 0x0d} __DCLSGetStatusPacket byte[] {0x00, 0x0e} __DCLSWritePacket byte[] {0x80, 0x0f} __DCLSReadPacket byte[] {0x00, 0x10} __DCGetCurProgNamePacket byte[] {0x00, 0x11} __DCMessageReadPacket byte[] {0x00, 0x13} __DCDatalogReadPacket byte[] {0x00, 0x19} __DCDatalogSetTimesPacket byte[] {0x80, 0x1a} __DCBTGetContactCntPacket byte[] {0x00, 0x1b} __DCBTGetContactNamePacket byte[] {0x00, 0x1c} __DCBTGetConnectCntPacket byte[] {0x00, 0x1d} __DCBTGetConnectNamePacket byte[] {0x00, 0x1e} __DCSetPropertyPacket byte[] {0x80, 0x1f} __DCGetPropertyPacket byte[] {0x00, 0x20} __DCUpdateResetCountPacket byte[] {0x80, 0x21} // system commands __SCOpenReadPacket byte[] {0x01, 0x80} __SCOpenWritePacket byte[] {0x01, 0x81} __SCReadPacket byte[] {0x01, 0x82} __SCWritePacket byte[] {0x01, 0x83} __SCClosePacket byte[] {0x01, 0x84} __SCDeletePacket byte[] {0x01, 0x85} __SCFindFirstPacket byte[] {0x01, 0x86} __SCFindNextPacket byte[] {0x01, 0x87} __SCGetFirmwareVerPacket byte[] {0x01, 0x88} __SCOpenWriteLinearPacket byte[] {0x01, 0x89} __SCOpenWriteDataPacket byte[] {0x01, 0x8b} __SCOpenAppendDataPacket byte[] {0x01, 0x8c} __SCIOMapReadPacket byte[] {0x01, 0x94} __SCIOMapWritePacket byte[] {0x81, 0x95} __SCSetBrickNamePacket byte[] {0x81, 0x98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} __SCBTGetAddressPacket byte[] {0x01, 0x9a} __SCGetDeviceInfoPacket byte[] {0x01, 0x9b} __SCDeleteUserFlashPacket byte[] {0x01, 0xA0} __SCPollCommandLenPacket byte[] {0x01, 0xA1} __SCPollCommandPacket byte[] {0x01, 0xA2} // append buffer number, cmd len, __SCRenameFilePacket byte[] {0x81, 0xA3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} __SCBTFactoryResetPacket byte[] {0x81, 0xA4} dseg ends #define __bluetoothStatus(_conn, _result) \ acquire __CBTCSMutex \ mov __CBTCSArgs.Connection, _conn \ syscall CommBTCheckStatus, __CBTCSArgs \ mov _result, __CBTCSArgs.Result \ release __CBTCSMutex #define __bluetoothWrite(_conn, _buffer, _result) \ acquire __CBTWMutex \ mov __CBTWArgs.Connection, _conn \ mov __CBTWArgs.Buffer, _buffer \ syscall CommBTWrite, __CBTWArgs \ mov _result, __CBTWArgs.Result \ release __CBTWMutex #define __UseRS485() \ setin IN_TYPE_HISPEED, IN_4, TypeField \ wait 1 #ifdef __ENHANCED_FIRMWARE dseg segment __CHSCSArgs TCommHSCheckStatus __CHSCSMutex mutex __CHSWArgs TCommHSReadWrite __CHSWMutex mutex __CHSRArgs TCommHSReadWrite __CHSRMutex mutex __CHSCArgs TCommHSControl __CHSCMutex mutex __SHSTmpVal sdword __WFRRMutex mutex __WFRRAvail byte __WFRR_I byte __WFRRCmd byte __WFRRBuffer byte[] __WFRRTmpBuffer byte[] __WFRRUnflattenBuf byte[] __WFRRUnflattenErr byte __WFRRTmpByte byte __WFRRTmpSWord sword __WFRRTmpSDWord sdword __WFRRStatus sbyte dseg ends #define __RS485Status(_sendingData, _dataAvail) \ acquire __CHSCSMutex \ syscall CommHSCheckStatus, __CHSCSArgs \ mov _sendingData, __CHSCSArgs.SendingData \ mov _dataAvail, __CHSCSArgs.DataAvailable \ release __CHSCSMutex #define __RS485WriteSCDC(_conn, _buffer, _status) \ acquire __CHSWMutex \ sub __WFRRTmpByte, _conn, CONN_HS_ALL \ arrbuild __CHSWArgs.Buffer, __WFRRTmpByte, _buffer \ syscall CommHSWrite, __CHSWArgs \ mov _status, __CHSWArgs.Status \ release __CHSWMutex #define __RS485Write(_buffer, _status) \ acquire __CHSWMutex \ mov __CHSWArgs.Buffer, _buffer \ syscall CommHSWrite, __CHSWArgs \ mov _status, __CHSWArgs.Status \ release __CHSWMutex #define __RS485Read(_buffer, _status) \ acquire __CHSRMutex \ syscall CommHSRead, __CHSRArgs \ mov _buffer, __CHSRArgs.Buffer \ mov _status, __CHSRArgs.Status \ release __CHSRMutex #if __FIRMWARE_VERSION > 107 #define __RS485Control(_cmd, _baud, _mode, _result) \ acquire __CHSCMutex \ mov __CHSCArgs.Command, _cmd \ mov __CHSCArgs.BaudRate, _baud \ mov __CHSCArgs.Mode, _mode \ syscall CommHSControl, __CHSCArgs \ mov _result, __CHSCArgs.Result \ release __CHSCMutex \ wait 1 #else #define __RS485Control(_cmd, _baud, _result) \ acquire __CHSCMutex \ mov __CHSCArgs.Command, _cmd \ mov __CHSCArgs.BaudRate, _baud \ syscall CommHSControl, __CHSCArgs \ mov _result, __CHSCArgs.Result \ release __CHSCMutex \ wait 1 #endif #define __sendRS485Bool(_bval, _status) \ acquire __CHSWMutex \ arrbuild __CHSWArgs.Buffer, _bval, 0 \ syscall CommHSWrite, __CHSWArgs \ mov _status, __CHSWArgs.Status \ release __CHSWMutex #define __sendRS485Number(_val, _status) \ acquire __CHSWMutex \ mov __SHSTmpVal, _val \ flatten __CHSWArgs.Buffer, __SHSTmpVal \ syscall CommHSWrite, __CHSWArgs \ mov _status, __CHSWArgs.Status \ release __CHSWMutex #define __sendRS485String(_str, _status) __RS485Write(_str, _status) #endif #ifdef __ENHANCED_FIRMWARE #define __connectionSCDCWrite(_conn, _buffer, _result) \ brcmp LT, __ConnWrite_Else##__I__, _conn, 4 \ __RS485WriteSCDC(_conn, _buffer, _result) \ jmp __ConnWrite_EndIf##__I__ \ __ConnWrite_Else##__I__: \ __bluetoothWrite(_conn, _buffer, _result) \ __ConnWrite_EndIf##__I__: \ __IncI__ #define __connectionRawWrite(_conn, _buffer, _result) \ brcmp LT, __ConnWrite_Else##__I__, _conn, 4 \ __RS485Write(_buffer, _result) \ jmp __ConnWrite_EndIf##__I__ \ __ConnWrite_Else##__I__: \ __bluetoothWrite(_conn, _buffer, _result) \ __ConnWrite_EndIf##__I__: \ __IncI__ #define __remoteConnectionIdle(_conn, _result) \ brcmp NEQ, __ConnIdle_Else##__I__, _conn, 4 \ __RS485Status(_result, __SHSTmpVal) \ jmp __ConnIdle_EndIf##__I__ \ __ConnIdle_Else##__I__: \ __bluetoothStatus(_conn, _result) \ __ConnIdle_EndIf##__I__: \ tst EQ, _result, _result \ __IncI__ subroutine __DoWaitForRemoteResponse set __WFRR_I, 0 __wFRR_Repeat: __GetLastResponseInfo(FALSE, __WFRRAvail, __WFRRCmd, __WFRRBuffer, __WFRRStatus) wait 2 add __WFRR_I, __WFRR_I, 1 // if it rolls back around to 0 then break out of loop brtst EQ, __wFRR_Break, __WFRR_I brtst EQ, __wFRR_Repeat, __WFRRAvail // > 0 bytes in last response so read it one more time and clear it __GetLastResponseInfo(TRUE, __WFRRAvail, __WFRRCmd, __WFRRBuffer, __WFRRStatus) jmp __wFRR_End __wFRR_Break: set __WFRRStatus, TRUE // timeout error occurred __wFRR_End: return ends #else #define __connectionSCDCWrite(_conn, _buffer, _result) __bluetoothWrite(_conn, _buffer, _result) #define __connectionRawWrite(_conn, _buffer, _result) __bluetoothWrite(_conn, _buffer, _result) #define __remoteConnectionIdle(_conn, _result) \ __bluetoothStatus(_conn, _result) \ tst EQ, _result, _result #endif #define __sendRemoteBool(_conn, _queue, _bval, _result) \ acquire __RemoteMutex \ mov __SRSTmpBuf, __DCMessageWritePacket \ replace __SRSTmpBuf, __SRSTmpBuf, 2, _queue \ replace __SRSTmpBuf, __SRSTmpBuf, 3, 2 \ arrbuild __SRSSendBuf, __SRSTmpBuf, _bval, 0 \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __sendRemoteNumber(_conn, _queue, _val, _result) \ acquire __RemoteMutex \ mov __SRSTmpBuf, __DCMessageWritePacket \ replace __SRSTmpBuf, __SRSTmpBuf, 2, _queue \ replace __SRSTmpBuf, __SRSTmpBuf, 3, 5 \ mov __SRSTmpLongVal, _val \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ arrbuild __SRSSendBuf, __SRSTmpBuf, __SRSFlattenBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __sendRemoteString(_conn, _queue, _str, _result) \ acquire __RemoteMutex \ mov __SRSTmpBuf, __DCMessageWritePacket \ replace __SRSTmpBuf, __SRSTmpBuf, 2, _queue \ arrsize __SRSTmpLongVal, _str \ replace __SRSTmpBuf, __SRSTmpBuf, 3, __SRSTmpLongVal \ arrbuild __SRSSendBuf, __SRSTmpBuf, _str \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteMessageRead(_conn, _queue, _result) \ acquire __RemoteMutex \ add __SRSTmpLongVal, _queue, 10 \ arrbuild __SRSSendBuf, __DCMessageReadPacket, __SRSTmpLongVal, _queue, 0x01 \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteResetScaledValue(_conn, _port, _result) \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __DCResetScaledValuePacket, _port \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteResetMotorPosition(_conn, _port, _brelative, _result) \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __DCResetMotorPosPacket, _port, _brelative \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteSetInputMode(_conn, _port, _type, _mode, _result) \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __DCSetInputModePacket, _port, _type, _mode \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteSetOutputState(_conn, _port, _speed, _mode, _regmode, _turnpct, _runstate, _tacholimit, _result) \ acquire __RemoteMutex \ mov __SRSTmpLongVal, _tacholimit \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ arrbuild __SRSTmpBuf, __DCSetOutputStatePacket, _port, _speed, _mode, _regmode, _turnpct, _runstate, __SRSFlattenBuf \ strtoarr __SRSSendBuf, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remotePlaySoundFile(_conn, _filename, _bloop, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __DCPlaySoundFilePacket \ strsubset __SRSTmpBuf, _filename, NA, 19 \ replace __SRSSendBuf, __SRSSendBuf, 2, _bloop \ replace __SRSSendBuf, __SRSSendBuf, 3, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remotePlayTone(_conn, _frequency, _duration, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __DCPlayTonePacket \ and __SRSTmpLongVal, _frequency, 0xff \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpLongVal \ div __SRSTmpLongVal, _frequency, 0xff \ replace __SRSSendBuf, __SRSSendBuf, 3, __SRSTmpLongVal \ and __SRSTmpLongVal, _duration, 0xff \ replace __SRSSendBuf, __SRSSendBuf, 4, __SRSTmpLongVal \ div __SRSTmpLongVal, _duration, 0xff \ replace __SRSSendBuf, __SRSSendBuf, 5, __SRSTmpLongVal \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteGenericFilenameCommand(_conn, _cmdBuf, _filename, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __GenericCmdFilenamePacket \ strsubset __SRSTmpBuf, _filename, NA, 19 \ replace __SRSSendBuf, __SRSSendBuf, NA, _cmdBuf \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteStartProgram(_conn, _filename, _result) __remoteGenericFilenameCommand(_conn, __DCStartProgramPacket, _filename, _result) #define __remoteGenericCreateFileCommand(_conn, _cmdBuf, _filename, _size, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __GenericCreateFilePacket \ strsubset __SRSTmpBuf, _filename, NA, 19 \ replace __SRSSendBuf, __SRSSendBuf, NA, _cmdBuf \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ mov __SRSTmpLongVal, _size \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 22, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteGenericByteCommand(_conn, _cmdBuf, _val, _result) \ compchk EQ, sizeof(_val), 1 \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, _cmdBuf, _val \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteResetTachoCount(_conn, _port, _result) __remoteGenericByteCommand(_conn, __DCUpdateResetCountPacket, _port, _result) #define __remoteDoWrite(_conn, _handle, _data, _result) \ compchk EQ, sizeof(_handle), 1 \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __SCWritePacket, _handle, _data \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteDoRead(_conn, _handle, _numbytes, _result) \ compchk EQ, sizeof(_handle), 1 \ acquire __RemoteMutex \ mov __SRSTmpWordVal, _numbytes \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ arrbuild __SRSSendBuf, __SCReadPacket, _handle, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteDoPollCommand(_conn, _bufnum, _len, _result) \ compchk EQ, sizeof(_bufnum), 1 \ compchk EQ, sizeof(_len), 1 \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __SCPollCommandPacket, _bufnum, _len \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteDoIOMapRead(_conn, _id, _offset, _numbytes, _result) \ compchk EQ, sizeof(_handle), 1 \ acquire __RemoteMutex \ mov __SRSSendBuf, __GenericIOMapPacket \ replace __SRSSendBuf, __SRSSendBuf, NA, __SCIOMapReadPacket \ mov __SRSTmpLongVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ mov __SRSTmpWordVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 6, __SRSTmpBuf \ mov __SRSTmpWordVal, _numbytes \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 8, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #ifdef __ENHANCED_FIRMWARE #define __remoteGetOutputState(_conn, _params, _result) \ __remoteGenericByteCommand(_conn, __DCGetOutputStatePacket, _params.Port, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGOSR_End##__I__, _result \ brcmp NEQ, __RRGOSR_End##__I__, __WFRRAvail, 23 \ unflatten _params, __WFRRUnflattenErr, __WFRRBuffer, _params \ __RRGOSR_End##__I__: \ __IncI__ #define __remoteGetInputValues(_conn, _params, _result) \ __remoteGenericByteCommand(_conn, __DCGetInputValuesPacket, _params.Port, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGIVR_End##__I__, _result \ brcmp NEQ, __RRGIVR_End##__I__, __WFRRAvail, 14 \ unflatten _params, __WFRRUnflattenErr, __WFRRBuffer, _params \ __RRGIVR_End##__I__: \ __IncI__ #define __remoteGetBatteryLevel(_conn, _value, _result) \ compchk EQ, sizeof(_value), 2 \ __connectionSCDCWrite(_conn, __DCGetBatteryLevelPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGBL_End##__I__, _result \ brcmp NEQ, __RRGBL_End##__I__, __WFRRAvail, 3 \ unflatten _value, __WFRRUnflattenErr, __WFRRBuffer, _value \ __RRGBL_End##__I__: \ __IncI__ #define __remoteLowspeedGetStatus(_conn, _value, _result) \ __connectionSCDCWrite(_conn, __DCLSGetStatusPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRLGS_End##__I__, _result \ brcmp NEQ, __RRLGS_End##__I__, __WFRRAvail, 2 \ index _value, __WFRRBuffer, NA \ __RRLGS_End##__I__: \ __IncI__ #define __remoteLowspeedRead(_conn, _port, _bread, _data, _result) \ __remoteGenericByteCommand(_conn, __DCLSReadPacket, _port, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRLR_End##__I__, _result \ brcmp NEQ, __RRLR_End##__I__, __WFRRAvail, 18 \ index _bread, __WFRRBuffer, NA \ arrsubset _data, __WFRRBuffer, 1, _bread \ __RRLR_End##__I__: \ __IncI__ #define __remoteGetCurrentProgramName(_conn, _name, _result) \ __connectionSCDCWrite(_conn, __DCGetCurProgNamePacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGCPN_End##__I__, _result \ brcmp NEQ, __RRGCPN_End##__I__, __WFRRAvail, 21 \ mov _name, __WFRRBuffer \ __RRGCPN_End##__I__: \ __IncI__ #define __remoteDatalogRead(_conn, _remove, _cnt, _log, _result) \ __remoteGenericByteCommand(_conn, __DCDatalogReadPacket, _remove, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRDR_End##__I__, _result \ brcmp NEQ, __RRDR_End##__I__, __WFRRAvail, 62 \ index _cnt, __WFRRBuffer, NA \ arrsubset _log, __WFRRBuffer, 1, _cnt \ __RRDR_End##__I__: \ __IncI__ #define __remoteGetContactCount(_conn, _cnt, _result) \ __connectionSCDCWrite(_conn, __DCBTGetContactCntPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGCTC_End##__I__, _result \ brcmp NEQ, __RRGCTC_End##__I__, __WFRRAvail, 2 \ index _cnt, __WFRRBuffer, NA \ __RRGCTC_End##__I__: \ __IncI__ #define __remoteGetContactName(_conn, _idx, _name, _result) \ __remoteGenericByteCommand(_conn, __DCBTGetContactNamePacket, _idx, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGCTN_End##__I__, _result \ brcmp NEQ, __RRGCTN_End##__I__, __WFRRAvail, 19 \ mov _name, __WFRRBuffer \ __RRGCTN_End##__I__: \ __IncI__ #define __remoteGetConnectionCount(_conn, _cnt, _result) \ __connectionSCDCWrite(_conn, __DCBTGetConnectCntPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGCNC_End##__I__, _result \ brcmp NEQ, __RRGCNC_End##__I__, __WFRRAvail, 2 \ index _cnt, __WFRRBuffer, NA \ __RRGCNC_End##__I__: \ __IncI__ #define __remoteGetConnectionName(_conn, _idx, _name, _result) \ __remoteGenericByteCommand(_conn, __DCBTGetConnectNamePacket, _idx, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGCNN_End##__I__, _result \ brcmp NEQ, __RRGCNN_End##__I__, __WFRRAvail, 19 \ mov _name, __WFRRBuffer \ __RRGCNN_End##__I__: \ __IncI__ #define __remoteGetProperty(_conn, _property, _value, _result) \ mov _value, 0 \ __remoteGenericByteCommand(_conn, __DCGetPropertyPacket, _property, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGP_End##__I__, _result \ unflatten _value, __WFRRUnflattenErr, __WFRRBuffer, _value \ __RRGP_End##__I__: \ __IncI__ #define __remoteOpenRead(_conn, _filename, _handle, _size, _result) \ __remoteGenericFilenameCommand(_conn, __SCOpenReadPacket, _filename, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RROR_End##__I__, _result \ brcmp NEQ, __RROR_End##__I__, __WFRRAvail, 6 \ index _handle, __WFRRBuffer, NA \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 1, 5 \ unflatten __WFRRTmpSDWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSDWord \ mov _size, __WFRRTmpSDWord \ __RROR_End##__I__: \ __IncI__ #define __remoteOpenWrite(_conn, _filename, _size, _handle, _result) \ __remoteGenericCreateFileCommand(_conn, __SCOpenWritePacket, _filename, _size, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RROW_End##__I__, _result \ brcmp NEQ, __RROW_End##__I__, __WFRRAvail, 2 \ index _handle, __WFRRBuffer, NA \ __RROW_End##__I__: \ __IncI__ #define __remoteRead(_conn, _handle, _numbytes, _data, _result) \ mov _result, 1 \ brcmp GT, __RRRead_End##__I__, _numbytes, 58 \ __remoteDoRead(_conn, _handle, _numbytes, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ add __WFRRTmpByte, _numbytes, 4 \ brtst NEQ, __RRRead_End##__I__, _result \ brcmp NEQ, __RRRead_End##__I__, __WFRRAvail, __WFRRTmpByte \ index _handle, __WFRRBuffer, NA \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 1, 2 \ arrtostr __WFRRUnflattenBuf, __WFRRTmpBuffer \ unflatten __WFRRTmpSWord, __WFRRUnflattenErr, __WFRRUnflattenBuf, __WFRRTmpSWord \ mov _numbytes, __WFRRTmpSWord \ arrsubset _data, __WFRRBuffer, 2, _numbytes \ __RRRead_End##__I__: \ __IncI__ #define __remoteWrite(_conn, _handle, _numbytes, _data, _result) \ mov _result, 1 \ brcmp GT, __RRWrite_End##__I__, _numbytes, 58 \ __remoteDoWrite(_conn, _handle, _data, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRWrite_End##__I__, _result \ brcmp NEQ, __RRWrite_End##__I__, __WFRRAvail, 4 \ index _handle, __WFRRBuffer, NA \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 1, 3 \ unflatten __WFRRTmpSWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSWord \ mov _numbytes, __WFRRTmpSWord \ __RRWrite_End##__I__: \ __IncI__ #define __remoteCloseFile(_conn, _handle, _result) \ __remoteGenericByteCommand(_conn, __SCClosePacket, _handle, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus #define __remoteDeleteFile(_conn, _filename, _result) \ __remoteGenericFilenameCommand(_conn, __SCDeletePacket, _filename, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus #define __remoteDeleteUserFlash(_conn, _result) \ __connectionSCDCWrite(_conn, __SCDeleteUserFlashPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus #define __remoteFindFirstFile(_conn, _mask, _handle, _name, _size, _result) \ __remoteGenericFilenameCommand(_conn, __SCFindFirstPacket, _mask, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRFindFirstFile_End##__I__, _result \ brcmp NEQ, __RRFindFirstFile_End##__I__, __WFRRAvail, 26 \ index _handle, __WFRRBuffer, NA \ arrsubset _name, __WFRRBuffer, 1, 20 \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 21, 5 \ unflatten __WFRRTmpSDWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSDWord \ mov _size, __WFRRTmpSDWord \ __RRFindFirstFile_End##__I__: \ __IncI__ #define __remoteFindNextFile(_conn, _handle, _name, _size, _result) \ __remoteGenericByteCommand(_conn, __SCFindNextPacket, _handle, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRFindNextFile_End##__I__, _result \ brcmp NEQ, __RRFindNextFile_End##__I__, __WFRRAvail, 26 \ index _handle, __WFRRBuffer, NA \ arrsubset _name, __WFRRBuffer, 1, 20 \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 21, 5 \ unflatten __WFRRTmpSDWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSDWord \ mov _size, __WFRRTmpSDWord \ __RRFindNextFile_End##__I__: \ __IncI__ #define __remoteGetFirmwareVersion(_conn, _pmin, _pmaj, _fmin, _fmaj, _result) \ __connectionSCDCWrite(_conn, __SCGetFirmwareVerPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGetFirmwareVersion_End##__I__, _result \ brcmp NEQ, __RRGetFirmwareVersion_End##__I__, __WFRRAvail, 5 \ index _pmin, __WFRRBuffer, NA \ index _pmaj, __WFRRBuffer, 1 \ index _fmin, __WFRRBuffer, 2 \ index _fmaj, __WFRRBuffer, 3 \ __RRGetFirmwareVersion_End##__I__: \ __IncI__ #define __remoteOpenWriteLinear(_conn, _filename, _size, _handle, _result) \ __remoteGenericCreateFileCommand(_conn, __SCOpenWriteLinearPacket, _filename, _size, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RROWL_End##__I__, _result \ brcmp NEQ, __RROWL_End##__I__, __WFRRAvail, 2 \ index _handle, __WFRRBuffer, NA \ __RROWL_End##__I__: \ __IncI__ #define __remoteOpenWriteData(_conn, _filename, _size, _handle, _result) \ __remoteGenericCreateFileCommand(_conn, __SCOpenWriteDataPacket, _filename, _size, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RROWD_End##__I__, _result \ brcmp NEQ, __RROWD_End##__I__, __WFRRAvail, 2 \ index _handle, __WFRRBuffer, NA \ __RROWD_End##__I__: \ __IncI__ #define __remoteOpenAppendData(_conn, _filename, _handle, _size, _result) \ __remoteGenericFilenameCommand(_conn, __SCOpenAppendDataPacket, _filename, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RROAD_End##__I__, _result \ brcmp NEQ, __RROAD_End##__I__, __WFRRAvail, 6 \ index _handle, __WFRRBuffer, NA \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 1, 5 \ unflatten __WFRRTmpSDWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSDWord \ mov _size, __WFRRTmpSDWord \ __RROAD_End##__I__: \ __IncI__ #define __remoteGetDeviceInfo(_conn, _name, _btaddr, _btsignal, _freemem, _result) \ __connectionSCDCWrite(_conn, __SCGetDeviceInfoPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGetDeviceInfo_End##__I__, _result \ brcmp NEQ, __RRGetDeviceInfo_End##__I__, __WFRRAvail, 31 \ arrsubset _name, __WFRRBuffer, NA, 15 \ arrsubset _btaddr, __WFRRBuffer, 15, 7 \ arrsubset _btsignal, __WFRRBuffer, 22, 4 \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 26, 5 \ unflatten __WFRRTmpSDWord, __WFRRUnflattenErr, __WFRRTmpBuffer, __WFRRTmpSDWord \ mov _freemem, __WFRRTmpSDWord \ __RRGetDeviceInfo_End##__I__: \ __IncI__ #define __remotePollCommandLength(_conn, _bufnum, _length, _result) \ __remoteGenericByteCommand(_conn, __SCPollCommandLenPacket, _bufnum, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRPollCommandLength_End##__I__, _result \ brcmp NEQ, __RRPollCommandLength_End##__I__, __WFRRAvail, 3 \ index _length, __WFRRBuffer, 1 \ __RRPollCommandLength_End##__I__: \ __IncI__ #define __remotePollCommand(_conn, _bufnum, _len, _data, _result) \ mov _result, 1 \ brcmp GT, __RRPollCommand_End##__I__, _len, 58 \ __remoteDoPollCommand(_conn, _bufnum, _len, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ add __WFRRTmpByte, _len, 3 \ brtst NEQ, __RRPollCommand_End##__I__, _result \ brcmp NEQ, __RRPollCommand_End##__I__, __WFRRAvail, __WFRRTmpByte \ index _len, __WFRRBuffer, 1 \ arrsubset _data, __WFRRBuffer, 2, _len \ __RRPollCommand_End##__I__: \ __IncI__ #define __remoteIOMapRead(_conn, _id, _offset, _numbytes, _data, _result) \ mov _result, 1 \ brcmp GT, __RRIOMapRead_End##__I__, _numbytes, 58 \ __remoteDoIOMapRead(_conn, _id, _offset, _numbytes, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ add __WFRRTmpByte, _numbytes, 7 \ brtst NEQ, __RRIOMapRead_End##__I__, _result \ brcmp NEQ, __RRIOMapRead_End##__I__, __WFRRAvail, __WFRRTmpByte \ arrsubset __WFRRTmpBuffer, __WFRRBuffer, 4, 2 \ arrtostr __WFRRUnflattenBuf, __WFRRTmpBuffer \ unflatten __WFRRTmpSWord, __WFRRUnflattenErr, __WFRRUnflattenBuf, __WFRRTmpSWord \ mov _numbytes, __WFRRTmpSWord \ arrsubset _data, __WFRRBuffer, 6, _numbytes \ __RRIOMapRead_End##__I__: \ __IncI__ #define __remoteGetBluetoothAddress(_conn, _btaddr, _result) \ __connectionSCDCWrite(_conn, __SCBTGetAddressPacket, _result) \ call __DoWaitForRemoteResponse \ mov _result, __WFRRStatus \ brtst NEQ, __RRGetBluetoothAddress_End##__I__, _result \ brcmp NEQ, __RRGetBluetoothAddress_End##__I__, __WFRRAvail, 8 \ arrsubset _btaddr, __WFRRBuffer, NA, 7 \ __RRGetBluetoothAddress_End##__I__: \ __IncI__ #define __remoteRenameFile(_conn, _oldname, _newname, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __SCRenameFilePacket \ strsubset __SRSTmpBuf, _oldname, NA, 19 \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ strsubset __SRSTmpBuf, _newname, NA, 19 \ replace __SRSSendBuf, __SRSSendBuf, 22, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #else #define __remoteGetOutputState(_conn, _port, _result) __remoteGenericByteCommand(_conn, __DCGetOutputStatePacket, _port, _result) #define __remoteGetInputValues(_conn, _port, _result) __remoteGenericByteCommand(_conn, __DCGetInputValuesPacket, _port, _result) #define __remoteGetBatteryLevel(_conn, _result) __connectionSCDCWrite(_conn, __DCGetBatteryLevelPacket, _result) #define __remoteLowspeedGetStatus(_conn, _result) __connectionSCDCWrite(_conn, __DCLSGetStatusPacket, _result) #define __remoteLowspeedRead(_conn, _port, _result) __remoteGenericByteCommand(_conn, __DCLSReadPacket, _port, _result) #define __remoteGetCurrentProgramName(_conn, _result) __connectionSCDCWrite(_conn, __DCGetCurProgNamePacket, _result) #define __remoteDatalogRead(_conn, _remove, _result) __remoteGenericByteCommand(_conn, __DCDatalogReadPacket, _remove, _result) #define __remoteGetContactCount(_conn, _result) __connectionSCDCWrite(_conn, __DCBTGetContactCntPacket, _result) #define __remoteGetContactName(_conn, _idx, _result) __remoteGenericByteCommand(_conn, __DCBTGetContactNamePacket, _idx, _result) #define __remoteGetConnectionCount(_conn, _result) __connectionSCDCWrite(_conn, __DCBTGetConnectCntPacket, _result) #define __remoteGetConnectionName(_conn, _idx, _result) __remoteGenericByteCommand(_conn, __DCBTGetConnectNamePacket, _idx, _result) #define __remoteGetProperty(_conn, _property, _result) __remoteGenericByteCommand(_conn, __DCGetPropertyPacket, _property, _result) #define __remoteOpenRead(_conn, _filename, _result) __remoteGenericFilenameCommand(_conn, __SCOpenReadPacket, _filename, _result) #define __remoteOpenWrite(_conn, _filename, _size, _result) __remoteGenericCreateFileCommand(_conn, __SCOpenWritePacket, _filename, _size, _result) #define __remoteRead(_conn, _handle, _numbytes, _result) __remoteDoRead(_conn, _handle, _numbytes, _result) #define __remoteWrite(_conn, _handle, _data, _result) __remoteDoWrite(_conn, _handle, _data, _result) #define __remoteCloseFile(_conn, _handle, _result) __remoteGenericByteCommand(_conn, __SCClosePacket, _handle, _result) #define __remoteDeleteFile(_conn, _filename, _result) __remoteGenericFilenameCommand(_conn, __SCDeletePacket, _filename, _result) #define __remoteFindFirstFile(_conn, _mask, _result) __remoteGenericFilenameCommand(_conn, __SCFindFirstPacket, _mask, _result) #define __remoteFindNextFile(_conn, _handle, _result) __remoteGenericByteCommand(_conn, __SCFindNextPacket, _handle, _result) #define __remoteOpenWriteLinear(_conn, _filename, _size, _result) __remoteGenericCreateFileCommand(_conn, __SCOpenWriteLinearPacket, _filename, _size, _result) #define __remoteOpenWriteData(_conn, _filename, _size, _result) __remoteGenericCreateFileCommand(_conn, __SCOpenWriteDataPacket, _filename, _size, _result) #define __remoteOpenAppendData(_conn, _filename, _result) __remoteGenericFilenameCommand(_conn, __SCOpenAppendDataPacket, _filename, _result) #define __remotePollCommandLength(_conn, _bufnum, _result) __remoteGenericByteCommand(_conn, __SCPollCommandLenPacket, _bufnum, _result) #define __remotePollCommand(_conn, _bufnum, _len, _result) __remoteDoPollCommand(_conn, _bufnum, _len, _result) #define __remoteIOMapRead(_conn, _id, _offset, _numbytes, _result) __remoteDoIOMapRead(_conn, _id, _offset, _numbytes, _result) #endif #define __remoteDatalogSetTimes(_conn, _synctime, _result) \ acquire __RemoteMutex \ mov __SRSTmpLongVal, _synctime \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ arrbuild __SRSSendBuf, __DCDatalogSetTimesPacket, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteSetProperty(_conn, _prop, _value, _result) \ compchk EQ, sizeof(_prop), 1 \ acquire __RemoteMutex \ flatten __SRSFlattenBuf, _value \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ arrbuild __SRSSendBuf, __DCSetPropertyPacket, _prop, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteLowspeedWrite(_conn, _port, _txlen, _rxlen, _data, _result) \ compchk EQ, sizeof(_port), 1 \ compchk EQ, sizeof(_txlen), 1 \ compchk EQ, sizeof(_rxlen), 1 \ acquire __RemoteMutex \ arrbuild __SRSSendBuf, __DCLSWritePacket, _port, _txlen, _rxlen, _data \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteIOMapWriteValue(_conn, _id, _offset, _value, _result) \ compchk EQ, sizeof(_handle), 1 \ acquire __RemoteMutex \ mov __SRSSendBuf, __GenericIOMapPacket \ replace __SRSSendBuf, __SRSSendBuf, NA, __SCIOMapWritePacket \ mov __SRSTmpLongVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ mov __SRSTmpWordVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 6, __SRSTmpBuf \ set __SRSTmpWordVal, sizeof(_value) \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 8, __SRSTmpBuf \ flatten __SRSFlattenBuf, _value \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ mov __SRSFlattenBuf, __SRSSendBuf \ arrbuild __SRSSendBuf, __SRSFlattenBuf, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteIOMapWriteBytes(_conn, _id, _offset, _data, _result) \ compchk EQ, sizeof(_handle), 1 \ acquire __RemoteMutex \ mov __SRSSendBuf, __GenericIOMapPacket \ replace __SRSSendBuf, __SRSSendBuf, NA, __SCIOMapWritePacket \ mov __SRSTmpLongVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpLongVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ mov __SRSTmpWordVal, _offset \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 6, __SRSTmpBuf \ arrsize __SRSTmpWordVal, _data \ flatten __SRSFlattenBuf, __SRSTmpWordVal \ strtoarr __SRSTmpBuf, __SRSFlattenBuf \ replace __SRSSendBuf, __SRSSendBuf, 8, __SRSTmpBuf \ mov __SRSFlattenBuf, __SRSSendBuf \ arrbuild __SRSSendBuf, __SRSFlattenBuf, _data \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #define __remoteSetBrickName(_conn, _name, _result) \ acquire __RemoteMutex \ mov __SRSSendBuf, __SCSetBrickNamePacket \ strsubset __SRSTmpBuf, _name, NA, 15 \ replace __SRSSendBuf, __SRSSendBuf, 2, __SRSTmpBuf \ __connectionSCDCWrite(_conn, __SRSSendBuf, _result) \ release __RemoteMutex #if defined(__ENHANCED_FIRMWARE) #define __SQRT(_X,_R) sqrt _R, _X #define __SIN(_X,_R) sin _R, _X #define __COS(_X,_R) cos _R, _X #define __ASIN(_X,_R) asin _R, _X #define __ACOS(_X,_R) acos _R, _X #else #if (__FIRMWARE_VERSION > 107) #define __SQRT(_X,_R) sqrt _R, _X #else #define __SQRT(_X,_R) \ acquire __sqrtMutex \ mov __sqrtValue, _X \ call __sqrtSub \ mov _R, __sqrtResult \ release __sqrtMutex #endif #define __SIN(_X,_R) \ acquire __sinMutex \ mov __sinValue, _X \ call __sinSub \ mov _R, __sinResult \ release __sinMutex #define __COS(_X,_R) \ acquire __sinMutex \ mov __sinValue, _X \ add __sinValue, __sinValue, 90 \ call __sinSub \ mov _R, __sinResult \ release __sinMutex #define __ASIN(_X,_R) \ acquire __asinMutex \ mov __asinValue, _X \ call __asinSub \ mov _R, __asinResult \ release __asinMutex #define __ACOS(_X,_R) \ acquire __asinMutex \ mov __asinValue, _X \ call __asinSub \ sub _R, 90, __asinResult \ release __asinMutex #endif // data segment dseg segment // sin/cos related tables __sin_table sword[] 0,2,3,5,7,9,10,12,14,16,17,19,21,22,24,26,28,29,31,33,34,36,37,39,41,42,44,45,47,48,50,52,53,54,56,57,59,60,62,63,64,66,67,68,69,71,72,73,74,75,77,78,79,80,81,82,83,84,85,86,87,87,88,89,90,91,91,92,93,93,94,95,95,96,96,97,97,97,98,98,98,99,99,99,99,100,100,100,100,100,100 __asin_table sdword[] 0,1,1,2,2,3,3,4,5,5,6,6,7,7,8,9,9,10,10,11,12,12,13,13,14,14,15,16,16,17,17,18,19,19,20,20,21,22,22,23,24,24,25,25,26,27,27,28,29,29,30,31,31,32,33,33,34,35,35,36,37,38,38,39,40,41,41,42,43,44,44,45,46,47,48,49,49,50,51,52,53,54,55,56,57,58,59,60,62,63,64,66,67,68,70,72,74,76,79,82,90 // mutexes __sqrtMutex mutex __sinMutex mutex __asinMutex mutex // sqrt variables __sqrtPairs byte[] 0, 0, 0, 0, 0, 0 __sqrtPaircount sbyte __sqrtValue dword __sqrtResult dword __sqrtP dword __sqrtR dword __sqrtM dword __sqrtN dword // sin variables __sinValue sdword __sinResult sdword __sinValueNeg byte // asin variables __asinValue sdword __asinResult sdword dseg ends subroutine __sinSub // move the sin to + angle set __sinValueNeg, FALSE brtst GTEQ, __sinValuePos, __sinValue neg __sinValue, __sinValue set __sinValueNeg, TRUE __sinValuePos: // get the 360 mod and check which quarter the sin falls into mod __sinValue, __sinValue, 360 brcmp GT, __sinQ4, __sinValue, 270 brcmp GT, __sinQ3, __sinValue, 180 brcmp GT, __sinQ2, __sinValue, 90 // 1st quarter index __sinResult, __sin_table, __sinValue jmp __sinAlmostDone __sinQ2: // 2nd quarter sub __sinValue, 180, __sinValue index __sinResult, __sin_table, __sinValue jmp __sinAlmostDone __sinQ3: // 3rd quarter sub __sinValue, __sinValue, 180 index __sinResult, __sin_table, __sinValue neg __sinResult, __sinResult jmp __sinAlmostDone __sinQ4: // 4th quarter sub __sinValue, 360, __sinValue index __sinResult, __sin_table, __sinValue neg __sinResult, __sinResult jmp __sinAlmostDone __sinAlmostDone: // if the incoming angle was <0, need to negate the result because sin(-x)=-sin(x) brcmp EQ, __sinDone, __sinValueNeg, FALSE neg __sinResult, __sinResult __sinDone: return ends subroutine __asinSub // input sin value should be -1 -> 1 brcmp GT, __asinValueBad, __asinValue, 100 brcmp LT, __asinValueBad, __asinValue, -100 // check if it's 0->-1 brtst LT, __asinValueNeg, __asinValue // value 0->1 index __asinResult, __asin_table, __asinValue jmp __asinDone __asinValueNeg: // value 0->-1 neg __asinValue, __asinValue index __asinResult, __asin_table, __asinValue neg __asinResult, __asinResult jmp __asinDone __asinValueBad: set __asinResult, 101 __asinDone: return ends subroutine __sqrtSub // if the input value is 0, we're done set __sqrtResult, 0 brtst EQ, __sqrtDone, __sqrtValue // init the paircount array mov __sqrtPaircount, 0 replace __sqrtPairs, __sqrtPairs, 0, 0 replace __sqrtPairs, __sqrtPairs, 1, 0 replace __sqrtPairs, __sqrtPairs, 2, 0 replace __sqrtPairs, __sqrtPairs, 3, 0 replace __sqrtPairs, __sqrtPairs, 4, 0 __sqrtPairsLoop: brtst EQ, __sqrtPairsOK, __sqrtValue mod __sqrtN, __sqrtValue, 100 replace __sqrtPairs, __sqrtPairs, __sqrtPaircount, __sqrtN div __sqrtValue, __sqrtValue, 100 add __sqrtPaircount, __sqrtPaircount, 1 jmp __sqrtPairsLoop __sqrtPairsOK: // get the leftmost pair index __sqrtP, __sqrtPairs, __sqrtPaircount set __sqrtResult, 1 // find the sqrt for the leftmost pair (1-9), if 0 we're not here! __sqrtFirstLoop: mul __sqrtN, __sqrtResult, __sqrtResult brcmp GT, __sqrtFirstOK, __sqrtN, __sqrtP add __sqrtResult, __sqrtResult, 1 jmp __sqrtFirstLoop __sqrtFirstOK: sub __sqrtResult, __sqrtResult, 1 // got the sqrt of the first pair in sqrtResult mul __sqrtN, __sqrtResult, __sqrtResult sub __sqrtM, __sqrtP, __sqrtN // in loop we get 1 new digit in sqrtResult for each pair __sqrtBigLoop: sub __sqrtPaircount, __sqrtPaircount, 1 brtst LT, __sqrtDone, __sqrtPaircount mul __sqrtM, __sqrtM, 100 index __sqrtP, __sqrtPairs, __sqrtPaircount add __sqrtM, __sqrtM, __sqrtP // find the next digit set __sqrtN, 1 __sqrtDigitLoop: mul __sqrtR, __sqrtResult, 20 add __sqrtR, __sqrtR, __sqrtN mul __sqrtR, __sqrtR, __sqrtN brcmp GT, __sqrtDigitDone, __sqrtR, __sqrtM add __sqrtN, __sqrtN, 1 jmp __sqrtDigitLoop __sqrtDigitDone: sub __sqrtN, __sqrtN, 1 // got the next digit // calculate the new value to continue with mul __sqrtR, __sqrtResult, 20 add __sqrtR, __sqrtR, __sqrtN mul __sqrtR, __sqrtR, __sqrtN sub __sqrtM, __sqrtM, __sqrtR // add the new digit to the end of the result in sqrtResult mul __sqrtResult, __sqrtResult, 10 add __sqrtResult, __sqrtResult, __sqrtN jmp __sqrtBigLoop __sqrtDone: return ends dseg segment __bcd2DecTens byte __bcd2DecOnes byte __bcd2DecMutex mutex dseg ends #define __bcd2dec(_bcd, _result) \ acquire __bcd2DecMutex \ div __bcd2DecTens, _bcd, 16 \ mod __bcd2DecOnes, _bcd, 16 \ mul _result, __bcd2DecTens, 10 \ add _result, _result, __bcd2DecOnes \ release __bcd2DecMutex #define __SetSensorHTEOPD(_port, _bStd) \ setin IN_TYPE_LIGHT_ACTIVE+_bStd, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #define __ReadSensorHTEOPD(_port, _val) \ getin _val, _port, RawValueField \ sub _val, 1023, _val #define __SetSensorHTGyro(_port) \ setin IN_TYPE_LIGHT_INACTIVE, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #define __ReadSensorHTGyro(_port, _offset, _val) \ getin _val, _port, RawValueField \ sub _val, _val, 600 \ sub _val, _val, _offset #define __ReadSensorHTMagnet(_port, _offset, _val) __ReadSensorHTGyro(_port, _offset, _val) #define __SetSensorHTMagnet(_port) __SetSensorHTGyro(_port) dseg segment __HTMplexRaw word __HTMplexScaled dword __HTMplexMutex mutex dseg ends #define __ReadSensorHTTouchMultiplexer(_p, _t1, _t2, _t3, _t4) \ acquire __HTMplexMutex \ getin __HTMplexRaw, _p, RawValueField \ mul __HTMplexScaled, __HTMplexRaw, 339 \ sub __HTMplexScaled, 346797, __HTMplexScaled \ div __HTMplexScaled, __HTMplexScaled, __HTMplexRaw \ add __HTMplexScaled, __HTMplexScaled, 5 \ div __HTMplexScaled, __HTMplexScaled, 10 \ and _t4, __HTMplexScaled, 8 \ and _t3, __HTMplexScaled, 4 \ and _t2, __HTMplexScaled, 2 \ and _t1, __HTMplexScaled, 1 \ release __HTMplexMutex dseg segment __HTPFStartIRLink byte[] 0x02, 0x42 __HTPFCommitIRLink byte[] 0x0B, 0x02, 0x01 __HTPFBits byte[] __HTPFI2CBuf byte[] __HTPFI sword __HTPFJ sword __HTPFValue byte __HTPFDx byte __PFBytes byte[] __PFMutex mutex __PFNx byte __PFPowerFuncMode byte __PFTmp byte __PFNibbles byte[] 0x00, 0x00, 0x00, 0x00 __PF_p1 byte __PF_p2 byte __PF_p3 byte __PF_p4 byte __PF_p5 byte __PFIdx byte __PFChToggle byte __PFToggles byte[] 0x00, 0x00, 0x00, 0x00 __RCToggles byte[] 0x00, 0x00, 0x00, 0x00 dseg ends subroutine __PFApplyToggle mov __PFIdx, __PF_p1 index __PFChToggle, __PFToggles, __PFIdx add __PF_p1, __PF_p1, __PFChToggle return ends subroutine __PFUpdateToggle xor __PFChToggle, __PFChToggle, 8 replace __PFToggles, __PFToggles, __PFIdx, __PFChToggle return ends subroutine __RCApplyToggle mov __PFIdx, __PF_p1 index __PFChToggle, __RCToggles, __PFIdx add __PF_p1, __PF_p1, __PFChToggle return ends subroutine __RCUpdateToggle xor __PFChToggle, __PFChToggle, 8 replace __RCToggles, __RCToggles, __PFIdx, __PFChToggle return ends subroutine __PFCalcChecksum // RCTrain or Power Function brtst EQ, __PFUseIRTrainMode, __PFPowerFuncMode index __PFNx, __PFNibbles, NA xor __PFTmp, 0xF, __PFNx index __PFNx, __PFNibbles, 1 xor __PFTmp, __PFTmp, __PFNx index __PFNx, __PFNibbles, 2 xor __PFTmp, __PFTmp, __PFNx jmp __PFEndPowerFuncModeCheck __PFUseIRTrainMode: index __PFNx, __PFNibbles, NA sub __PFTmp, 0xF, __PFNx index __PFNx, __PFNibbles, 1 sub __PFTmp, __PFTmp, __PFNx index __PFNx, __PFNibbles, 2 sub __PFTmp, __PFTmp, __PFNx __PFEndPowerFuncModeCheck: replace __PFNibbles, __PFNibbles, 3, __PFTmp return ends subroutine __PFComboDirectSub call __PFApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 replace __PFNibbles, __PFNibbles, 1, PF_MODE_COMBO_DIRECT mul __PF_p3, __PF_p3, 4 add __PF_p3, __PF_p3, __PF_p2 replace __PFNibbles, __PFNibbles, 2, __PF_p3 call __PFUpdateToggle return ends subroutine __PFSinglePinSub call __PFApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 set __PF_p1, PF_MODE_SINGLE_PIN_TIME brtst EQ, __PFEndIfSPContinuous, __PF_p5 set __PF_p1, PF_MODE_SINGLE_PIN_CONT __PFEndIfSPContinuous: replace __PFNibbles, __PFNibbles, 1, __PF_p1 mul __PF_p2, __PF_p2, 8 mul __PF_p3, __PF_p3, 4 add __PF_p2, __PF_p2, __PF_p3 add __PF_p2, __PF_p2, __PF_p4 replace __PFNibbles, __PFNibbles, 2, __PF_p2 call __PFUpdateToggle return ends subroutine __PFSingleOutputSub call __PFApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 set __PF_p1, PF_MODE_SINGLE_OUTPUT_PWM brtst EQ, __PFEndIfSOCst, __PF_p4 set __PF_p1, PF_MODE_SINGLE_OUTPUT_CST __PFEndIfSOCst: add __PF_p1, __PF_p1, __PF_p2 replace __PFNibbles, __PFNibbles, 1, __PF_p1 replace __PFNibbles, __PFNibbles, 2, __PF_p3 call __PFUpdateToggle return ends subroutine __PFComboPWMSub call __PFApplyToggle add __PF_p1, __PF_p1, PF_MODE_COMBO_PWM replace __PFNibbles, __PFNibbles, NA, __PF_p1 replace __PFNibbles, __PFNibbles, 1, __PF_p3 replace __PFNibbles, __PFNibbles, 2, __PF_p2 call __PFUpdateToggle return ends subroutine __PFTrainSub call __PFApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 replace __PFNibbles, __PFNibbles, 1, PF_MODE_TRAIN replace __PFNibbles, __PFNibbles, 2, __PF_p2 call __PFUpdateToggle return ends subroutine __RCTrainSub call __RCApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 replace __PFNibbles, __PFNibbles, 1, PF_MODE_TRAIN replace __PFNibbles, __PFNibbles, 2, __PF_p2 call __RCUpdateToggle return ends subroutine __PFRawOutputSub call __PFApplyToggle replace __PFNibbles, __PFNibbles, NA, __PF_p1 replace __PFNibbles, __PFNibbles, 1, __PF_p2 replace __PFNibbles, __PFNibbles, 2, __PF_p3 call __PFUpdateToggle return ends subroutine __HTPowerFunctionCalcBits call __PFCalcChecksum brtst EQ, __HTPFUseIRTrainMode, __PFPowerFuncMode set __HTPFDx, 3 jmp __HTPFEndPowerFuncModeCheck __HTPFUseIRTrainMode: set __HTPFDx, 2 __HTPFEndPowerFuncModeCheck: arrinit __HTPFBits, 0, 88 arrinit __PFBytes, 0, 11 // fill in the bits set __PFIdx, 0 replace __HTPFBits, __HTPFBits, __PFIdx, 1 add __PFIdx, __PFIdx, 8 // check bits in n0..n3 set __HTPFI, 0 __lblCalcBitsForIBitSet: index __PFNx, __PFNibbles, __HTPFI set __HTPFJ, 3 __lblCalcBitsForJBitSet: replace __HTPFBits, __HTPFBits, __PFIdx, 1 shl __PFTmp, 1, __HTPFJ and __HTPFValue, __PFNx, __PFTmp add __PFIdx, __PFIdx, __HTPFDx brcmp NEQ, __lblCalcBitsFoundZero, __HTPFValue, __PFTmp add __PFIdx, __PFIdx, 2 __lblCalcBitsFoundZero: sub __HTPFJ, __HTPFJ, 1 brtst GTEQ, __lblCalcBitsForJBitSet, __HTPFJ add __HTPFI, __HTPFI, 1 brcmp LTEQ, __lblCalcBitsForIBitSet, __HTPFI, 3 replace __HTPFBits, __HTPFBits, __PFIdx, 1 // now calculate bytes set __HTPFI, 0 __lblCalcBitsWhileIByteCalc: set __HTPFValue, 0 set __HTPFJ, 0 __lblCalcBitsForJByteCalc: index __PFTmp, __HTPFBits, __HTPFI add __HTPFValue, __HTPFValue, __PFTmp brcmp GTEQ, __lblCalcBitsByteCalcLastBit, __HTPFJ, 7 mul __HTPFValue, __HTPFValue, 2 __lblCalcBitsByteCalcLastBit: add __HTPFI, __HTPFI, 1 add __HTPFJ, __HTPFJ, 1 brcmp LTEQ, __lblCalcBitsForJByteCalc, __HTPFJ, 7 div __PFIdx, __HTPFI, 8 sub __PFIdx, __PFIdx, 1 replace __PFBytes, __PFBytes, __PFIdx, __HTPFValue brcmp LT, __lblCalcBitsWhileIByteCalc, __HTPFI, 88 // set IRLink mode to either PF or IRTrain sub __HTPFDx, __HTPFDx, 1 replace __HTPFCommitIRLink, __HTPFCommitIRLink, 1, __HTPFDx // build i2c buffer arrbuild __HTPFI2CBuf, __HTPFStartIRLink, __PFBytes, __HTPFCommitIRLink return ends #define __HTPFComboDirect(_port, _channel, _outa, _outb, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _outa, 4 \ mod __PF_p3, _outb, 4 \ call __PFComboDirectSub \ set __PFPowerFuncMode, TRUE \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTPFSinglePin(_port, _channel, _out, _pin, _func, _cont, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _out, 2 \ mod __PF_p3, _pin, 2 \ mod __PF_p4, _func, 4 \ set __PF_p5, _cont \ call __PFSinglePinSub \ set __PFPowerFuncMode, TRUE \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTPFSingleOutput(_port, _channel, _out, _func, _cst, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _out, 2 \ mod __PF_p3, _func, 16 \ set __PF_p4, _cst \ call __PFSingleOutputSub \ set __PFPowerFuncMode, TRUE \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTPFComboPWM(_port, _channel, _outa, _outb, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _outa, 16 \ mod __PF_p3, _outb, 16 \ call __PFComboPWMSub \ set __PFPowerFuncMode, TRUE \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTIRTrain(_port, _channel, _func, _PFMode, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _func, 5 \ compif EQ, _PFMode, TRUE \ call __PFTrainSub \ compelse \ call __RCTrainSub \ compend \ set __PFPowerFuncMode, _PFMode \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTPFRawOutput(_port, _nibble0, _nibble1, _nibble2, _result) \ acquire __PFMutex \ mod __PF_p1, _nibble0, 7 \ mod __PF_p2, _nibble1, 16 \ mod __PF_p3, _nibble2, 16 \ call __PFRawOutputSub \ set __PFPowerFuncMode, TRUE \ call __HTPowerFunctionCalcBits \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs0 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ syscall CommLSWrite, __CLSWArgs##_port \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ compend #define __HTPFRepeatLastCommand(_port, _count, _delay, _result) \ acquire __PFMutex \ mov __PF_p1, _count \ compif EQ, isconst(_port), FALSE \ acquire __CLSWMutex0 \ acquire __CLSWMutex1 \ acquire __CLSWMutex2 \ acquire __CLSWMutex3 \ mov __CLSWArgs0.Buffer, __HTPFI2CBuf \ release __PFMutex \ mov __CLSWArgs0.Port, _port \ mov __CLSWArgs0.ReturnLen, 0 \ __HTPFRepeatLoop##__I__: \ syscall CommLSWrite, __CLSWArgs0 \ waitv _delay \ sub __PF_p1, __PF_p1, 1 \ brtst GT, __HTPFRepeatLoop##__I__, __PF_p1 \ mov _result, __CLSWArgs0.Result \ release __CLSWMutex0 \ release __CLSWMutex1 \ release __CLSWMutex2 \ release __CLSWMutex3 \ __IncI__ \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __CLSWMutex##_port \ mov __CLSWArgs##_port.Buffer, __HTPFI2CBuf \ release __PFMutex \ set __CLSWArgs##_port.Port, _port \ mov __CLSWArgs##_port.ReturnLen, 0 \ __HTPFRepeatLoop##__I__: \ syscall CommLSWrite, __CLSWArgs##_port \ waitv _delay \ sub __PF_p1, __PF_p1, 1 \ brtst GT, __HTPFRepeatLoop##__I__, __PF_p1 \ mov _result, __CLSWArgs##_port.Result \ release __CLSWMutex##_port \ __IncI__ \ compend dseg segment TRCXCommand struct Port byte Address byte ResponseBytes byte Command byte[] Response byte[] TRCXCommand ends __gRCXCmd TRCXCommand __RCXCmdMutex mutex dseg ends subroutine __HTRCXCommandSub dseg segment __RCSToggle byte __RCSI byte __RCSInCmd byte[] __RCSCmdBytes sbyte __RCSCmd byte __RCSCSum byte __RCSMsgBufSize byte __RCSTotalBytes byte __RCSTmpByte byte __RCSTmpByte2 byte __RCSResult byte __RCSHeaderMsg byte[] 0x02, 0x4a, 0x55, 0xff, 0x00, 0x03, 0x00, 0x01 dseg ends arrsize __RCSCmdBytes, __gRCXCmd.Command index __RCSCmd, __gRCXCmd.Command, NA set __RCSCSum, 0 replace __RCSHeaderMsg, __RCSHeaderMsg, NA, __gRCXCmd.Address // send the IR message __lowspeedWrite(__gRCXCmd.Port, 0, __RCSHeaderMsg, __RCSTmpByte) wait 12 // build rest of the message set __RCSMsgBufSize, 2 mul __RCSMsgBufSize, __RCSMsgBufSize, __RCSCmdBytes add __RCSMsgBufSize, __RCSMsgBufSize, 7 add __RCSTotalBytes, __RCSMsgBufSize, __gRCXCmd.ResponseBytes arrinit __RCSInCmd, 0, __RCSMsgBufSize replace __RCSInCmd, __RCSInCmd, NA, __gRCXCmd.Address set __RCSTmpByte, 2 mul __RCSTmpByte, __RCSTmpByte, __RCSCmdBytes sub __RCSTmpByte, 0x4b, __RCSTmpByte replace __RCSInCmd, __RCSInCmd, 1, __RCSTmpByte // put cmd and ~cmd into msg or __RCSTmpByte, __RCSCmd, __RCSToggle replace __RCSInCmd, __RCSInCmd, 2, __RCSTmpByte mov __RCSCSum, __RCSTmpByte sub __RCSTmpByte, 0xFF, __RCSTmpByte replace __RCSInCmd, __RCSInCmd, 3, __RCSTmpByte set __RCSI, 0 xor __RCSToggle, __RCSToggle, 8 brcmp LTEQ, __RCSEndWhileILTCmdBytes, __RCSCmdBytes, 1 __RCSWhileILTCmdBytes: sub __RCSTmpByte, __RCSCmdBytes, 1 brcmp GTEQ, __RCSEndWhileILTCmdBytes, __RCSI, __RCSTmpByte add __RCSTmpByte, __RCSI, 1 index __RCSTmpByte2, __gRCXCmd.Command, __RCSTmpByte mul __RCSTmpByte, __RCSI, 2 add __RCSTmpByte, __RCSTmpByte, 4 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, __RCSTmpByte2 add __RCSCSum, __RCSCSum, __RCSTmpByte2 add __RCSTmpByte, __RCSTmpByte, 1 sub __RCSTmpByte2, 0xFF, __RCSTmpByte2 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, __RCSTmpByte2 add __RCSI, __RCSI, 1 jmp __RCSWhileILTCmdBytes __RCSEndWhileILTCmdBytes: mul __RCSTmpByte, __RCSI, 2 add __RCSTmpByte, __RCSTmpByte, 4 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, __RCSCSum sub __RCSTmpByte2, 0xFF, __RCSCSum add __RCSTmpByte, __RCSTmpByte, 1 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, __RCSTmpByte2 // fill in the last three bytes add __RCSTmpByte, __RCSTmpByte, 1 mul __RCSTmpByte2, __RCSCmdBytes, 2 add __RCSTmpByte2, __RCSTmpByte2, 2 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, __RCSTmpByte2 add __RCSTmpByte, __RCSTmpByte, 1 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, 0x00 add __RCSTmpByte, __RCSTmpByte, 1 replace __RCSInCmd, __RCSInCmd, __RCSTmpByte, 0x01 // send the IR message __lowspeedWrite(__gRCXCmd.Port, 0, __RCSInCmd, __RCSTmpByte) // give the message time to be transferred mul __RCSTmpByte, __RCSTotalBytes, 5 add __RCSTmpByte, __RCSTmpByte, 10 waitv __RCSTmpByte // do we need to read a response? brtst EQ, __RCSNoResponse, __gRCXCmd.ResponseBytes arrbuild __RCSInCmd, __gRCXCmd.Address, 0x51 mov __RCSTmpByte, __gRCXCmd.ResponseBytes __ReadI2CBytes(__gRCXCmd.Port, __RCSInCmd, __RCSTmpByte, __gRCXCmd.Response, __RCSResult) __RCSNoResponse: return ends #define __HTRCXSetIRLinkPort(_port) \ set __gRCXCmd.Port, _port \ set __gRCXCmd.Address, 0x02 #define __HTRCXPoll(_src, _value, _result) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PollOp, _src, _value \ set __gRCXCmd.ResponseBytes, 12 \ call __HTRCXCommandSub \ index _result, __gRCXCmd.Response, 7 \ index __RCSTmpByte, __gRCXCmd.Response, 5 \ mul _result, _result, 256 \ add _result, _result, __RCSTmpByte \ release __RCXCmdMutex #define __HTRCXBatteryLevel(_result) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_BatteryLevelOp \ set __gRCXCmd.ResponseBytes, 12 \ call __HTRCXCommandSub \ index _result, __gRCXCmd.Response, 7 \ index __RCSTmpByte, __gRCXCmd.Response, 5 \ mul _result, _result, 256 \ add _result, _result, __RCSTmpByte \ release __RCXCmdMutex #define __HTRCXOpNoArgs(_op) \ acquire __RCXCmdMutex \ arrinit __gRCXCmd.Command, _op, 1 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetOutput(_outputs, _mode) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _mode \ arrbuild __gRCXCmd.Command, RCX_OnOffFloatOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetDirection(_outputs, _dir) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _dir \ arrbuild __gRCXCmd.Command, RCX_OutputDirOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetPower(_outputs, _pwrsrc, _pwrval) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_OutputPowerOp, _outputs, _pwrsrc, _pwrval \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXOnFwd(_outputs) \ __HTRCXSetDirection(_outputs, RCX_OUT_FWD) \ __HTRCXSetOutput(_outputs, RCX_OUT_ON) #define __HTRCXOnRev(_outputs) \ __HTRCXSetDirection(_outputs, RCX_OUT_REV) \ __HTRCXSetOutput(_outputs, RCX_OUT_ON) #define __HTRCXOnFor(_outputs, _ms) \ __HTRCXSetOutput(_outputs, RCX_OUT_ON) \ waitv _ms \ __HTRCXSetOutput(_outputs, RCX_OUT_OFF) #define __HTRCXSetTxPower(_pwr) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_IRModeOp, _pwr \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXPlaySound(_snd) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PlaySoundOp, _snd \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXDeleteTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DeleteTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXStartTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_StartTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXStopTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_StopTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSelectProgram(_prog) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SelectProgramOp, _prog \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXClearTimer(_timer) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearTimerOp, _timer \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetSleepTime(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_AutoOffOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXDeleteSub(_s) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DeleteSubOp, _s \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXClearSensor(_port) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearSensorOp, _port \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXPlayToneVar(_varnum, _duration) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PlayToneVarOp, _varnum, _duration \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetWatch(_hours, _minutes) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetWatchOp, _hours, _minutes \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetSensorType(_port, _type) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_InputTypeOp, _port, _type \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetSensorMode(_port, _mode) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_InputModeOp, _port, _mode \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXCreateDatalog(_size) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _size, 0xFF \ div __RCSTmpByte2, _size, 256 \ arrbuild __gRCXCmd.Command, RCX_SetDatalogOp, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXAddToDatalog(_src, _value) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DatalogOp, _src, _value \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSendSerial(_first, _count) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SendUARTDataOp, _first, _count \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXRemote(_cmd) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _cmd, 0xFF \ div __RCSTmpByte2, _cmd, 256 \ arrbuild __gRCXCmd.Command, RCX_RemoteOp, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXEvent(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_DirectEventOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXPlayTone(_freq, _duration) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _freq, 0xFF \ div __RCSTmpByte2, _freq, 256 \ arrbuild __gRCXCmd.Command, RCX_PlayToneOp, __RCSTmpByte, __RCSTmpByte2, _duration \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSelectDisplay(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_DisplayOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXPollMemory(_memaddress, _result) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _memaddress, 0xFF \ div __RCSTmpByte2, _memaddress, 256 \ arrbuild __gRCXCmd.Command, RCX_PollMemoryOp, __RCSTmpByte, __RCSTmpByte2, 1 \ set __gRCXCmd.ResponseBytes, 16 \ call __HTRCXCommandSub \ index _result, __gRCXCmd.Response, 7 \ index __RCSTmpByte, __gRCXCmd.Response, 5 \ mul _result, _result, 256 \ add _result, _result, __RCSTmpByte \ release __RCXCmdMutex #define __HTRCXSetEvent(_evt, _src, _type) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetEventOp, _evt, _src, _type \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetGlobalOutput(_outputs, _mode) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _mode \ arrbuild __gRCXCmd.Command, RCX_GOutputModeOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetGlobalDirection(_outputs, _dir) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _dir \ arrbuild __gRCXCmd.Command, RCX_GOutputDirOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_GOutputPowerOp, _outputs, _pwrsrc, _pwrval \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXIncCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_IncCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXDecCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DecCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXClearCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetPriority(_p) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetPriorityOp, _p \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTRCXSetMessage(_msg) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_MessageOp, _msg \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetScoutMode(_mode) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ScoutOp, _mode \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSendVLL(_src, _value) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_VLLOp, _src, _value \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetSensorClickTime(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSBlinkTimeOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetSensorHysteresis(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSHysteresisOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetSensorLowerLimit(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSLowerThreshOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetSensorUpperLimit(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSUpperThreshOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetEventFeedback(_src, _value) \ acquire __RCXCmdMutex \ and __RCSTmpByte, _value, 0xFF \ div __RCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_SetFeedbackOp, _src, __RCSTmpByte, __RCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutMuteSound() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, 0x80 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutUnmuteSound() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, 0xc0 \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSelectSounds(_grp) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, _grp \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __HTScoutSetLight(_x) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_LightOp, _x \ set __gRCXCmd.ResponseBytes, 0 \ call __HTRCXCommandSub \ release __RCXCmdMutex #define __ReadSensorHTCompass(_port, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 2 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, NA \ index __RLSBytesCountVar, __RLSReadBufVar, 1 \ add _value, _value, _value \ add _value, _value, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 2 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, NA \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 1 \ add _value, _value, _value \ add _value, _value, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorHTAccel(_port, _x, _y, _z, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _x, __RLSReadBufVar, NA \ index __RLSBytesCountVar, __RLSReadBufVar, 3 \ brcmp LTEQ, __RSHTAX##__I__, _x, 127 \ sub _x, _x, 256 \ __RSHTAX##__I__: \ __IncI__ \ mul _x, _x, 4 \ add _x, _x, __RLSBytesCountVar \ index _y, __RLSReadBufVar, 1 \ index __RLSBytesCountVar, __RLSReadBufVar, 4 \ brcmp LTEQ, __RSHTAY##__I__, _y, 127 \ sub _y, _y, 256 \ __RSHTAY##__I__: \ __IncI__ \ mul _y, _y, 4 \ add _y, _y, __RLSBytesCountVar \ index _z, __RLSReadBufVar, 2 \ index __RLSBytesCountVar, __RLSReadBufVar, 5 \ brcmp LTEQ, __RSHTAZ##__I__, _z, 127 \ sub _z, _z, 256 \ __RSHTAZ##__I__: \ __IncI__ \ mul _z, _z, 4 \ add _z, _z, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _x, __RLSReadBuf##_port, NA \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 3 \ brcmp LTEQ, __RSHTAX##__I__, _x, 127 \ sub _x, _x, 256 \ __RSHTAX##__I__: \ __IncI__ \ mul _x, _x, 4 \ add _x, _x, __RLSBytesCount##_port \ index _y, __RLSReadBuf##_port, 1 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 4 \ brcmp LTEQ, __RSHTAY##__I__, _y, 127 \ sub _y, _y, 256 \ __RSHTAY##__I__: \ __IncI__ \ mul _y, _y, 4 \ add _y, _y, __RLSBytesCount##_port \ index _z, __RLSReadBuf##_port, 2 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 5 \ brcmp LTEQ, __RSHTAZ##__I__, _z, 127 \ sub _z, _z, 256 \ __RSHTAZ##__I__: \ __IncI__ \ mul _z, _z, 4 \ add _z, _z, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend dseg segment __RSHTColorRawBuf byte[] 0x02, 0x46 __RSHTColorNormBuf byte[] 0x02, 0x4C __RSHTColor2NormBuf byte[] 0x02, 0x47 dseg ends #define __ReadSensorHTRawColor(_port, _Red, _Green, _Blue, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RSHTColorRawBuf \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _Red, __RLSReadBufVar, 1 \ index __RLSBytesCountVar, __RLSReadBufVar, NA \ mul _Red, _Red, 256 \ add _Red, _Red, __RLSBytesCountVar \ index _Green, __RLSReadBufVar, 3 \ index __RLSBytesCountVar, __RLSReadBufVar, 2 \ mul _Green, _Green, 256 \ add _Green, _Green, __RLSBytesCountVar \ index _Blue, __RLSReadBufVar, 5 \ index __RLSBytesCountVar, __RLSReadBufVar, 4 \ mul _Blue, _Blue, 256 \ add _Blue, _Blue, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RSHTColorRawBuf \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _Red, __RLSReadBuf##_port, 1 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, NA \ mul _Red, _Red, 256 \ add _Red, _Red, __RLSBytesCount##_port \ index _Green, __RLSReadBuf##_port, 3 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 2 \ mul _Green, _Green, 256 \ add _Green, _Green, __RLSBytesCount##_port \ index _Blue, __RLSReadBuf##_port, 5 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 4 \ mul _Blue, _Blue, 256 \ add _Blue, _Blue, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorHTColor(_port, _ColorNum, _Red, _Green, _Blue, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 4 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _ColorNum, __RLSReadBufVar, NA \ index _Red, __RLSReadBufVar, 1 \ index _Green, __RLSReadBufVar, 2 \ index _Blue, __RLSReadBufVar, 3 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 4 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _ColorNum, __RLSReadBuf##_port, NA \ index _Red, __RLSReadBuf##_port, 1 \ index _Green, __RLSReadBuf##_port, 2 \ index _Blue, __RLSReadBuf##_port, 3 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTNormalizedColor(_port, _ColorIdx, _Red, _Green, _Blue, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RSHTColorNormBuf \ set __RLSBytesCountVar, 4 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _ColorIdx, __RLSReadBufVar, NA \ index _Red, __RLSReadBufVar, 1 \ index _Green, __RLSReadBufVar, 2 \ index _Blue, __RLSReadBufVar, 3 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RSHTColorNormBuf \ set __RLSBytesCount##_port, 4 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _ColorIdx, __RLSReadBuf##_port, NA \ index _Red, __RLSReadBuf##_port, 1 \ index _Green, __RLSReadBuf##_port, 2 \ index _Blue, __RLSReadBuf##_port, 3 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTColor2Active(_port, _ColorNum, _Red, _Green, _Blue, _White, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 5 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _ColorNum, __RLSReadBufVar, NA \ index _Red, __RLSReadBufVar, 1 \ index _Green, __RLSReadBufVar, 2 \ index _Blue, __RLSReadBufVar, 3 \ index _White, __RLSReadBufVar, 4 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 5 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _ColorNum, __RLSReadBuf##_port, NA \ index _Red, __RLSReadBuf##_port, 1 \ index _Green, __RLSReadBuf##_port, 2 \ index _Blue, __RLSReadBuf##_port, 3 \ index _White, __RLSReadBuf##_port, 4 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTNormalizedColor2Active(_port, _ColorIdx, _Red, _Green, _Blue, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RSHTColor2NormBuf \ set __RLSBytesCountVar, 4 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _ColorIdx, __RLSReadBufVar, NA \ index _Red, __RLSReadBufVar, 1 \ index _Green, __RLSReadBufVar, 2 \ index _Blue, __RLSReadBufVar, 3 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RSHTColor2NormBuf \ set __RLSBytesCount##_port, 5 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _ColorIdx, __RLSReadBuf##_port, NA \ index _Red, __RLSReadBuf##_port, 1 \ index _Green, __RLSReadBuf##_port, 2 \ index _Blue, __RLSReadBuf##_port, 3 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTRawColor2(_port, _Red, _Green, _Blue, _White, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 8 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _Red, __RLSReadBufVar, NA \ index __RLSBytesCountVar, __RLSReadBufVar, 1 \ mul _Red, _Red, 256 \ add _Red, _Red, __RLSBytesCountVar \ index _Green, __RLSReadBufVar, 2 \ index __RLSBytesCountVar, __RLSReadBufVar, 3 \ mul _Green, _Green, 256 \ add _Green, _Green, __RLSBytesCountVar \ index _Blue, __RLSReadBufVar, 4 \ index __RLSBytesCountVar, __RLSReadBufVar, 5 \ mul _Blue, _Blue, 256 \ add _Blue, _Blue, __RLSBytesCountVar \ index _White, __RLSReadBufVar, 6 \ index __RLSBytesCountVar, __RLSReadBufVar, 7 \ mul _White, _White, 256 \ add _White, _White, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 8 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _Red, __RLSReadBuf##_port, NA \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 1 \ mul _Red, _Red, 256 \ add _Red, _Red, __RLSBytesCount##_port \ index _Green, __RLSReadBuf##_port, 2 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 3 \ mul _Green, _Green, 256 \ add _Green, _Green, __RLSBytesCount##_port \ index _Blue, __RLSReadBuf##_port, 4 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 5 \ mul _Blue, _Blue, 256 \ add _Blue, _Blue, __RLSBytesCount##_port \ index _White, __RLSReadBuf##_port, 6 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 7 \ mul _White, _White, 256 \ add _White, _White, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRSeeker(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _dir, __RLSReadBufVar, NA \ index _s1, __RLSReadBufVar, 1 \ index _s3, __RLSReadBufVar, 2 \ index _s5, __RLSReadBufVar, 3 \ index _s7, __RLSReadBufVar, 4 \ index _s9, __RLSReadBufVar, 5 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _dir, __RLSReadBuf##_port, NA \ index _s1, __RLSReadBuf##_port, 1 \ index _s3, __RLSReadBuf##_port, 2 \ index _s5, __RLSReadBuf##_port, 3 \ index _s7, __RLSReadBuf##_port, 4 \ index _s9, __RLSReadBuf##_port, 5 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRSeeker2DC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _avg, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, 0x10, 0x42 \ set __RLSBytesCountVar, 7 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _dir, __RLSReadBufVar, NA \ index _s1, __RLSReadBufVar, 1 \ index _s3, __RLSReadBufVar, 2 \ index _s5, __RLSReadBufVar, 3 \ index _s7, __RLSReadBufVar, 4 \ index _s9, __RLSReadBufVar, 5 \ index _avg, __RLSReadBufVar, 6 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, 0x10, 0x42 \ set __RLSBytesCount##_port, 7 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _dir, __RLSReadBuf##_port, NA \ index _s1, __RLSReadBuf##_port, 1 \ index _s3, __RLSReadBuf##_port, 2 \ index _s5, __RLSReadBuf##_port, 3 \ index _s7, __RLSReadBuf##_port, 4 \ index _s9, __RLSReadBuf##_port, 5 \ index _avg, __RLSReadBuf##_port, 6 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRSeeker2AC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, 0x10, 0x49 \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _dir, __RLSReadBufVar, NA \ index _s1, __RLSReadBufVar, 1 \ index _s3, __RLSReadBufVar, 2 \ index _s5, __RLSReadBufVar, 3 \ index _s7, __RLSReadBufVar, 4 \ index _s9, __RLSReadBufVar, 5 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, 0x10, 0x49 \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _dir, __RLSReadBuf##_port, NA \ index _s1, __RLSReadBuf##_port, 1 \ index _s3, __RLSReadBuf##_port, 2 \ index _s5, __RLSReadBuf##_port, 3 \ index _s7, __RLSReadBuf##_port, 4 \ index _s9, __RLSReadBuf##_port, 5 \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRSeeker2Addr(_port, _reg, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, 0x10, _reg \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, 0x10, _reg \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __SetHTIRSeeker2Mode(_port, _mode, _result) __I2CSendCmd(_port, 0x10, _mode, _result) #define __ReadSensorHTIRReceiver(_port, _pfdata, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 8 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ mov _pfdata, __RLSReadBufVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 8 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ mov _pfdata, __RLSReadBuf##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRReceiverEx(_port, _reg, _pfchar, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ add __RLSBytesCountVar, 0x42, _reg \ arrbuild __RLSReadBufVar, 0x02, __RLSBytesCountVar \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _pfchar, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ add __RLSBytesCount##_port, 0x42, _reg \ arrbuild __RLSReadBuf##_port, 0x02, __RLSBytesCount##_port \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _pfchar, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __SetHTColor2Mode(_port, _mode, _result) __I2CSendCmd(_port, 0x02, _mode, _result) #define __ReadSensorHTColorNum(_port, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __ReadSensorHTIRSeekerDir(_port, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __ResetSensorHTAngle(_port, _mode, _result) \ compchk EQ, isconst(_mode), TRUE \ __I2CSendCmd(_port, 0x02, _mode, _result) \ compif EQ, _mode, HTANGLE_MODE_CALIBRATE \ wait 30 \ compend #define __ReadSensorHTAngle(_port, _Angle, _AccAngle, _RPM, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufLSWrite1 \ set __RLSBytesCountVar, 8 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _Angle, __RLSReadBufVar, NA \ add _Angle, _Angle, _Angle \ index __RLSBytesCountVar, __RLSReadBufVar, 1 \ add _Angle, _Angle, __RLSBytesCountVar \ index _AccAngle, __RLSReadBufVar, 2 \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCountVar, __RLSReadBufVar, 3 \ add _AccAngle, _AccAngle, __RLSBytesCountVar \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCountVar, __RLSReadBufVar, 4 \ add _AccAngle, _AccAngle, __RLSBytesCountVar \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCountVar, __RLSReadBufVar, 5 \ add _AccAngle, _AccAngle, __RLSBytesCountVar \ index _RPM, __RLSReadBufVar, 6 \ mul _RPM, _RPM, 256 \ index __RLSBytesCountVar, __RLSReadBufVar, 7 \ add _RPM, _RPM, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufLSWrite1 \ set __RLSBytesCount##_port, 8 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _Angle, __RLSReadBuf##_port, NA \ add _Angle, _Angle, _Angle \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 1 \ add _Angle, _Angle, __RLSBytesCount##_port \ index _AccAngle, __RLSReadBuf##_port, 2 \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 3 \ add _AccAngle, _AccAngle, __RLSBytesCount##_port \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 4 \ add _AccAngle, _AccAngle, __RLSBytesCount##_port \ mul _AccAngle, _AccAngle, 256 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 5 \ add _AccAngle, _AccAngle, __RLSBytesCount##_port \ index _RPM, __RLSReadBuf##_port, 6 \ mul _RPM, _RPM, 256 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 7 \ add _RPM, _RPM, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __ReadI2CDeviceInfo(_port, _i2caddr, _info, _strVal) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, _info \ set __RLSBytesCountVar, 8 \ call __ReadLSBytesVar \ mov _strVal, __RLSReadBufVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, _info \ set __RLSBytesCount##_port, 8 \ call __ReadLSBytes##_port \ mov _strVal, __RLSReadBuf##_port \ release __RLSBmutex##_port \ compend #define __SetSensorMSPressure(_port) \ setin IN_TYPE_REFLECTION, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorMSDRODActive(_port) \ setin IN_TYPE_LIGHT_ACTIVE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorMSDRODInactive(_port) \ setin IN_TYPE_LIGHT_INACTIVE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) #define __SetSensorNXTSumoEyesLong(_port) \ setin IN_TYPE_LIGHT_INACTIVE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) \ wait 275 #define __SetSensorNXTSumoEyesShort(_port) \ setin IN_TYPE_LIGHT_ACTIVE, _port, TypeField \ setin IN_MODE_PCTFULLSCALE, _port, InputModeField \ __ResetSensor(_port) \ wait 275 #define __SetSensorMSTouchMux(_port) \ setin IN_TYPE_LIGHT_INACTIVE, _port, TypeField \ setin IN_MODE_RAW, _port, InputModeField \ __ResetSensor(_port) #define __ReadSensorMSPressure(_port, _value) \ getin _value, _port, RawValueField \ sub _value, 1024, _value \ div _value, _value, 25 #define __ReadSensorMSPressureRaw(_port, _value) \ getin _value, _port, RawValueField #define __ReadSensorMSDROD(_port, _value) \ getin _value, _port, NormalizedValueField #define __ReadSensorNXTSumoEyes(_port, _value) \ getin _value, _port, NormalizedValueField \ mul _value, _value, 100 \ div _value, _value, 1023 #define __ReadSensorMSCompass(_port, _i2caddr, _value) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, 0x42 \ set __RLSBytesCountVar, 2 \ call __ReadLSBytesVar \ index _value, __RLSReadBufVar, 1 \ index __RLSBytesCountVar, __RLSReadBufVar, NA \ mul _value, _value, 256 \ add _value, _value, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, 0x42 \ set __RLSBytesCount##_port, 2 \ call __ReadLSBytes##_port \ index _value, __RLSReadBuf##_port, 1 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, NA \ mul _value, _value, 256 \ add _value, _value, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __ReadSensorMSRTClock(_port, _sec, _min, _hrs, _dow, _date, _month, _year, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, 0xD0, 0x00 \ set __RLSBytesCountVar, 8 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _sec, __RLSReadBufVar, NA \ index _min, __RLSReadBufVar, 1 \ index _hrs, __RLSReadBufVar, 2 \ index _dow, __RLSReadBufVar, 3 \ index _date, __RLSReadBufVar, 4 \ index _month, __RLSReadBufVar, 5 \ index _year, __RLSReadBufVar, 6 \ bcd2dec(_sec, _sec) \ bcd2dec(_min, _min) \ bcd2dec(_hrs, _hrs) \ bcd2dec(_dow, _dow) \ bcd2dec(_date, _date) \ bcd2dec(_month, _month) \ bcd2dec(_year, _year) \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, 0xD0, 0x00 \ set __RLSBytesCount##_port, 8 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _sec, __RLSReadBuf##_port, NA \ index _min, __RLSReadBuf##_port, 1 \ index _hrs, __RLSReadBuf##_port, 2 \ index _dow, __RLSReadBuf##_port, 3 \ index _date, __RLSReadBuf##_port, 4 \ index _month, __RLSReadBuf##_port, 5 \ index _year, __RLSReadBuf##_port, 6 \ bcd2dec(_sec, _sec) \ bcd2dec(_min, _min) \ bcd2dec(_hrs, _hrs) \ bcd2dec(_dow, _dow) \ bcd2dec(_date, _date) \ bcd2dec(_month, _month) \ bcd2dec(_year, _year) \ release __RLSBmutex##_port \ compend #define __ReadSensorMSTilt(_port, _i2caddr, _x, _y, _z, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, 0x42 \ set __RLSBytesCountVar, 3 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _x, __RLSReadBufVar, NA \ index _y, __RLSReadBufVar, 1 \ index _z, __RLSReadBufVar, 2 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, 0x42 \ set __RLSBytesCount##_port, 3 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _x, __RLSReadBuf##_port, NA \ index _y, __RLSReadBuf##_port, 1 \ index _z, __RLSReadBuf##_port, 2 \ release __RLSBmutex##_port \ compend #define __ReadSensorMSAccel(_port, _i2caddr, _x, _y, _z, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, 0x45 \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _x, __RLSReadBufVar, NA \ index __RLSBytesCountVar, __RLSReadBufVar, 1 \ mul __RLSBytesCountVar, __RLSBytesCountVar, 256 \ add _x, _x, __RLSBytesCountVar \ index _y, __RLSReadBufVar, 2 \ index __RLSBytesCountVar, __RLSReadBufVar, 3 \ mul __RLSBytesCountVar, __RLSBytesCountVar, 256 \ add _y, _y, __RLSBytesCountVar \ index _z, __RLSReadBufVar, 4 \ index __RLSBytesCountVar, __RLSReadBufVar, 5 \ mul __RLSBytesCountVar, __RLSBytesCountVar, 256 \ add _z, _z, __RLSBytesCountVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, 0x45 \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _x, __RLSReadBuf##_port, NA \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 1 \ mul __RLSBytesCount##_port, __RLSBytesCount##_port, 256 \ add _x, _x, __RLSBytesCount##_port \ index _y, __RLSReadBuf##_port, 2 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 3 \ mul __RLSBytesCount##_port, __RLSBytesCount##_port, 256 \ add _y, _y, __RLSBytesCount##_port \ index _z, __RLSReadBuf##_port, 4 \ index __RLSBytesCount##_port, __RLSReadBuf##_port, 5 \ mul __RLSBytesCount##_port, __RLSBytesCount##_port, 256 \ add _z, _z, __RLSBytesCount##_port \ release __RLSBmutex##_port \ compend #define __PFMateSend(_port, _i2caddr, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, PFMATE_REG_CHANNEL, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ arrbuild __RLSReadBufVar, _i2caddr, PFMATE_REG_CMD, PFMATE_CMD_GO \ set __RLSBytesCountVar, 0 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, PFMATE_REG_CHANNEL, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, PFMATE_REG_CMD, PFMATE_CMD_GO \ set __RLSBytesCount##_port, 0 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ release __RLSBmutex##_port \ compend #define __PFMateSendRaw(_port, _i2caddr, _channel, _b1, _b2, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, PFMATE_REG_CHANNEL, _channel, 0x00, _b1, _b2 \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ arrbuild __RLSReadBufVar, _i2caddr, PFMATE_REG_CMD, PFMATE_CMD_RAW \ set __RLSBytesCountVar, 0 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, PFMATE_REG_CHANNEL, _channel, 0x00, _b1, _b2 \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, PFMATE_REG_CMD, PFMATE_CMD_RAW \ set __RLSBytesCount##_port, 0 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ release __RLSBmutex##_port \ compend dseg segment __RLSBbufRFIDInit byte[] 0x04, 0x32 __RLSBbufRFIDData byte[] 0x04, 0x42 __RFIDCount byte __RFIDCont_Port byte __RFIDCont_Result byte __RFIDCont_Output byte[] __RFIDmutex mutex dseg ends #define __RFIDInit(_port, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ mov __RLSReadBufVar, __RLSBbufRFIDInit \ set __RLSBytesCountVar, 0 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ mov __RLSReadBuf##_port, __RLSBbufRFIDInit \ set __RLSBytesCount##_port, 0 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ release __RLSBmutex##_port \ compend #define __RFIDMode(_port, _mode, _result) __I2CSendCmd(_port, 0x04, _mode, _result) #define __RFIDStatus(_port, _result) __MSReadValue(_port, 0x04, 0x32, 1, _result, __RDSD_LSStatus) #define __RFIDRead(_port, _output, _result) \ set __RFIDCount, 5 \ __ReadI2CBytes(_port, __RLSBbufRFIDData, __RFIDCount, _output, _result) #define __RFIDStop(_port, _result) \ __RFIDInit(_port, _result) \ wait 10 \ __RFIDMode(_port, RFID_MODE_STOP, _result) #define __RFIDReadSingle(_port, _output, _result) \ __RFIDInit(_port, _result) \ wait 15 \ __RFIDMode(_port, RFID_MODE_SINGLE, _result) \ wait 250 \ __RFIDRead(_port, _output, _result) #define __RFIDReadContinuous(_port, _output, _result) \ acquire __RFIDmutex \ mov __RFIDCont_Port, _port \ call __RFIDReadContinuousSub \ mov _output, __RFIDCont_Output \ mov _result, __RFIDCont_Result \ release __RFIDmutex #define __NXTServoInit(_port, _i2caddr, _servo, _result) \ __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_INIT, _result) \ __I2CSendCmd(_port, _i2caddr, _servo+1, _result) #define __NXTServoGotoMacroAddress(_port, _i2caddr, _macro, _result) \ __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_GOTO, _result) \ __I2CSendCmd(_port, _i2caddr, _macro, _result) #define __NXTServoEditMacro(_port, _i2caddr, _result) \ __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_EDIT1, _result) \ __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_EDIT2, _result) #define __NXTHIDLoadCharacter(_port, _i2caddr, _modifier, _character, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, _modifier, _character \ set __RLSBytesCountVar, 0 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, _modifier, _character \ set __RLSBytesCount##_port, 0 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ release __RLSBmutex##_port \ compend dseg segment __WDSC_LSB byte __WDSC_MSB byte __WDSC_Port byte __WDSC_WriteBytes byte[] __WDSC_SensorAddress byte __WDSC_SensorRegister byte __WDSC_ByteCount byte __WDSC_lswArgs TCommLSWrite __WDSC_LSStatus sbyte __WDSC_Result sbyte __WDSCmutex mutex __DNRVmutex mutex __RDSD_Port byte __RDSD_SensorAddress byte __RDSD_SensorRegister byte __RDSD_NumBytesToRead byte __RDSD_Value sdword __RDSD_lswArgs TCommLSWrite __RDSD_lsrArgs TCommLSRead __RDSD_LSStatus sbyte __RDSD_bytesRead sdword __RDSD_PreviousValue sdword __RDSD_Byte byte dseg ends #define __MSWriteToRegister(_port, _i2caddr, _reg, _bytes, _result) \ acquire __WDSCmutex \ mov __WDSC_Port, _port \ mov __WDSC_SensorAddress, _i2caddr \ set __WDSC_SensorRegister, _reg \ arrbuild __WDSC_WriteBytes, _bytes \ call __MSWriteBytesSub \ mov _result, __WDSC_LSStatus \ release __WDSCmutex #define __MSWriteLEIntToRegister(_port, _i2caddr, _reg, _ival, _result) \ acquire __WDSCmutex \ mov __WDSC_Port, _port \ mov __WDSC_SensorAddress, _i2caddr \ set __WDSC_SensorRegister, _reg \ and __WDSC_LSB, _ival, 0xFF \ div __WDSC_MSB, _ival, 0xFF \ arrbuild __WDSC_WriteBytes, __WDSC_LSB, __WDSC_MSB \ call __MSWriteBytesSub \ mov _result, __WDSC_LSStatus \ release __WDSCmutex #define __I2CSendCmd(_port, _i2caddr, _cmd, _result) \ __MSWriteToRegister(_port, _i2caddr, I2C_REG_CMD, _cmd, _result) #define __TempSendCmd(_port, _cmd, _result) \ __MSWriteToRegister(_port, LEGO_ADDR_TEMP, TEMP_REG_CONFIG, _cmd, _result) #define __MSReadValue(_port, _i2caddr, _reg, _bytes, _out, _result) \ acquire __DNRVmutex \ mov __RDSD_Port, _port \ mov __RDSD_SensorAddress, _i2caddr \ mov __RDSD_SensorRegister, _reg \ set __RDSD_NumBytesToRead, _bytes \ call __MSReadLEValueSub \ mov _out, __RDSD_Value \ mov _result, __RDSD_LSStatus \ release __DNRVmutex subroutine __RFIDReadContinuousSub __RFIDInit(__RFIDCont_Port, __RFIDCont_Result) wait 15 __RFIDStatus(__RFIDCont_Port, __RFIDCont_Result) brtst GT, __RFIDCont_Endif, __RFIDCont_Result __RFIDMode(__RFIDCont_Port, RFID_MODE_CONTINUOUS, __RFIDCont_Result) wait 250 __RFIDCont_Endif: __RFIDRead(__RFIDCont_Port, __RFIDCont_Output, __RFIDCont_Result) return ends subroutine __MSWriteBytesSub mov __WDSC_lswArgs.Port, __WDSC_Port arrbuild __WDSC_lswArgs.Buffer, __WDSC_SensorAddress, __WDSC_SensorRegister, __WDSC_WriteBytes set __WDSC_lswArgs.ReturnLen, 0 syscall CommLSWrite, __WDSC_lswArgs __WDSC_StatusLoop: __lowspeedCheckStatus(__WDSC_Port, __WDSC_LSStatus) brtst GT, __WDSC_StatusLoop, __WDSC_LSStatus return ends subroutine __MSReadLEValueSub mov __RDSD_lswArgs.Port, __RDSD_Port arrbuild __RDSD_lswArgs.Buffer, __RDSD_SensorAddress, __RDSD_SensorRegister mov __RDSD_lswArgs.ReturnLen, __RDSD_NumBytesToRead syscall CommLSWrite, __RDSD_lswArgs __RDSD_CheckStatusAfterWriteLoop: __lowspeedCheckStatus(__RDSD_Port, __RDSD_LSStatus) brtst GT, __RDSD_CheckStatusAfterWriteLoop, __RDSD_LSStatus brtst EQ, __RDSD_GoAheadWithRead, __RDSD_LSStatus jmp __RDSD_ReadError __RDSD_GoAheadWithRead: mov __RDSD_lsrArgs.Port, __RDSD_Port mov __RDSD_lsrArgs.BufferLen, __RDSD_NumBytesToRead syscall CommLSRead, __RDSD_lsrArgs __RDSD_CheckStatusAfterReadLoop: __lowspeedCheckStatus(__RDSD_Port, __RDSD_LSStatus) brtst GT, __RDSD_CheckStatusAfterReadLoop, __RDSD_LSStatus arrsize __RDSD_bytesRead, __RDSD_lsrArgs.Buffer brcmp NEQ, __RDSD_ReadError, __RDSD_bytesRead, __RDSD_NumBytesToRead brtst EQ, __RDSD_GoAheadAndCalculateValue, __RDSD_LSStatus __RDSD_ReadError: mov __RDSD_Value, __RDSD_PreviousValue jmp __RDSD_ReturnResults __RDSD_GoAheadAndCalculateValue: set __RDSD_Value, 0 brcmp EQ, __RDSD_OneByte, __RDSD_NumBytesToRead, 1 brcmp EQ, __RDSD_TwoBytes, __RDSD_NumBytesToRead, 2 brcmp NEQ, __RDSD_ReadError, __RDSD_NumBytesToRead, 4 index __RDSD_Byte, __RDSD_lsrArgs.Buffer, 3 mul __RDSD_Value, __RDSD_Byte, 256 index __RDSD_Byte, __RDSD_lsrArgs.Buffer, 2 add __RDSD_Value, __RDSD_Value, __RDSD_Byte mul __RDSD_Value, __RDSD_Value, 256 __RDSD_TwoBytes: index __RDSD_Byte, __RDSD_lsrArgs.Buffer, 1 add __RDSD_Value, __RDSD_Value, __RDSD_Byte mul __RDSD_Value, __RDSD_Value, 256 __RDSD_OneByte: index __RDSD_Byte, __RDSD_lsrArgs.Buffer, NA add __RDSD_Value, __RDSD_Value, __RDSD_Byte mov __RDSD_PreviousValue, __RDSD_Value __RDSD_ReturnResults: return ends #define __ReadSensorMSPlayStation(_port, _i2caddr, _b1, _b2, _xleft, _yleft, _xright, _yright, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, PSP_REG_BTNSET1 \ set __RLSBytesCountVar, 6 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _b1, __RLSReadBufVar, NA \ index _b2, __RLSReadBufVar, 1 \ index _xleft, __RLSReadBufVar, 2 \ index _yleft, __RLSReadBufVar, 3 \ index _xright, __RLSReadBufVar, 4 \ index _yright, __RLSReadBufVar, 5 \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, PSP_REG_BTNSET1 \ set __RLSBytesCount##_port, 6 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _b1, __RLSReadBuf##_port, NA \ index _b2, __RLSReadBuf##_port, 1 \ index _xleft, __RLSReadBuf##_port, 2 \ index _yleft, __RLSReadBuf##_port, 3 \ index _xright, __RLSReadBuf##_port, 4 \ index _yright, __RLSReadBuf##_port, 5 \ release __RLSBmutex##_port \ compend #define __RunNRLinkMacro(_port, _i2caddr, _macro, _result) \ acquire __WDSCmutex \ mov __WDSC_Port, _port \ mov __WDSC_SensorAddress, _i2caddr \ arrbuild __WDSC_WriteBytes, NRLINK_CMD_RUN_MACRO, _macro \ call __MSWriteBytesSub \ mov _result, __WDSC_LSStatus \ release __WDSCmutex #define __ReadNRLinkStatus(_port, _i2caddr, _value, _result) \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, I2C_REG_CMD \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ index _value, __RLSReadBufVar, NA \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, I2C_REG_CMD \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ index _value, __RLSReadBuf##_port, NA \ release __RLSBmutex##_port \ compend #define __WriteNRLinkBytes(_port, _i2caddr, _bytes, _result) \ __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_FLUSH, _result) \ __MSWriteToRegister(_port, _i2caddr, NRLINK_REG_DATA, _bytes, _result) \ arrsize __WDSC_ByteCount, _bytes \ __MSWriteToRegister(_port, _i2caddr, NRLINK_REG_BYTES, __WDSC_ByteCount, _result) #define __ReadNRLinkBytes(_port, _i2caddr, _bytes, _result) \ acquire __DNRVmutex \ compif EQ, isconst(_port), FALSE \ acquire __RLSBmutex0 \ acquire __RLSBmutex1 \ acquire __RLSBmutex2 \ acquire __RLSBmutex3 \ mov __RLSReadPort, _port \ arrbuild __RLSReadBufVar, _i2caddr, NRLINK_REG_BYTES \ set __RLSBytesCountVar, 1 \ call __ReadLSBytesVar \ index __RLSBytesCountVar, __RLSReadBufVar, NA \ arrbuild __RLSReadBufVar, _i2caddr, NRLINK_REG_DATA \ call __ReadLSBytesVar \ tst EQ, _result, __RLSBResultVar \ mov _bytes, __RLSReadBufVar \ release __RLSBmutex0 \ release __RLSBmutex1 \ release __RLSBmutex2 \ release __RLSBmutex3 \ compelse \ compchk LT, _port, 0x04 \ compchk GTEQ, _port, 0x00 \ acquire __RLSBmutex##_port \ arrbuild __RLSReadBuf##_port, _i2caddr, NRLINK_REG_BYTES \ set __RLSBytesCount##_port, 1 \ call __ReadLSBytes##_port \ index __RLSBytesCount##_port, __RLSReadBuf##_port, NA \ arrbuild __RLSReadBuf##_port, _i2caddr, NRLINK_REG_DATA \ call __ReadLSBytes##_port \ tst EQ, _result, __RLSBResult##_port \ mov _bytes, __RLSReadBuf##_port \ release __RLSBmutex##_port \ compend \ __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_FLUSH, _result) \ release __DNRVmutex dseg segment __MSPFByte1 byte __MSPFByte2 byte dseg ends subroutine __MSPowerFunctionCalcBytes call __PFCalcChecksum // build __PFBytes using two values calculated from the __PFNibbles index __MSPFByte1, __PFNibbles, NA index __PFTmp, __PFNibbles, 1 mul __MSPFByte1, __MSPFByte1, 16 add __MSPFByte1, __MSPFByte1, __PFTmp index __MSPFByte2, __PFNibbles, 2 index __PFTmp, __PFNibbles, 3 mul __MSPFByte2, __MSPFByte2, 16 add __MSPFByte2, __MSPFByte2, __PFTmp arrbuild __PFBytes, __MSPFByte1, __MSPFByte2 return ends #define __MSPFComboDirect(_port, _i2caddr, _channel, _outa, _outb, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _outa, 4 \ mod __PF_p3, _outb, 4 \ call __PFComboDirectSub \ set __PFPowerFuncMode, TRUE \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSPFSinglePin(_port, _i2caddr, _channel, _out, _pin, _func, _cont, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _out, 2 \ mod __PF_p3, _pin, 2 \ mod __PF_p4, _func, 4 \ set __PF_p5, _cont \ call __PFSinglePinSub \ set __PFPowerFuncMode, TRUE \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSPFSingleOutput(_port, _i2caddr, _channel, _out, _func, _cst, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _out, 2 \ mod __PF_p3, _func, 16 \ set __PF_p4, _cst \ call __PFSingleOutputSub \ set __PFPowerFuncMode, TRUE \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSPFComboPWM(_port, _i2caddr, _channel, _outa, _outb, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _outa, 16 \ mod __PF_p3, _outb, 16 \ call __PFComboPWMSub \ set __PFPowerFuncMode, TRUE \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSIRTrain(_port, _i2caddr, _channel, _func, _PFMode, _result) \ acquire __PFMutex \ mod __PF_p1, _channel, 4 \ mod __PF_p2, _func, 5 \ compif EQ, _PFMode, TRUE \ call __PFTrainSub \ compelse \ call __RCTrainSub \ compend \ set __PFPowerFuncMode, _PFMode \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSPFRawOutput(_port, _i2caddr, _nibble0, _nibble1, _nibble2, _result) \ acquire __PFMutex \ mod __PF_p1, _nibble0, 7 \ mod __PF_p2, _nibble1, 16 \ mod __PF_p3, _nibble2, 16 \ call __PFRawOutputSub \ set __PFPowerFuncMode, TRUE \ call __MSPowerFunctionCalcBytes \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ release __PFMutex #define __MSPFRepeatLastCommand(_port, _i2caddr, _count, _delay, _result) \ acquire __PFMutex \ mov __PF_p1, _count \ __MSPFRepeatLoop##__I__: \ __WriteNRLinkBytes(_port, _i2caddr, __PFBytes, _result) \ waitv _delay \ sub __PF_p1, __PF_p1, 1 \ brtst GT, __MSPFRepeatLoop##__I__, __PF_p1 \ release __PFMutex \ __IncI__ subroutine __MSRCXCommandSub dseg segment __MSRCSToggle byte __MSRCSI byte __MSRCSInCmd byte[] __MSRCSTmpBuf byte[] __MSRCSCmdBytes sbyte __MSRCSCmd byte __MSRCSCSum byte __MSRCSMsgBufSize byte __MSRCSTmpByte byte __MSRCSTmpSByte sbyte __MSRCSTmpWord word __MSRCSTmpByte2 byte __MSRCSResult byte dseg ends arrsize __MSRCSCmdBytes, __gRCXCmd.Command index __MSRCSCmd, __gRCXCmd.Command, NA set __MSRCSCSum, 0 // build the message set __MSRCSMsgBufSize, 2 mul __MSRCSMsgBufSize, __MSRCSMsgBufSize, __MSRCSCmdBytes add __MSRCSMsgBufSize, __MSRCSMsgBufSize, 5 arrinit __MSRCSInCmd, 0, __MSRCSMsgBufSize replace __MSRCSInCmd, __MSRCSInCmd, NA, 0x55 replace __MSRCSInCmd, __MSRCSInCmd, 1, 0xFF replace __MSRCSInCmd, __MSRCSInCmd, 2, 0x00 // add cmd and ~cmd bytes or __MSRCSTmpByte, __MSRCSCmd, __MSRCSToggle replace __MSRCSInCmd, __MSRCSInCmd, 3, __MSRCSTmpByte mov __MSRCSCSum, __MSRCSTmpByte sub __MSRCSTmpByte, 0xFF, __MSRCSCSum replace __MSRCSInCmd, __MSRCSInCmd, 4, __MSRCSTmpByte set __MSRCSI, 0 xor __MSRCSToggle, __MSRCSToggle, 8 brcmp LTEQ, __MSRCSEndWhileILTCmdBytes, __MSRCSCmdBytes, 1 __MSRCSWhileILTCmdBytes: sub __MSRCSTmpByte, __MSRCSCmdBytes, 1 brcmp GTEQ, __MSRCSEndWhileILTCmdBytes, __MSRCSI, __MSRCSTmpByte add __MSRCSTmpByte, __MSRCSI, 1 index __MSRCSTmpByte2, __gRCXCmd.Command, __MSRCSTmpByte mul __MSRCSTmpByte, __MSRCSI, 2 add __MSRCSTmpByte, __MSRCSTmpByte, 5 replace __MSRCSInCmd, __MSRCSInCmd, __MSRCSTmpByte, __MSRCSTmpByte2 // calculate checksum add __MSRCSCSum, __MSRCSCSum, __MSRCSTmpByte2 add __MSRCSTmpByte, __MSRCSTmpByte, 1 sub __MSRCSTmpByte2, 255, __MSRCSTmpByte2 replace __MSRCSInCmd, __MSRCSInCmd, __MSRCSTmpByte, __MSRCSTmpByte2 add __MSRCSI, __MSRCSI, 1 jmp __MSRCSWhileILTCmdBytes __MSRCSEndWhileILTCmdBytes: // add the two checksum bytes mul __MSRCSTmpByte, __MSRCSI, 2 add __MSRCSTmpByte, __MSRCSTmpByte, 5 replace __MSRCSInCmd, __MSRCSInCmd, __MSRCSTmpByte, __MSRCSCSum sub __MSRCSTmpByte2, 255, __MSRCSCSum add __MSRCSTmpByte, __MSRCSTmpByte, 1 replace __MSRCSInCmd, __MSRCSInCmd, __MSRCSTmpByte, __MSRCSTmpByte2 // if the size of __MSRCSInCmd > 14 then we need to chunk up the transmission mov __MSRCSTmpSByte, __MSRCSMsgBufSize __MSRCSWhileMsgBufSizeGTZero: arrsubset __gRCXCmd.Command, __MSRCSInCmd, NA, 14 arrbuild __MSRCSTmpBuf, __gRCXCmd.Address, 0x42, __gRCXCmd.Command // write message bytes to the NRLink device __WriteNRLinkBytes(__gRCXCmd.Port, __gRCXCmd.Address, __MSRCSTmpBuf, __MSRCSResult) sub __MSRCSTmpSByte, __MSRCSTmpSByte, 14 brtst LTEQ, __MSRCSEndWhileMsgBufSizeGTZero, __MSRCSTmpSByte arrsubset __MSRCSTmpBuf, __MSRCSInCmd, 14, NA mov __MSRCSInCmd, __MSRCSTmpBuf jmp __MSRCSWhileMsgBufSizeGTZero __MSRCSEndWhileMsgBufSizeGTZero: // Now send the IR message arrbuild __MSRCSTmpBuf, __gRCXCmd.Address, 0x40, __MSRCSMsgBufSize __WriteNRLinkBytes(__gRCXCmd.Port, __gRCXCmd.Address, __MSRCSTmpBuf, __MSRCSResult) // give the message time to be transferred mul __MSRCSTmpWord, __MSRCSMsgBufSize, 5 waitv __MSRCSTmpWord // do we need to read a response? brtst EQ, __MSRCSNoResponse, __gRCXCmd.ResponseBytes // give the message time to be transferred add __MSRCSTmpWord, __MSRCSMsgBufSize, __gRCXCmd.ResponseBytes mul __MSRCSTmpWord, __MSRCSTmpWord, 5 waitv __MSRCSTmpWord // read the response __ReadNRLinkBytes(__gRCXCmd.Port, __gRCXCmd.Address, __gRCXCmd.Response, __MSRCSResult) __MSRCSNoResponse: return ends #define __MSRCXSetNRLink(_port, _i2caddr) \ set __gRCXCmd.Port, _port \ set __gRCXCmd.Address, _i2caddr #define __MSRCXPoll(_src, _value, _result) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PollOp, _src, _value \ set __gRCXCmd.ResponseBytes, 12 \ call __MSRCXCommandSub \ index _result, __gRCXCmd.Response, 4 \ index __MSRCSTmpByte, __gRCXCmd.Response, 2 \ mul _result, _result, 256 \ add _result, _result, __MSRCSTmpByte \ release __RCXCmdMutex #define __MSRCXBatteryLevel(_result) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_BatteryLevelOp \ set __gRCXCmd.ResponseBytes, 12 \ call __MSRCXCommandSub \ index _result, __gRCXCmd.Response, 4 \ index __MSRCSTmpByte, __gRCXCmd.Response, 2 \ mul _result, _result, 256 \ add _result, _result, __MSRCSTmpByte \ release __RCXCmdMutex #define __MSRCXOpNoArgs(_op) \ acquire __RCXCmdMutex \ arrinit __gRCXCmd.Command, _op, 1 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetOutput(_outputs, _mode) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _mode \ arrbuild __gRCXCmd.Command, RCX_OnOffFloatOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetDirection(_outputs, _dir) \ acquire __RCXCmdMutex \ add __RCSTmpByte, _outputs, _dir \ arrbuild __gRCXCmd.Command, RCX_OutputDirOp, __RCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetPower(_outputs, _pwrsrc, _pwrval) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_OutputPowerOp, _outputs, _pwrsrc, _pwrval \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXOnFwd(_outputs) \ __MSRCXSetDirection(_outputs, RCX_OUT_FWD) \ __MSRCXSetOutput(_outputs, RCX_OUT_ON) #define __MSRCXOnRev(_outputs) \ __MSRCXSetDirection(_outputs, RCX_OUT_REV) \ __MSRCXSetOutput(_outputs, RCX_OUT_ON) #define __MSRCXOnFor(_outputs, _ms) \ __MSRCXSetOutput(_outputs, RCX_OUT_ON) \ waitv _ms \ __MSRCXSetOutput(_outputs, RCX_OUT_OFF) #define __MSRCXSetTxPower(_pwr) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_IRModeOp, _pwr \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXPlaySound(_snd) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PlaySoundOp, _snd \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXDeleteTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DeleteTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXStartTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_StartTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXStopTask(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_StopTaskOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSelectProgram(_prog) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SelectProgramOp, _prog \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXClearTimer(_timer) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearTimerOp, _timer \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetSleepTime(_t) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_AutoOffOp, _t \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXDeleteSub(_s) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DeleteSubOp, _s \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXClearSensor(_port) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearSensorOp, _port \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXPlayToneVar(_varnum, _duration) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_PlayToneVarOp, _varnum, _duration \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetWatch(_hours, _minutes) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetWatchOp, _hours, _minutes \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetSensorType(_port, _type) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_InputTypeOp, _port, _type \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetSensorMode(_port, _mode) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_InputModeOp, _port, _mode \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXCreateDatalog(_size) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _size, 0xFF \ div __MSRCSTmpByte2, _size, 256 \ arrbuild __gRCXCmd.Command, RCX_SetDatalogOp, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXAddToDatalog(_src, _value) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DatalogOp, _src, _value \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSendSerial(_first, _count) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SendUARTDataOp, _first, _count \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXRemote(_cmd) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _cmd, 0xFF \ div __MSRCSTmpByte2, _cmd, 256 \ arrbuild __gRCXCmd.Command, RCX_RemoteOp, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXEvent(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_DirectEventOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXPlayTone(_freq, _duration) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _freq, 0xFF \ div __MSRCSTmpByte2, _freq, 256 \ arrbuild __gRCXCmd.Command, RCX_PlayToneOp, __MSRCSTmpByte, __MSRCSTmpByte2, _duration \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSelectDisplay(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_DisplayOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXPollMemory(_memaddress, _result) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _memaddress, 0xFF \ div __MSRCSTmpByte2, _memaddress, 256 \ arrbuild __gRCXCmd.Command, RCX_PollMemoryOp, __MSRCSTmpByte, __MSRCSTmpByte2, 1 \ set __gRCXCmd.ResponseBytes, 12 \ call __MSRCXCommandSub \ index _result, __gRCXCmd.Response, 4 \ index __MSRCSTmpByte, __gRCXCmd.Response, 2 \ mul _result, _result, 256 \ add _result, _result, __MSRCSTmpByte \ release __RCXCmdMutex #define __MSRCXSetEvent(_evt, _src, _type) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetEventOp, _evt, _src, _type \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetGlobalOutput(_outputs, _mode) \ acquire __RCXCmdMutex \ add __MSRCSTmpByte, _outputs, _mode \ arrbuild __gRCXCmd.Command, RCX_GOutputModeOp, __MSRCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetGlobalDirection(_outputs, _dir) \ acquire __RCXCmdMutex \ add __MSRCSTmpByte, _outputs, _dir \ arrbuild __gRCXCmd.Command, RCX_GOutputDirOp, __MSRCSTmpByte \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_GOutputPowerOp, _outputs, _pwrsrc, _pwrval \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXCalibrateEvent(_evt, _low, _hi, _hyst) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_CalibrateEventOp, _evt, _low, _hi, _hyst \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __RCXVarOp(_op, _vnum, _src, _val) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _val, 0xFF \ div __MSRCSTmpByte2, _val, 256 \ arrbuild __gRCXCmd.Command, _op, _vnum, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSet(_dstsrc, _dstval, _src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_SetSourceValueOp, _dstsrc, _dstval, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXUnlock() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_UnlockOp, 1, 3, 5, 7, 11 \ set __gRCXCmd.ResponseBytes, 16 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXReset() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_BootModeOp, 1, 3, 5, 7, 11 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXBoot() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_UnlockFirmOp, 0x4c, 0x45, 0x47, 0x4F, 0xAE \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetUserDisplay(_src, _value, _precision) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_ViewSourceValOp, 0, _precision, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXIncCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_IncCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXDecCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_DecCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXClearCounter(_counter) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ClearCounterOp, _counter \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetPriority(_p) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SetPriorityOp, _p \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSRCXSetMessage(_msg) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_MessageOp, _msg \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetScoutMode(_mode) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ScoutOp, _mode \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetScoutRules(_m, _t, _l, _tm, _fx) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_ScoutRulesOp, _m, _t, _l, _tm, _fx \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSendVLL(_src, _value) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_VLLOp, _src, _value \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetSensorClickTime(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSBlinkTimeOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetSensorHysteresis(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSHysteresisOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetSensorLowerLimit(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSLowerThreshOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetSensorUpperLimit(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_LSUpperThreshOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetEventFeedback(_src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_SetFeedbackOp, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetCounterLimit(_ctr, _src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_SetCounterOp, _ctr, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetTimerLimit(_tmr, _src, _value) \ acquire __RCXCmdMutex \ and __MSRCSTmpByte, _value, 0xFF \ div __MSRCSTmpByte2, _value, 256 \ arrbuild __gRCXCmd.Command, RCX_SetTimerLimitOp, _tmr, _src, __MSRCSTmpByte, __MSRCSTmpByte2 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutMuteSound() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, 0x80 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutUnmuteSound() \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, 0xc0 \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSelectSounds(_grp) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_SoundOp, _grp \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __MSScoutSetLight(_x) \ acquire __RCXCmdMutex \ arrbuild __gRCXCmd.Command, RCX_LightOp, _x \ set __gRCXCmd.ResponseBytes, 0 \ call __MSRCXCommandSub \ release __RCXCmdMutex #define __glInit() \ call __GL_glInit #define __glSet(_glType, _glValue) \ mov __GL_glSettingType, _glType \ mov __GL_glSettingValue, _glValue \ call __GL_glSet #define __glBeginObject(_glObjId) \ mov __GL_object.firstVertex, __GL_vertexCount \ mov __GL_object.lastVertex, __GL_vertexCount \ mov __GL_object.firstPolygon, __GL_polygonCount \ mov _glObjId, __GL_objectCount #define __glEndObject() \ call __GL_glEndObject #define __glObjectAction(_glObjectId, _glAction, _glValue) \ mov __GL_objectIndex, _glObjectId \ mov __GL_action, _glAction \ mov __GL_value, _glValue \ call __GL_glObjectAction #define __glAddVertex(_glX, _glY, _glZ) \ mov __GL_vertex0.orig.x, _glX \ mov __GL_vertex0.orig.y, _glY \ mov __GL_vertex0.orig.z, _glZ \ call __GL_glAddVertex #define __glBegin(_glBeginMode) \ mov __GL_polygon.beginMode, _glBeginMode \ mov __GL_polygon.firstVertex, __GL_pvDataCount \ mov __GL_polygon.lastVertex, __GL_pvDataCount #define __glEnd() \ call __GL_glEnd #define __glBeginRender() \ call __GL_glResetObjects #define __glCallObject(_glObjectId) \ mov __GL_objectIndex, _glObjectId \ call __GL_glCallObject #define __glFinishRender() \ call __GL_glRotateVertexList \ set __GL_glDrawPoint.Location.X, 200 \ set __GL_glDrawPoint.Options, DRAW_OPT_CLEAR_WHOLE_SCREEN \ syscall DrawPoint, __GL_glDrawPoint \ call __GL_glRenderObjects #define __glSetAngleX(_glValue) \ add __GL_angleX, _glValue, 3600 \ mod __GL_angleX, __GL_angleX, 360 #define __glAddToAngleX(_glValue) \ add __GL_angleX, __GL_angleX, _glValue \ add __GL_angleX, __GL_angleX, 3600 \ mod __GL_angleX, __GL_angleX, 360 #define __glSetAngleY(_glValue) \ add __GL_angleY, _glValue, 3600 \ mod __GL_angleY, __GL_angleY, 360 #define __glAddToAngleY(_glValue) \ add __GL_angleY, __GL_angleY, _glValue \ add __GL_angleY, __GL_angleY, 3600 \ mod __GL_angleY, __GL_angleY, 360 #define __glSetAngleZ(_glValue) \ add __GL_angleZ, _glValue, 3600 \ mod __GL_angleZ, __GL_angleZ, 360 #define __glAddToAngleZ(_glValue) \ add __GL_angleZ, __GL_angleZ, _glValue \ add __GL_angleZ, __GL_angleZ, 3600 \ mod __GL_angleZ, __GL_angleZ, 360 #define __glSin32768(_glAngle, _glResult) \ mov __GL_angle, _glAngle \ mod __GL_angle, __GL_angle, 360 \ index _glResult, __GL_SIN_TABLE, __GL_angle #define __glCos32768(_glAngle, _glResult) \ mov __GL_angle, _glAngle \ add __GL_angle, __GL_angle, 90 \ mod __GL_angle, __GL_angle, 360 \ index _glResult, __GL_SIN_TABLE, __GL_angle #define __glBox(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glObjId) \ mov __GL_mode _glMode \ mov __GL_sizeX _glSizeX \ mov __GL_sizeY _glSizeY \ mov __GL_sizeZ _glSizeZ \ call __GL_glBox \ mov _glObjId, __GL_tmpId #define __glPyramid(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glOjbId) \ mov __GL_mode _glMode \ mov __GL_sizeX _glSizeX \ mov __GL_sizeY _glSizeY \ mov __GL_sizeZ _glSizeZ \ call __GL_glPyramid \ mov _glObjId, __GL_tmpId //----------------------------------------------------------------------------------------- // // Private definitions... // //----------------------------------------------------------------------------------------- #define __glRangeCheck(_glValue, _glMaxValue, _glErrorMsg) \ mov __GL_glRangeValue, _glValue \ mov __GL_glRangeMaxValue, _glMaxValue \ mov __GL_glRangeErrorMsg, _glErrorMsg \ call __GL_glRangeCheck // Data sizes... #define __GL_MAX_VERTICES 256 #define __GL_MAX_LINES 256 #define __GL_MAX_POLYGONS 128 #define __GL_MAX_OBJECT_ACTIONS 32 #define __GL_MAX_OBJECTS 16 #define __GL_MAX_PV_DATA 256 #define __GL_MAX_PL_DATA 256 dseg segment // Sine table constants... __GL_SIN_TABLE sword[] 0,572,1144,1715,2286,2856,3425,3993,4560,5126,5690,6252,6813,7371,7927, \ 8481,9032,9580,10126,10668,11207,11743,12275,12803,13328,13848,14365,14876,15384,15886,16384, \ 16877,17364,17847,18324,18795,19261,19720,20174,20622,21063,21498,21926,22348,22763,23170,23571, \ 23965,24351,24730,25102,25466,25822,26170,26510,26842,27166,27482,27789,28088,28378,28660,28932, \ 29197,29452,29698,29935,30163,30382,30592,30792,30983,31164,31336,31499,31651,31795,31928,32052, \ 32166,32270,32365,32449,32524,32588,32643,32688,32723,32748,32763,32767,32763,32748,32723,32688, \ 32643,32588,32524,32449,32365,32270,32166,32052,31928,31795,31651,31499,31336,31164,30983,30792, \ 30592,30382,30163,29935,29698,29452,29197,28932,28660,28378,28088,27789,27482,27166,26842,26510, \ 26170,25822,25466,25102,24730,24351,23965,23571,23170,22763,22348,21926,21498,21063,20622,20174, \ 19720,19261,18795,18324,17847,17364,16877,16384,15886,15384,14876,14365,13848,13328,12803,12275, \ 11743,11207,10668,10126,9580,9032,8481,7927,7371,6813,6252,5690,5126,4560,3993,3425,2856,2286, \ 1715,1144,572,0,-572,-1144,-1715,-2286,-2856,-3425,-3993,-4560,-5126,-5690,-6252,-6813,-7371, \ -7927,-8481,-9032,-9580,-10126,-10668,-11207,-11743,-12275,-12803,-13328,-13848,-14365,-14876, \ -15384,-15886,-16384,-16877,-17364,-17847,-18324,-18795,-19261,-19720,-20174,-20622,-21063,-21498,\ -21926,-22348,-22763,-23170,-23571,-23965,-24351,-24730,-25102,-25466,-25822,-26170,-26510,-26842,\ -27166,-27482,-27789,-28088,-28378,-28660,-28932,-29197,-29452,-29698,-29935,-30163,-30382,-30592,\ -30792,-30983,-31164,-31336,-31499,-31651,-31795,-31928,-32052,-32166,-32270,-32365,-32449,-32524,\ -32588,-32643,-32688,-32723,-32748,-32763,-32767,-32763,-32748,-32723,-32688,-32643,-32588,-32524,\ -32449,-32365,-32270,-32166,-32052,-31928,-31795,-31651,-31499,-31336,-31164,-30983,-30792,-30592,\ -30382,-30163,-29935,-29698,-29452,-29197,-28932,-28660,-28378,-28088,-27789,-27482,-27166,-26842,\ -26510,-26170,-25822,-25466,-25102,-24730,-24351,-23965,-23571,-23170,-22763,-22348,-21926,-21498,\ -21063,-20622,-20174,-19720,-19261,-18795,-18324,-17847,-17364,-16877,-16384,-15886,-15384,-14876,\ -14365,-13848,-13328,-12803,-12275,-11743,-11207,-10668,-10126,-9580,-9032,-8481,-7927,-7371, \ -6813,-6252,-5690,-5126,-4560,-3993,-3425,-2856,-2286,-1715,-1144,-572,0 // General stuff, copied from NXTDefs.h... __GL_glDrawLine TDrawLine __GL_glDrawPoint TDrawPoint __GL_glDrawCircle TDrawCircle __GL_glDrawData TDrawText // settings... TGLSettings struct cullMode byte circleSize byte camDepth byte zoom byte TGLSettings ends __GL_glSettings TGLSettings __GL_glSettingType byte __GL_glSettingValue byte // Vertex data... TGLVertex struct x sword //sdword y sword //sdword z sword //sdword TGLVertex ends TGLScreenVertex struct x sword //sdword y sword //sdword TGLScreenVertex ends TGLRotVertex struct orig TGLVertex rot TGLVertex screen TGLScreenVertex TGLRotVertex ends __GL_vertexData TGLRotVertex[] __GL_vertex0 TGLRotVertex __GL_vertex1 TGLRotVertex __GL_vertex2 TGLRotVertex __GL_vertexCount byte __GL_vertexIndex byte __GL_vertexOffset byte // Line data... TGLLine struct firstVertex byte lastVertex byte TGLLine ends __GL_lineData TGLLine[] __GL_line TGLLine __GL_lineCount byte __GL_lineIndex byte __GL_lineDone byte[] // Polygon data... TGLPolygon struct beginMode byte firstVertex byte lastVertex byte firstLine byte lastLine byte TGLPolygon ends __GL_polygonData TGLPolygon[] __GL_polygon TGLPolygon __GL_polygonCount byte __GL_polygonIndex byte // Polygon/vertex link... __GL_pvData byte[] __GL_pvDataCount byte // Polygon/line link... __GL_plData byte[] __GL_plDataCount byte // Object action... TGLObjectAction struct type byte value sword //sdword // fsin float // fcos float lsin sword //sdword lcos sword //sdword TGLObjectAction ends __GL_objectAction TGLObjectAction __GL_objectActionData TGLObjectAction[] __GL_objectActionCount byte // Object data... TObject struct firstVertex byte lastVertex byte firstPolygon byte lastPolygon byte firstLine byte lastLine byte render byte // settings... circleSize byte cullMode byte actionCount byte actionList byte[] TObject ends __GL_objectData TObject[] __GL_object TObject __GL_objectCount byte __GL_objectIndex byte // Temp offset... __GL_offset word // Counters... __GL_i word __GL_j word __GL_k word __GL_l word // Angles... __GL_angleX sword //sdword __GL_angleY sword //sdword __GL_angleZ sword //sdword // Save angles... __GL_saveAngleX sword //sdword __GL_saveAngleY sword //sdword __GL_saveAngleZ sword //sdword __GL_sinX sword //sdword __GL_cosX sword //sdword __GL_sinY sword //sdword __GL_cosY sword //sdword __GL_sinZ sword //sdword __GL_cosZ sword //sdword // __GL_sinX float // __GL_cosX float // __GL_sinY float // __GL_cosY float // __GL_sinZ float // __GL_cosZ float // Temp vars for calculations... __GL_a sdword __GL_b sdword __GL_c sdword __GL_d sdword __GL_e sdword __GL_f sdword // Rotated x, y, z coords... __GL_xx sdword __GL_yy sdword __GL_zz sdword __GL_camDepth sdword __GL_zoom sdword __GL_x0 sdword __GL_y0 sdword __GL_z0 sdword __GL_x1 sdword __GL_y1 sdword __GL_z1 sdword __GL_x2 sdword __GL_y2 sdword __GL_z2 sdword // data for filling polygons... __GL_buffer byte[] __GL_minX sword __GL_maxX sword __GL_startY sword __GL_startX sword __GL_endY sword __GL_endX sword __GL_deltaY sword __GL_deltaX sword __GL_action byte __GL_index word __GL_value sword //sdword __GL_type sword //sdword // rangecheck data... __GL_glRangeValue word __GL_glRangeMaxValue word __GL_glRangeErrorMsg byte[] __GL_glErrorState byte FALSE __GL_glErrorMsg byte[] __GL_glLinesClipped byte dseg ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glRangeCheck // Description : Check array sizes. //----------------------------------------------------------------------------------------- subroutine __GL_glRangeCheck // check if there's an already error... brcmp EQ, __GL_nbc_gl_range_ok, __GL_glErrorState, TRUE // check the range... brcmp LT, __GL_nbc_gl_range_ok, __GL_glRangeValue, __GL_glRangeMaxValue set __GL_glErrorState, TRUE mov __GL_glErrorMsg, __GL_glRangeErrorMsg __GL_nbc_gl_range_ok: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glInit // Description : Initialize vars. //----------------------------------------------------------------------------------------- subroutine __GL_glInit set __GL_glSettings.cullMode, GL_CULL_BACK set __GL_glSettings.circleSize, 4 set __GL_glSettings.camDepth, 100 set __GL_glSettings.zoom, 0 arrinit __GL_vertexData, __GL_vertex0, __GL_MAX_VERTICES set __GL_vertexCount, 0 arrinit __GL_lineData, __GL_line, __GL_MAX_LINES set __GL_lineCount, 0 arrinit __GL_polygonData, __GL_polygon, __GL_MAX_POLYGONS set __GL_polygonCount, 0 arrinit __GL_objectActionData, __GL_objectAction, __GL_MAX_OBJECT_ACTIONS arrinit __GL_object.actionList, 0, __GL_MAX_OBJECT_ACTIONS arrinit __GL_objectData, __GL_object, __GL_MAX_OBJECTS set __GL_objectCount, 0 arrinit __GL_pvData 0, __GL_MAX_PV_DATA set __GL_pvDataCount, 0 arrinit __GL_plData 0, __GL_MAX_PL_DATA set __GL_plDataCount 0 set __GL_angleX, 0 set __GL_angleY, 0 set __GL_angleZ, 0 arrinit __GL_buffer, 0, 200 return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glSet // Description : Change settings. //----------------------------------------------------------------------------------------- subroutine __GL_glSet brcmp EQ, __GL_nbc_gl_set_circle_size, __GL_glSettingType, GL_CIRCLE_SIZE brcmp EQ, __GL_nbc_gl_set_cull_mode, __GL_glSettingType, GL_CULL_MODE brcmp EQ, __GL_nbc_gl_set_camera_depth, __GL_glSettingType, GL_CAMERA_DEPTH brcmp EQ, __GL_nbc_gl_set_zoom_factor, __GL_glSettingType, GL_ZOOM_FACTOR // unknown setting... jmp __GL_nbc_gl_set_done __GL_nbc_gl_set_circle_size: mov __GL_glSettings.circleSize, __GL_glSettingValue jmp __GL_nbc_gl_set_done __GL_nbc_gl_set_cull_mode: mov __GL_glSettings.cullMode, __GL_glSettingValue jmp __GL_nbc_gl_set_done __GL_nbc_gl_set_camera_depth: mov __GL_glSettings.camDepth, __GL_glSettingValue jmp __GL_nbc_gl_set_done __GL_nbc_gl_set_zoom_factor: mov __GL_glSettings.zoom, __GL_glSettingValue __GL_nbc_gl_set_done: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glAddVertex // Description : Check if there's an existing vertex with the same (x,y,z) coord. // If there's an existing vertex found then return the index to that vertex // else add the vertex to the list and return the index of the added vertex. //----------------------------------------------------------------------------------------- subroutine __GL_glAddVertex brcmp EQ, __GL_nbc_gl_add_vertex_error, __GL_glErrorState, TRUE // check if the list is empty... brcmp EQ, __GL_nbc_gl_empty_vertex_list, __GL_vertexCount, 0 // loop through the list... mov __GL_i, __GL_object.firstVertex __GL_nbc_gl_find_vertex: index __GL_vertex1, __GL_vertexData, __GL_i brcmp NEQ, __GL_nbc_gl_vertex_not_equal, __GL_vertex1.orig.x, __GL_vertex0.orig.x brcmp NEQ, __GL_nbc_gl_vertex_not_equal, __GL_vertex1.orig.y, __GL_vertex0.orig.y brcmp NEQ, __GL_nbc_gl_vertex_not_equal, __GL_vertex1.orig.z, __GL_vertex0.orig.z mov __GL_vertexIndex, __GL_i jmp __GL_nbc_gl_add_vertex_done __GL_nbc_gl_vertex_not_equal: add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_find_vertex, __GL_i, __GL_object.lastVertex __GL_nbc_gl_empty_vertex_list: __glRangeCheck(__GL_vertexCount, __GL_MAX_VERTICES, 'Too many vertices') brcmp EQ, __GL_nbc_gl_add_vertex_error, __GL_glErrorState, TRUE // there's no matching vertex found, add a new vertex to the list... replace __GL_vertexData, __GL_vertexData, __GL_vertexCount, __GL_vertex0 mov __GL_vertexIndex, __GL_vertexCount add __GL_vertexCount, __GL_vertexCount, 1 __GL_nbc_gl_add_vertex_done: replace __GL_pvData, __GL_pvData, __GL_polygon.lastVertex, __GL_vertexIndex add __GL_polygon.lastVertex, __GL_polygon.lastVertex, 1 add __GL_pvDataCount, __GL_pvDataCount, 1 mov __GL_object.lastVertex, __GL_vertexCount __GL_nbc_gl_add_vertex_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glEnd // Description : Store the polygon data, call __GL_glAddLines to optimize lines list. //----------------------------------------------------------------------------------------- subroutine __GL_glEnd brcmp EQ, __GL_nbc_gl_end_error, __GL_glErrorState, TRUE call __GL_glAddLines replace __GL_polygonData, __GL_polygonData, __GL_polygonCount, __GL_polygon add __GL_polygonCount, __GL_polygonCount, 1 __GL_nbc_gl_end_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glAddLines // Description : Add the lines of the polygon and check if the line already exists. // Each line should be rendered only once. //----------------------------------------------------------------------------------------- subroutine __GL_glAddLines brcmp EQ, __GL_nbc_gl_add_lines_error, __GL_glErrorState, TRUE mov __GL_polygon.firstLine, __GL_plDataCount // loop through polygon vertex the list... mov __GL_i, __GL_polygon.firstVertex __GL_nbc_gl_find_lines1: add __GL_j, __GL_i, 1 brcmp LT, __GL_nbc_gl_find_lines_modj, __GL_j, __GL_polygon.lastVertex mov __GL_j, __GL_polygon.firstVertex // if the beginMode is GL_LINE then don't close the polygon... brcmp EQ, __GL_nbc_gl_add_line_done2, __GL_polygon.beginMode, GL_LINE __GL_nbc_gl_find_lines_modj: // _a = _pvData[_i] index __GL_a, __GL_pvData, __GL_i // _b = _pvData[_j] index __GL_b, __GL_pvData, __GL_j // check if the list is empty... brcmp EQ, __GL_nbc_empty_lines_list, __GL_lineCount, 0 // loop through the line list to find a matching line... mov __GL_k, __GL_object.firstLine __GL_nbc_gl_find_lines2: index __GL_line, __GL_lineData, __GL_k brcmp NEQ, __GL_nbc_gl_find_line_not_equal1, __GL_a, __GL_line.firstVertex brcmp NEQ, __GL_nbc_gl_find_line_not_equal1, __GL_b, __GL_line.lastVertex mov __GL_lineIndex, __GL_k jmp __GL_nbc_gl_add_line_done1 __GL_nbc_gl_find_line_not_equal1: brcmp NEQ, __GL_nbc_gl_find_line_not_equal2, __GL_b, __GL_line.firstVertex brcmp NEQ, __GL_nbc_gl_find_line_not_equal2, __GL_a, __GL_line.lastVertex mov __GL_lineIndex, __GL_k jmp __GL_nbc_gl_add_line_done1 __GL_nbc_gl_find_line_not_equal2: add __GL_k, __GL_k, 1 brcmp LT, __GL_nbc_gl_find_lines2, __GL_k, __GL_lineCount __GL_nbc_empty_lines_list: mov __GL_line.firstVertex, __GL_a mov __GL_line.lastVertex, __GL_b __glRangeCheck(__GL_lineCount, __GL_MAX_LINES, 'Too many lines') brcmp EQ, __GL_nbc_gl_add_lines_error, __GL_glErrorState, TRUE // _lineData[_lineCount] = _line replace __GL_lineData, __GL_lineData, __GL_lineCount, __GL_line mov __GL_lineIndex, __GL_lineCount add __GL_lineCount, __GL_lineCount, 1 __GL_nbc_gl_add_line_done1: __glRangeCheck(__GL_plDataCount, __GL_MAX_PL_DATA, 'Too many poly-lines') brcmp EQ, __GL_nbc_gl_add_lines_error, __GL_glErrorState, TRUE // _plData[_plDataCount] = _lineIndex replace __GL_plData, __GL_plData, __GL_plDataCount, __GL_lineIndex add __GL_plDataCount, __GL_plDataCount, 1 add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_find_lines1, __GL_i, __GL_polygon.lastVertex __GL_nbc_gl_add_line_done2: mov __GL_polygon.lastLine, __GL_plDataCount __GL_nbc_gl_add_lines_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glEndObject // Description : Save the last polygon number, store the object in the objectlist. //----------------------------------------------------------------------------------------- subroutine __GL_glEndObject brcmp EQ, __GL_nbc_gl_end_object_error, __GL_glErrorState, TRUE mov __GL_object.lastPolygon, __GL_polygonCount replace __GL_objectData, __GL_objectData, __GL_objectCount, __GL_object add __GL_objectCount, __GL_objectCount, 1 __GL_nbc_gl_end_object_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glObjectAction // Description : Add an action to the object... //----------------------------------------------------------------------------------------- subroutine __GL_glObjectAction index __GL_object, __GL_objectData, __GL_objectIndex mov __GL_objectAction.type, __GL_action mov __GL_objectAction.value, __GL_value brcmp EQ, __GL_nbc_gl_action_rotate, __GL_action, GL_ROTATE_X brcmp EQ, __GL_nbc_gl_action_rotate, __GL_action, GL_ROTATE_Y brcmp EQ, __GL_nbc_gl_action_rotate, __GL_action, GL_ROTATE_Z jmp __GL_nbc_gl_action_no_rotate __GL_nbc_gl_action_rotate: // if the action is a rotation of any kind then grab the sin and cos of the angle mod __GL_value, __GL_value, 360 // sind __GL_objectAction.fsin, __GL_value // cosd __GL_objectAction.fcos, __GL_value index __GL_objectAction.lsin, __GL_SIN_TABLE, __GL_value add __GL_value, __GL_value, 90 mod __GL_value, __GL_value, 360 index __GL_objectAction.lcos, __GL_SIN_TABLE, __GL_value __GL_nbc_gl_action_no_rotate: __glRangeCheck(__GL_object.actionCount, __GL_MAX_OBJECT_ACTIONS, 'Too many object-actions') brcmp EQ, __GL_nbc_gl_add_object_error, __GL_glErrorState, TRUE // _object.actionList[_object.actionCount] = _objectActionCount replace __GL_object.actionList, __GL_object.actionList, __GL_object.actionCount, __GL_objectActionCount add __GL_object.actionCount, __GL_object.actionCount, 1 replace __GL_objectData, __GL_objectData, __GL_objectIndex, __GL_object __glRangeCheck(__GL_objectActionCount, __GL_MAX_OBJECT_ACTIONS, 'Too many object-actions') brcmp EQ, __GL_nbc_gl_add_object_error, __GL_glErrorState, TRUE // _objectActionData[_objectActionCount] = _objectAction replace __GL_objectActionData, __GL_objectActionData, __GL_objectActionCount, __GL_objectAction add __GL_objectActionCount, __GL_objectActionCount, 1 __GL_nbc_gl_add_object_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glRotateObject // Description : Check the object actions and apply them to the object... //----------------------------------------------------------------------------------------- subroutine __GL_glRotateObject mov __GL_i, __GL_object.firstVertex __GL_nbc_gl_apply_next_vertex: index __GL_vertex0, __GL_vertexData, __GL_i mov __GL_vertex0.rot.x, __GL_vertex0.orig.x mov __GL_vertex0.rot.y, __GL_vertex0.orig.y mov __GL_vertex0.rot.z, __GL_vertex0.orig.z brcmp EQ, __GL_nbc_gl_no_actions, __GL_object.actionCount, 0 set __GL_j, 0 __GL_nbc_gl_apply_next_action: // _objectAction = _objectActionData[_object.actionData[_j]] index __GL_k, __GL_object.actionList, __GL_j index __GL_objectAction, __GL_objectActionData, __GL_k brcmp EQ, __GL_nbc_gl_apply_translate_x, __GL_objectAction.type, GL_TRANSLATE_X brcmp EQ, __GL_nbc_gl_apply_translate_y, __GL_objectAction.type, GL_TRANSLATE_Y brcmp EQ, __GL_nbc_gl_apply_translate_z, __GL_objectAction.type, GL_TRANSLATE_Z brcmp EQ, __GL_nbc_gl_apply_rotate_x, __GL_objectAction.type, GL_ROTATE_X brcmp EQ, __GL_nbc_gl_apply_rotate_y, __GL_objectAction.type, GL_ROTATE_Y brcmp EQ, __GL_nbc_gl_apply_rotate_z, __GL_objectAction.type, GL_ROTATE_Z brcmp EQ, __GL_nbc_gl_apply_scale_x, __GL_objectAction.type, GL_SCALE_X brcmp EQ, __GL_nbc_gl_apply_scale_y, __GL_objectAction.type, GL_SCALE_Y brcmp EQ, __GL_nbc_gl_apply_scale_z, __GL_objectAction.type, GL_SCALE_Z jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_translate_x: add __GL_vertex0.rot.x, __GL_vertex0.rot.x, __GL_objectAction.value jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_translate_y: add __GL_vertex0.rot.y, __GL_vertex0.rot.y, __GL_objectAction.value jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_translate_z: add __GL_vertex0.rot.z, __GL_vertex0.rot.z, __GL_objectAction.value jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_rotate_x: mul __GL_a, __GL_objectAction.lcos, __GL_vertex0.rot.y shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lsin, __GL_vertex0.rot.z shr __GL_b, __GL_b, 15 sub __GL_c, __GL_a, __GL_b mul __GL_a, __GL_objectAction.lsin, __GL_vertex0.rot.y shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lcos, __GL_vertex0.rot.z shr __GL_b, __GL_b, 15 add __GL_d, __GL_a, __GL_b mov __GL_vertex0.rot.y, __GL_c mov __GL_vertex0.rot.z, __GL_d jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_rotate_y: mul __GL_a, __GL_objectAction.lsin, __GL_vertex0.rot.z shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lcos, __GL_vertex0.rot.x shr __GL_b, __GL_b, 15 add __GL_c, __GL_a, __GL_b mul __GL_a, __GL_objectAction.lcos, __GL_vertex0.rot.z shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lsin, __GL_vertex0.rot.x shr __GL_b, __GL_b, 15 sub __GL_d, __GL_a, __GL_b mov __GL_vertex0.rot.x, __GL_c mov __GL_vertex0.rot.z, __GL_d jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_rotate_z: mul __GL_a, __GL_objectAction.lcos, __GL_vertex0.rot.x shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lsin, __GL_vertex0.rot.y shr __GL_b, __GL_b, 15 sub __GL_c, __GL_a, __GL_b mul __GL_a, __GL_objectAction.lsin, __GL_vertex0.rot.x shr __GL_a, __GL_a, 15 mul __GL_b, __GL_objectAction.lcos, __GL_vertex0.rot.y shr __GL_b, __GL_b, 15 add __GL_d, __GL_a, __GL_b mov __GL_vertex0.rot.x, __GL_c mov __GL_vertex0.rot.y, __GL_d jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_scale_x: mul __GL_vertex0.rot.x, __GL_vertex0.rot.x, __GL_objectAction.value shr __GL_vertex0.rot.x, __GL_vertex0.rot.x, 8 jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_scale_y: mul __GL_vertex0.rot.y, __GL_vertex0.rot.y, __GL_objectAction.value shr __GL_vertex0.rot.y, __GL_vertex0.rot.y, 8 jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_scale_z: mul __GL_vertex0.rot.z, __GL_vertex0.rot.z, __GL_objectAction.value shr __GL_vertex0.rot.z, __GL_vertex0.rot.z, 8 jmp __GL_nbc_gl_apply_done __GL_nbc_gl_apply_done: add __GL_j, __GL_j, 1 brcmp LT, __GL_nbc_gl_apply_next_action, __GL_j, __GL_object.actionCount __GL_nbc_gl_no_actions: replace __GL_vertexData, __GL_vertexData, __GL_i, __GL_vertex0 add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_apply_next_vertex, __GL_i, __GL_object.lastVertex return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glRotateVertexList // Description : Rotate all the vertices in the vertext list... //----------------------------------------------------------------------------------------- subroutine __GL_glRotateVertexList // update all object actions first... set __GL_l, 0 __GL_nbc_gl_rotate_objects: index __GL_object, __GL_objectData, __GL_l brcmp EQ, __GL_nbc_gl_dont_rotate_object, __GL_object.render, FALSE call __GL_glRotateObject __GL_nbc_gl_dont_rotate_object: add __GL_l, __GL_l, 1 brcmp LT, __GL_nbc_gl_rotate_objects, __GL_l, __GL_objectCount mov __GL_saveAngleX, __GL_angleX mov __GL_saveAngleY, __GL_angleY index __GL_sinX, __GL_SIN_TABLE, __GL_angleX add __GL_angleX, __GL_angleX, 90 mod __GL_angleX, __GL_angleX, 360 index __GL_cosX, __GL_SIN_TABLE, __GL_angleX index __GL_sinY, __GL_SIN_TABLE, __GL_angleY add __GL_angleY, __GL_angleY, 90 mod __GL_angleY, __GL_angleY, 360 index __GL_cosY, __GL_SIN_TABLE, __GL_angleY mov __GL_camDepth, __GL_glSettings.camDepth mov __GL_zoom, __GL_glSettings.zoom set __GL_i, 0 set __GL_vertexOffset, 0 __GL_nbc_gl_rotate_loop: // get the values from the vertex list... index __GL_vertex0, __GL_vertexData, __GL_vertexOffset // z1 = (_vertex0.rot.z * _cosY) - (_vertex0.rot.x * _sinY) mul __GL_a, __GL_vertex0.rot.z, __GL_cosY shr __GL_a, __GL_a, 15 mul __GL_b, __GL_vertex0.rot.x, __GL_sinY shr __GL_b, __GL_b, 15 sub __GL_z1, __GL_a, __GL_b // xx = (_vertex0.rot.z * _sinY) + (_vertex0.rot.x * _cosY) mul __GL_a, __GL_vertex0.rot.z, __GL_sinY shr __GL_a, __GL_a, 15 mul __GL_b, __GL_vertex0.rot.x, __GL_cosY shr __GL_b, __GL_b, 15 add __GL_xx, __GL_a, __GL_b // zz = (_vertex0.rot.y * _sinX) + (_z1 * _cosX) + _zoom mul __GL_a, __GL_vertex0.rot.y, __GL_sinX shr __GL_a, __GL_a, 15 mul __GL_b, __GL_z1, __GL_cosX shr __GL_b, __GL_b, 15 add __GL_zz, __GL_a, __GL_b add __GL_zz, __GL_zz, __GL_zoom // yy = (_vertex0.rot.y * cosX) - (z1 * sinX) mul __GL_a, __GL_vertex0.rot.y, __GL_cosX shr __GL_a, __GL_a, 15 mul __GL_b, __GL_z1, __GL_sinX shr __GL_b, __GL_b, 15 sub __GL_yy, __GL_a, __GL_b // the actual screen coords... add __GL_zz, __GL_zz, __GL_camDepth // _vertex0.screen.sx = width + (x * camDepth) / (zz + camDepth)) // _vertex0.screen.sy = height - (y * camDepth) / (zz + camDepth)) mul __GL_vertex0.screen.x, __GL_xx, __GL_camDepth div __GL_vertex0.screen.x, __GL_vertex0.screen.x, __GL_zz add __GL_vertex0.screen.x, __GL_vertex0.screen.x, 50 mul __GL_vertex0.screen.y, __GL_yy, __GL_camDepth div __GL_vertex0.screen.y, __GL_vertex0.screen.y, __GL_zz sub __GL_vertex0.screen.y, 32, __GL_vertex0.screen.y // save the screen coords... replace __GL_vertexData, __GL_vertexData, __GL_vertexOffset, __GL_vertex0 add __GL_vertexOffset, __GL_vertexOffset, 1 add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_rotate_loop, __GL_i, __GL_vertexCount mov __GL_angleX, __GL_saveAngleX mov __GL_angleY, __GL_saveAngleY return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glResetObjects // Description : Reset the rotate, translate and scale actions for all objects... //----------------------------------------------------------------------------------------- subroutine __GL_glResetObjects set __GL_glLinesClipped, 0 brcmp EQ, __GL_nbc_gl_reset_objects_error, __GL_glErrorState, TRUE arrinit __GL_lineDone, 0, __GL_lineCount set __GL_objectActionCount, 0 set __GL_i, 0 __GL_nbc_gl_reset_actions: index __GL_object, __GL_objectData, __GL_i set __GL_object.actionCount, 0 set __GL_object.render, FALSE replace __GL_objectData, __GL_objectData, __GL_i, __GL_object add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_reset_actions, __GL_i, __GL_objectCount __GL_nbc_gl_reset_objects_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glCallObject // Description : Set the render boolean, copy the settings... //----------------------------------------------------------------------------------------- subroutine __GL_glCallObject brcmp EQ, __GL_nbc_gl_call_object_error, __GL_glErrorState, TRUE index __GL_object, __GL_objectData, __GL_objectIndex set __GL_object.render, TRUE mov __GL_object.cullMode, __GL_glSettings.cullMode mov __GL_object.circleSize, __GL_glSettings.circleSize replace __GL_objectData, __GL_objectData, __GL_objectIndex, __GL_object __GL_nbc_gl_call_object_error: return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glDrawObject // Description : Draw the object, this routine expects the '_object' struct to be set. //----------------------------------------------------------------------------------------- subroutine __GL_glDrawObject // set once... mov __GL_glDrawLine.Options, 0 // loop through the polygon list for this object... mov __GL_i, __GL_object.firstPolygon __GL_nbc_gl_draw_polygons: // get the information for the polygon... index __GL_polygon, __GL_polygonData, __GL_i brcmp EQ, __GL_nbc_gl_render_polygon, __GL_polygon.beginMode, GL_POLYGON brcmp EQ, __GL_nbc_gl_render_line, __GL_polygon.beginMode, GL_LINE brcmp EQ, __GL_nbc_gl_render_point, __GL_polygon.beginMode, GL_POINT brcmp EQ, __GL_nbc_gl_render_circle, __GL_polygon.beginMode, GL_CIRCLE jmp __GL_nbc_gl_cull_polygon //--------------------------------------------------------------------------------------- // Render a polygon... //--------------------------------------------------------------------------------------- __GL_nbc_gl_render_polygon: // loop through the vertex list for this polygon... mov __GL_j, __GL_polygon.firstVertex mov __GL_k, __GL_polygon.lastVertex // _vertex0 = _vertexData[_pvData[j]] index __GL_vertexOffset, __GL_pvData, __GL_j index __GL_vertex0, __GL_vertexData, __GL_vertexOffset // _vertex1 = _vertexData[_pvData[j + 1]] add __GL_j, __GL_j, 1 index __GL_vertexOffset, __GL_pvData, __GL_j index __GL_vertex1, __GL_vertexData, __GL_vertexOffset // _vertex2 = _vertexData[_pvData[j + 2]] add __GL_j, __GL_j, 1 index __GL_vertexOffset, __GL_pvData, __GL_j index __GL_vertex2, __GL_vertexData, __GL_vertexOffset // check if culling is enabled... brcmp EQ, __GL_nbc_gl_no_culling, __GL_object.cullMode, GL_CULL_NONE // calculate the culling... // ((x1 - x0) * (y2 - y0) >= (x2 - x0) * (y1 - y0)) sub __GL_a, __GL_vertex1.screen.x, __GL_vertex0.screen.x sub __GL_b, __GL_vertex2.screen.y, __GL_vertex0.screen.y mul __GL_c, __GL_a, __GL_b sub __GL_d, __GL_vertex2.screen.x, __GL_vertex0.screen.x sub __GL_e, __GL_vertex1.screen.y, __GL_vertex0.screen.y mul __GL_f, __GL_d, __GL_e // check if culling is enabled... brcmp EQ, __GL_nbc_gl_check_front_cull, __GL_object.cullMode, GL_CULL_FRONT brcmp GTEQ, __GL_nbc_gl_cull_polygon, __GL_c, __GL_f jmp __GL_nbc_gl_no_culling __GL_nbc_gl_check_front_cull: brcmp GTEQ, __GL_nbc_gl_cull_polygon, __GL_f, __GL_c __GL_nbc_gl_no_culling: //--> render the lines... mov __GL_j, __GL_polygon.firstLine __GL_nbc_gl_draw_lines: // _k = _plData[_j] index __GL_k, __GL_plData, __GL_j // render every line only once! // _l = _lineDone[_k] index __GL_l, __GL_lineDone, __GL_k brcmp EQ, __GL_nbc_gl_line_done, __GL_l, 1 // set the 'done' byte... replace __GL_lineDone, __GL_lineDone, 1, __GL_l // _line = _lineData[_k] index __GL_line, __GL_lineData, __GL_k // _vertex1 = _vertexData[_line.firstVertex] index __GL_vertex1, __GL_vertexData, __GL_line.firstVertex // _vertex1 = _vertexData[_line.lastVertex] index __GL_vertex2, __GL_vertexData, __GL_line.lastVertex // very crude clipping... // add __GL_glLinesClipped, __GL_glLinesClipped, 1 // brcmp LT, __GL_nbc_gl_line_done, __GL_vertex1.screen.x, 0 // brcmp LT, __GL_nbc_gl_line_done, __GL_vertex2.screen.x, 0 // brcmp LT, __GL_nbc_gl_line_done, __GL_vertex1.screen.y, 0 // brcmp LT, __GL_nbc_gl_line_done, __GL_vertex2.screen.y, 0 // brcmp GT, __GL_nbc_gl_line_done, __GL_vertex1.screen.x, 99 // brcmp GT, __GL_nbc_gl_line_done, __GL_vertex2.screen.x, 99 // brcmp GT, __GL_nbc_gl_line_done, __GL_vertex1.screen.y, 63 // brcmp GT, __GL_nbc_gl_line_done, __GL_vertex2.screen.y, 63 // sub __GL_glLinesClipped, __GL_glLinesClipped, 1 // mov __GL_glDrawLine.StartLoc.X, __GL_vertex1.screen.x // mov __GL_glDrawLine.StartLoc.Y, __GL_vertex1.screen.y // mov __GL_glDrawLine.EndLoc.X, __GL_vertex2.screen.x // mov __GL_glDrawLine.EndLoc.Y, __GL_vertex2.screen.y mov __GL_glDrawLine.StartLoc, __GL_vertex1.screen mov __GL_glDrawLine.EndLoc, __GL_vertex2.screen syscall DrawLine, __GL_glDrawLine __GL_nbc_gl_line_done: add __GL_j, __GL_j, 1 brcmp LT, __GL_nbc_gl_draw_lines, __GL_j, __GL_polygon.lastLine //<-- render the lines... /* mov __GL_minX, 1000 mov __GL_maxX, -1000 set __GL_a, 0 __GL_nbc_gl_polygon_loop: add __GL_b, __GL_a, 1 brcmp LT, __GL_nbc_gl_modb, __GL_b, __GL_polygon.lastVertex mov __GL_b, __GL_polygon.firstVertex __GL_nbc_gl_modb: // _vertex1 = _vertexData[_pvData[_a]] index __GL_vertexOffset, __GL_pvData, __GL_a index __GL_vertex1, __GL_vertexData, __GL_vertexOffset // _vertex1 = _vertexData[_pvData[_b]] index __GL_vertexOffset, __GL_pvData, __GL_b index __GL_vertex2, __GL_vertexData, __GL_vertexOffset brcmp GTEQ, __GL_nbc_gl_minx1, __GL_vertex1.screen.x, __GL_minX mov __GL_minX, __GL_vertex1.screen.x __GL_nbc_gl_minx1: brcmp GTEQ, __GL_nbc_gl_minx2, __GL_vertex2.screen.x, __GL_minX mov __GL_minX, __GL_vertex2.screen.x __GL_nbc_gl_minx2: brcmp LTEQ, __GL_nbc_gl_maxx1, __GL_vertex1.screen.x, __GL_maxX mov __GL_maxX, __GL_vertex1.screen.x __GL_nbc_gl_maxx1: brcmp LTEQ, __GL_nbc_gl_maxx2, __GL_vertex2.screen.x, __GL_maxX mov __GL_maxX, __GL_vertex2.screen.x __GL_nbc_gl_maxx2: mov __GL_index, 0 mov __GL_startY, __GL_vertex1.screen.y mov __GL_startX, __GL_vertex1.screen.x mov __GL_endY, __GL_vertex2.screen.y mov __GL_endX, __GL_vertex2.screen.x brcmp GTEQ, __GL_nbc_gl_polygon_flip, __GL_endX, __GL_startX mov __GL_startY, __GL_vertex2.screen.y mov __GL_startX, __GL_vertex2.screen.x mov __GL_endY, __GL_vertex1.screen.y mov __GL_endX, __GL_vertex1.screen.x mov __GL_index, 100 __GL_nbc_gl_polygon_flip: sub __GL_deltaY, __GL_endY, __GL_startY sub __GL_deltaX, __GL_endX, __GL_startX mov __GL_c, __GL_startX __GL_nbc_gl_polygon_line: add __GL_offset, __GL_c, __GL_index // _startY + _deltaY * (_c - _startX) / _deltaX sub __GL_value, __GL_c, __GL_startX mul __GL_value, __GL_value, __GL_deltaY div __GL_value, __GL_value, __GL_deltaX add __GL_value, __GL_value, __GL_startY replace __GL_buffer, __GL_buffer, __GL_offset, __GL_value add __GL_c, __GL_c, 1 brcmp LTEQ __GL_nbc_gl_polygon_line, __GL_c, __GL_endX add __GL_a, __GL_a, 1 brcmp LT __GL_nbc_gl_polygon_loop, __GL_a, __GL_polygon.lastVertex mov __GL_a, __GL_minX __GL_nbc_gl_polygon_lines: index __GL_startY, __GL_buffer, __GL_a add __GL_b, __GL_a, 100 index __GL_endY, __GL_buffer, __GL_b mov __GL_glDrawLine.Options, 0 mov __GL_glDrawLine.StartLoc.X, __GL_a mov __GL_glDrawLine.StartLoc.Y, __GL_startY mov __GL_glDrawLine.EndLoc.X, __GL_a mov __GL_glDrawLine.EndLoc.Y, __GL_endY syscall DrawLine, __GL_glDrawLine add __GL_a, __GL_a, 1 brcmp LTEQ, __GL_nbc_gl_polygon_lines, __GL_a, __GL_maxX */ jmp __GL_nbc_gl_cull_polygon //--------------------------------------------------------------------------------------- // Render lines... //--------------------------------------------------------------------------------------- __GL_nbc_gl_render_line: mov __GL_j, __GL_polygon.firstLine __GL_nbc_gl_render_lines: // _k = _plData[_j] index __GL_k, __GL_plData, __GL_j // render every line only once! // _l = _lineDone[_k] index __GL_l, __GL_lineDone, __GL_k brcmp EQ, __GL_nbc_gl_render_lines_done, __GL_l, 1 // set the 'done' byte... replace __GL_lineDone, __GL_lineDone, 1, __GL_l // _line = _lineData[_k] index __GL_line, __GL_lineData, __GL_k // _vertex1 = _vertexData[_line.firstVertex] // _vertex2 = _vertexData[_line.lastVertex] index __GL_vertex1, __GL_vertexData, __GL_line.firstVertex index __GL_vertex2, __GL_vertexData, __GL_line.lastVertex mov __GL_glDrawLine.StartLoc, __GL_vertex1.screen mov __GL_glDrawLine.EndLoc, __GL_vertex2.screen // mov __GL_glDrawLine.StartLoc.X, __GL_vertex1.screen.x // mov __GL_glDrawLine.StartLoc.Y, __GL_vertex1.screen.y // mov __GL_glDrawLine.EndLoc.X, __GL_vertex2.screen.x // mov __GL_glDrawLine.EndLoc.Y, __GL_vertex2.screen.y syscall DrawLine, __GL_glDrawLine __GL_nbc_gl_render_lines_done: add __GL_j, __GL_j, 1 brcmp LT, __GL_nbc_gl_render_lines, __GL_j, __GL_polygon.lastLine jmp __GL_nbc_gl_cull_polygon //--------------------------------------------------------------------------------------- // Render points... //--------------------------------------------------------------------------------------- __GL_nbc_gl_render_point: set __GL_glDrawPoint.Options, 0 mov __GL_j, __GL_polygon.firstVertex __GL_nbc_gl_render_points: // _vertex0 = _vertexData[_pvData[j]] index __GL_vertexOffset, __GL_pvData, __GL_j index __GL_vertex0, __GL_vertexData, __GL_vertexOffset mov __GL_glDrawPoint.Location, __GL_vertex0.screen // mov __GL_glDrawPoint.Location.X, __GL_vertex0.screen.x // mov __GL_glDrawPoint.Location.Y, __GL_vertex0.screen.y syscall DrawPoint, __GL_glDrawPoint add __GL_j, __GL_j, 1 brcmp LT, __GL_nbc_gl_render_points, __GL_j, __GL_polygon.lastVertex jmp __GL_nbc_gl_cull_polygon //--------------------------------------------------------------------------------------- // Render circle... //--------------------------------------------------------------------------------------- __GL_nbc_gl_render_circle: set __GL_glDrawCircle.Options, 0 mov __GL_glDrawCircle.Size, __GL_object.circleSize mov __GL_j, __GL_polygon.firstVertex __GL_nbc_gl_render_circles: // _vertex0 = _vertexData[_pvData[j]] index __GL_vertexOffset, __GL_pvData, __GL_j index __GL_vertex0, __GL_vertexData, __GL_vertexOffset mov __GL_glDrawCircle.Center, __GL_vertex0.screen // mov __GL_glDrawCircle.Center.X, __GL_vertex0.screen.x // mov __GL_glDrawCircle.Center.Y, __GL_vertex0.screen.y syscall DrawCircle, __GL_glDrawCircle add __GL_j, __GL_j, 1 brcmp LT, __GL_nbc_gl_render_circles, __GL_j, __GL_polygon.lastVertex jmp __GL_nbc_gl_cull_polygon __GL_nbc_gl_cull_polygon: add __GL_i, __GL_i, 1 brcmp LT, __GL_nbc_gl_draw_polygons, __GL_i, __GL_object.lastPolygon return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glRenderObjects // Description : Draw all objects which have been called... //----------------------------------------------------------------------------------------- subroutine __GL_glRenderObjects brcmp EQ, __GL_nbc_gl_render_objects_error, __GL_glErrorState, TRUE set __GL_objectIndex, 0 __GL_nbc_gl_render_objects: // get the information for the object... index __GL_object, __GL_objectData, __GL_objectIndex brcmp EQ, __GL_nbc_gl_dont_render_object, __GL_object.render, FALSE call __GL_glDrawObject __GL_nbc_gl_dont_render_object: add __GL_objectIndex, __GL_objectIndex, 1 brcmp LT, __GL_nbc_gl_render_objects, __GL_objectIndex, __GL_objectCount return __GL_nbc_gl_render_objects_error: // Display the error message... set __GL_glDrawData.Options, 1 set __GL_glDrawData.Location.X, 0 set __GL_glDrawData.Location.Y, 56 mov __GL_glDrawData.Text, 'Error:' syscall DrawText, __GL_glDrawData set __GL_glDrawData.Options, 0 set __GL_glDrawData.Location.Y, 48 mov __GL_glDrawData.Text, __GL_glErrorMsg syscall DrawText, __GL_glDrawData return ends dseg segment __GL_tmpId byte __GL_mode byte __GL_sizeX sdword __GL_sizeY sdword __GL_sizeZ sdword __GL_angle sdword dseg ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glBox // Description : Add a box with the dimensions: _sizeX, _sizeY, _sizeZ. // Use mode _mode. //----------------------------------------------------------------------------------------- subroutine __GL_glBox shr __GL_x1, __GL_sizeX, 1 neg __GL_x0, __GL_x1 shr __GL_y1, __GL_sizeY, 1 neg __GL_y0, __GL_y1 shr __GL_z1, __GL_sizeZ, 1 neg __GL_z0, __GL_z1 __glBeginObject(__GL_tmpId) __glBegin(__GL_mode) __glAddVertex(__GL_x0, __GL_y0, __GL_z0) __glAddVertex(__GL_x1, __GL_y0, __GL_z0) __glAddVertex(__GL_x1, __GL_y1, __GL_z0) __glAddVertex(__GL_x0, __GL_y1, __GL_z0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x0, __GL_y1, __GL_z1) __glAddVertex(__GL_x1, __GL_y1, __GL_z1) __glAddVertex(__GL_x1, __GL_y0, __GL_z1) __glAddVertex(__GL_x0, __GL_y0, __GL_z1) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x0, __GL_y1, __GL_z0) __glAddVertex(__GL_x0, __GL_y1, __GL_z1) __glAddVertex(__GL_x0, __GL_y0, __GL_z1) __glAddVertex(__GL_x0, __GL_y0, __GL_z0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x1, __GL_y0, __GL_z0) __glAddVertex(__GL_x1, __GL_y0, __GL_z1) __glAddVertex(__GL_x1, __GL_y1, __GL_z1) __glAddVertex(__GL_x1, __GL_y1, __GL_z0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x0, __GL_y0, __GL_z0) __glAddVertex(__GL_x0, __GL_y0, __GL_z1) __glAddVertex(__GL_x1, __GL_y0, __GL_z1) __glAddVertex(__GL_x1, __GL_y0, __GL_z0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x1, __GL_y1, __GL_z0) __glAddVertex(__GL_x1, __GL_y1, __GL_z1) __glAddVertex(__GL_x0, __GL_y1, __GL_z1) __glAddVertex(__GL_x0, __GL_y1, __GL_z0) __glEnd() __glEndObject() return ends //----------------------------------------------------------------------------------------- // Subroutine : __GL_glPyramid // Description : Add a pyramid with the dimensions: _sizeX, _sizeY, _sizeZ. // Use mode _mode. //----------------------------------------------------------------------------------------- subroutine __GL_glPyramid shr __GL_x1, __GL_sizeX, 1 neg __GL_x0, __GL_x1 shr __GL_z1, __GL_sizeZ, 1 neg __GL_z0, __GL_z1 neg __GL_y0, __GL_sizeY __glBeginObject(__GL_tmpId) __glBegin(__GL_mode) __glAddVertex(__GL_x1, 0, __GL_z0) __glAddVertex(__GL_x1, 0, __GL_z1) __glAddVertex(__GL_x0, 0, __GL_z1) __glAddVertex(__GL_x0, 0, __GL_z0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x0, 0, __GL_z0) __glAddVertex(__GL_x0, 0, __GL_z1) __glAddVertex(0, __GL_y0, 0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x1, 0, __GL_z1) __glAddVertex(__GL_x1, 0, __GL_z0) __glAddVertex(0, __GL_y0, 0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x1, 0, __GL_z0) __glAddVertex(__GL_x0, 0, __GL_z0) __glAddVertex(0, __GL_y0, 0) __glEnd() __glBegin(__GL_mode) __glAddVertex(__GL_x0, 0, __GL_z1) __glAddVertex(__GL_x1, 0, __GL_z1) __glAddVertex(0, __GL_y0, 0) __glEnd() __glEndObject() return ends // no documentation for these functions since they are essentially readonly #define SetLSInputBuffer(_p, _offset, _cnt, _data) __setLSInputBuffer(_p, _offset, _cnt, _data) #define SetLSInputBufferInPtr(_p, _n) __setLSInputBufferInPtr(_p, _n) #define SetLSInputBufferOutPtr(_p, _n) __setLSInputBufferOutPtr(_p, _n) #define SetLSInputBufferBytesToRx(_p, _n) __setLSInputBufferBytesToRx(_p, _n) #define SetLSOutputBuffer(_p, _offset, _cnt, _data) __setLSOutputBuffer(_p, _offset, _cnt, _data) #define SetLSOutputBufferInPtr(_p, _n) __setLSOutputBufferInPtr(_p, _n) #define SetLSOutputBufferOutPtr(_p, _n) __setLSOutputBufferOutPtr(_p, _n) #define SetLSOutputBufferBytesToRx(_p, _n) __setLSOutputBufferBytesToRx(_p, _n) #define SetLSMode(_p, _n) __setLSMode(_p, _n) #define SetLSChannelState(_p, _n) __setLSChannelState(_p, _n) #define SetLSErrorType(_p, _n) __setLSErrorType(_p, _n) #define SetLSState(_n) __setLSState(_n) #define SetLSSpeed(_n) __setLSSpeed(_n) #ifdef __ENHANCED_FIRMWARE #define SetLSNoRestartOnRead(_n) __setLSNoRestartOnRead(_n) #endif // these functions really cannot be used for any useful purpose (read-only) #define SetBTDeviceName(_p, _str) __setBTDeviceName(_p, _str) #define SetBTDeviceAddress(_p, _btaddr) __setBTDeviceAddress(_p, _btaddr) #define SetBTConnectionName(_p, _str) __setBTConnectionName(_p, _str) #define SetBTConnectionPinCode(_p, _code) __setBTConnectionPinCode(_p, _code) #define SetBTConnectionAddress(_p, _btaddr) __setBTConnectionAddress(_p, _btaddr) #define SetBrickDataName(_str) SetCommModuleBytes(CommOffsetBrickDataName, 16, _str) #define SetBrickDataAddress(_btaddr) SetCommModuleBytes(CommOffsetBrickDataBdAddr, 7, _btaddr) #define SetBTDeviceClass(_p, _n) __setBTDeviceClass(_p, _n) #define SetBTDeviceStatus(_p, _n) __setBTDeviceStatus(_p, _n) #define SetBTConnectionClass(_p, _n) __setBTConnectionClass(_p, _n) #define SetBTConnectionHandleNum(_p, _n) __setBTConnectionHandleNum(_p, _n) #define SetBTConnectionStreamStatus(_p, _n) __setBTConnectionStreamStatus(_p, _n) #define SetBTConnectionLinkQuality(_p, _n) __setBTConnectionLinkQuality(_p, _n) #define SetBrickDataBluecoreVersion(_n) __setBrickDataBluecoreVersion(_n) #define SetBrickDataBtStateStatus(_n) __setBrickDataBtStateStatus(_n) #define SetBrickDataBtHardwareStatus(_n) __setBrickDataBtHardwareStatus(_n) #define SetBrickDataTimeoutValue(_n) __setBrickDataTimeoutValue(_n) #define SetBTDeviceCount(_n) __setBTDeviceCount(_n) #define SetBTDeviceNameCount(_n) __setBTDeviceNameCount(_n) // not ready to be documented #define SpawnProgram(_fname) __spawnProgram(_fname) // standard firmware math functions written by Tamas Sorosy (www.sorosy.com) // X is any integer, Y is the sqrt value (0->max), if X<0, Y is the sqrt value of absolute X #define Sqrt(_X,_R) __SQRT(_X,_R) // X is any integer in degrees, Y is 100* the sin value (-100->100) #define Sin(_X,_R) __SIN(_X,_R) // X is any integer in degrees, Y is 100* the cos value (-100->100) #define Cos(_X,_R) __COS(_X,_R) // X is 100* the sin value (-100->100), Y is -90->90, Y is 101 if X is outside -100->100 range #define Asin(_X,_R) __ASIN(_X,_R) // X is 100* the cos value (-100->100), Y is 0->180, Y is -11 if X is outside -100->100 range #define Acos(_X,_R) __ACOS(_X,_R) dseg segment __Pos_i sword __Pos_l1 sword __Pos_lDelta sword __Pos_tmpstr byte[] __Pos_s2 byte[] __Pos_s1 byte[] __Pos_Result sword __Pos_Mutex mutex dseg ends subroutine __PosSubroutine arrsize __Pos_l1, __Pos_s1 sub __Pos_l1, __Pos_l1, 1 arrsize __Pos_lDelta, __Pos_s2 sub __Pos_lDelta, __Pos_lDelta, __Pos_l1 set __Pos_i, 0 __Pos_Repeat: sub __Pos_lDelta, __Pos_lDelta, 1 brtst 0, __Pos_RepeatEnd, __Pos_lDelta strsubset __Pos_tmpstr, __Pos_s2, __Pos_i, __Pos_l1 cmp 4, __Pos_Result, __Pos_s1, __Pos_tmpstr brtst 4, __Pos_RepeatAgain, __Pos_Result mov __Pos_Result, __Pos_i return __Pos_RepeatAgain: add __Pos_i, __Pos_i, 1 jmp __Pos_Repeat __Pos_RepeatEnd: set __Pos_Result, -1 return ends #define __doPos(_s1, _s2, _result) \ acquire __Pos_Mutex \ mov __Pos_s1, _s1 \ mov __Pos_s2, _s2 \ call __PosSubroutine \ mov _result, __Pos_Result \ release __Pos_Mutex \ #endif /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// OUTPUT MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup OutputModule * @{ */ /** @defgroup OutputModuleFunctions Output module functions * Functions for accessing and modifying output module features. * @{ */ /** * Reset tachometer counter. * Reset the tachometer count and tachometer limit goal for the specified * outputs. * * \param _p Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ #define ResetTachoCount(_p) __resetTachoCount(_p) /** * Reset block-relative counter. * Reset the block-relative position counter for the specified outputs. * * \param _p Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ #define ResetBlockTachoCount(_p) __resetBlockTachoCount(_p) /** * Reset program-relative counter. * Reset the program-relative position counter for the specified outputs. * * \param _p Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ #define ResetRotationCount(_p) __resetRotationCount(_p) /** * Reset all tachometer counters. * Reset all three position counters and reset the current tachometer limit * goal for the specified outputs. * * \param _p Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ #define ResetAllTachoCounts(_p) __resetAllTachoCounts(_p) /** * Run motors forward and reset counters. * Set outputs to forward direction and turn them on. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnFwdEx(_ports, _pwr, _reset) __OnFwdEx(_ports, _pwr, _reset) /** * Run motors backward and reset counters. * Set outputs to reverse direction and turn them on. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnRevEx(_ports, _pwr, _reset) __OnRevEx(_ports, _pwr, _reset) /** * Run motors forward and reset counters. * Set outputs to forward direction and turn them on. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnFwdExPID(_ports, _pwr, _reset, _p, _i, _d) __OnFwdExPID(_ports, _pwr, _reset, _p, _i, _d) /** * Run motors backward and reset counters. * Set outputs to reverse direction and turn them on. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnRevExPID(_ports, _pwr, _reset, _p, _i, _d) __OnRevExPID(_ports, _pwr, _reset, _p, _i, _d) /** * Run motors forward. * Set outputs to forward direction and turn them on. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. */ #define OnFwd(_ports, _pwr) OnFwdEx(_ports, _pwr, RESET_BLOCKANDTACHO) /** * Run motors backward. * Set outputs to reverse direction and turn them on. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. */ #define OnRev(_ports, _pwr) OnRevEx(_ports, _pwr, RESET_BLOCKANDTACHO) /** * Coast motors and reset counters. * Turn off the specified outputs, making them coast to a stop. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define CoastEx(_ports, _reset) __CoastEx(_ports, _reset) /** * Turn motors off and reset counters. * Turn the specified outputs off (with braking). * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OffEx(_ports, _reset) __OffEx(_ports, _reset) /** * Coast motors. * Turn off the specified outputs, making them coast to a stop. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ #define Coast(_ports) CoastEx(_ports, RESET_BLOCKANDTACHO) /** * Turn motors off. * Turn the specified outputs off (with braking). * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ #define Off(_ports) OffEx(_ports, RESET_BLOCKANDTACHO) /** * Float motors. * Make outputs float. Float is an alias for Coast. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ #define Float(_ports) Coast(_ports) /** * Run motors forward regulated and reset counters. * Run the specified outputs forward using the specified regulation mode. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnFwdRegEx(_ports, _pwr, _regmode, _reset) __OnFwdRegEx(_ports, _pwr, _regmode, _reset) /** * Run motors backward regulated and reset counters. * Run the specified outputs in reverse using the specified regulation mode. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnRevRegEx(_ports, _pwr, _regmode, _reset) __OnRevRegEx(_ports, _pwr, _regmode, _reset) /** * Run motors forward regulated and reset counters with PID factors. * Run the specified outputs forward using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnFwdRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) __OnFwdRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) /** * Run motors backward regulated and reset counters with PID factors. * Run the specified outputs in reverse using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnRevRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) __OnRevRegExPID(_ports, _pwr, _regmode, _reset, _p, _i, _d) /** * Run motors forward regulated. * Run the specified outputs forward using the specified regulation mode. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. */ #define OnFwdReg(_ports, _pwr, _regmode) OnFwdRegEx(_ports, _pwr, _regmode, RESET_BLOCKANDTACHO) /** * Run motors forward regulated. * Run the specified outputs in reverse using the specified regulation mode. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. */ #define OnRevReg(_ports, _pwr, _regmode) OnRevRegEx(_ports, _pwr, _regmode, RESET_BLOCKANDTACHO) /** * Run motors forward regulated with PID factors. * Run the specified outputs forward using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnFwdRegPID(_ports, _pwr, _regmode, _p, _i, _d) OnFwdRegExPID(_ports, _pwr, _regmode, RESET_BLOCKANDTACHO, _p, _i, _d) /** * Run motors reverse regulated with PID factors. * Run the specified outputs in reverse using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _regmode Regulation mode, see \ref OutRegModeConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnRevRegPID(_ports, _pwr, _regmode, _p, _i, _d) OnRevRegExPID(_ports, _pwr, _regmode, RESET_BLOCKANDTACHO, _p, _i, _d) /** * Run motors forward synchronised and reset counters. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnFwdSyncEx(_ports, _pwr, _turnpct, _reset) __OnFwdSyncEx(_ports, _pwr, _turnpct, _reset) /** * Run motors backward synchronised and reset counters. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ #define OnRevSyncEx(_ports, _pwr, _turnpct, _reset) __OnRevSyncEx(_ports, _pwr, _turnpct, _reset) /** * Run motors forward synchronised and reset counters with PID factors. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnFwdSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) __OnFwdSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) /** * Run motors backward synchronised and reset counters with PID factors. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnRevSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) __OnRevSyncExPID(_ports, _pwr, _turnpct, _reset, _p, _i, _d) /** * Run motors forward synchronised. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. */ #define OnFwdSync(_ports, _pwr, _turnpct) OnFwdSyncEx(_ports, _pwr, _turnpct, RESET_BLOCKANDTACHO) /** * Run motors backward synchronised. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. */ #define OnRevSync(_ports, _pwr, _turnpct) OnRevSyncEx(_ports, _pwr, _turnpct, RESET_BLOCKANDTACHO) /** * Run motors forward synchronised with PID factors. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnFwdSyncPID(_ports, _pwr, _turnpct, _p, _i, _d) OnFwdSyncExPID(_ports, _pwr, _turnpct, RESET_BLOCKANDTACHO, _p, _i, _d) /** * Run motors backward synchronised with PID factors. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define OnRevSyncPID(_ports, _pwr, _turnpct, _p, _i, _d) OnRevSyncExPID(_ports, _pwr, _turnpct, RESET_BLOCKANDTACHO, _p, _i, _d) /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _angle Angle limit, in degree. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _bSync Synchronise two motors. Should be set to true if a non-zero * turn percent is specified or no turning will occur. * \param _bStop Specify whether the motor(s) should brake at the end of the * rotation. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define RotateMotorExPID(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) \ __RotateMotorExPID(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, _p, _i, _d) // default PID values are 96, 32, 32 (PID_3, PID_1, PID_1) /** * Rotate motor with PID factors. * Run the specified outputs forward for the specified number of degrees. * Specify proportional, integral, and derivative factors. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _angle Angle limit, in degree. Can be negative to reverse direction. * \param _p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param _d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ #define RotateMotorPID(_ports, _pwr, _angle, _p, _i, _d) \ __RotateMotorExPID(_ports, _pwr, _angle, 0, FALSE, TRUE, _p, _i, _d) /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _angle Angle limit, in degree. Can be negative to reverse direction. * \param _turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param _bSync Synchronise two motors. Should be set to true if a non-zero * turn percent is specified or no turning will occur. * \param _bStop Specify whether the motor(s) should brake at the end of the * rotation. */ #define RotateMotorEx(_ports, _pwr, _angle, _turnpct, _bSync, _bStop) \ __RotateMotorExPID(_ports, _pwr, _angle, _turnpct, _bSync, _bStop, PID_1, PID_0, PID_3) /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * * \param _ports Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param _pwr Output power, 0 to 100. Can be negative to reverse direction. * \param _angle Angle limit, in degree. Can be negative to reverse direction. */ #define RotateMotor(_ports, _pwr, _angle) \ __RotateMotorExPID(_ports, _pwr, _angle, 0, FALSE, TRUE, PID_1, PID_0, PID_3) /** * Set motor regulation frequency. * Set the motor regulation frequency to the specified number of milliseconds. * \param _n The motor regulation frequency in milliseconds */ #define SetOutPwnFreq(_n) __setOutPwnFreq(_n) /** * Get motor regulation frequency. * Get the current motor regulation frequency. * \param _n The motor regulation frequency in milliseconds */ #define GetOutPwnFreq(_n) __GetOutPwnFreq(_n) /** * Set motor regulation time. * Set the motor regulation time to the specified number of milliseconds. * \param _n The motor regulation time in milliseconds */ #define SetOutRegulationTime(_n) __setOutRegulationTime(_n) /** * Get motor regulation time. * Get the current motor regulation time. * \param _n The motor regulation time in milliseconds */ #define GetOutRegulationTime(_n) __GetOutRegulationTime(_n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Set motor regulation options. * Set the motor regulation options. * \param _n The motor regulation options */ #define SetOutRegulationOptions(_n) __setOutRegulationOptions(_n) /** * Get motor regulation options. * Get the current motor regulation options. * \param _n The motor regulation options */ #define GetOutRegulationOptions(_n) __GetOutRegulationOptions(_n) #endif /** @} */ // end of OutputModuleFunctions group /** @} */ // end of OutputModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// INPUT MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup InputModule * @{ */ /** @defgroup InputModuleFunctions Input module functions * Functions for accessing and modifying input module features. * @{ */ /** * Set sensor type. * Set a sensor's type, which must be one of the predefined sensor type * constants. After changing the type or the mode of a sensor * port you must call \ref ResetSensor to give the firmware time to reconfigure * the sensor port. * \sa SetSensorMode() * \param _port The port to configure. See \ref NBCInputPortConstants. * \param _t The desired sensor type. See \ref NBCSensorTypeConstants. */ #define SetSensorType(_port,_t) setin _t, _port, TypeField /** * Set sensor mode. * Set a sensor's mode, which should be one of the predefined sensor mode * constants. A slope parameter for boolean conversion, if desired, may be * added to the mode. After changing the type or the mode of a sensor * port you must call \ref ResetSensor to give the firmware time to reconfigure * the sensor port. * \sa SetSensorType() * \param _port The port to configure. See \ref NBCInputPortConstants. * \param _m The desired sensor mode. See \ref NBCSensorModeConstants. */ #define SetSensorMode(_port,_m) setin _m, _port, InputModeField /** * Read sensor scaled value. * Return the processed sensor reading for a sensor on the specified port. * * \param _port The sensor port. See \ref NBCInputPortConstants. A variable whose value is * the desired sensor port may also be used. * \param _value The sensor's scaled value. */ #define ReadSensor(_port,_value) getin _value, _port, ScaledValueField /** * Clear a sensor value. * Clear the value of a sensor - only affects sensors that are configured * to measure a cumulative quantity such as rotation or a pulse count. * \param _port The port to clear. See \ref NBCInputPortConstants. */ #define ClearSensor(_port) setin 0, _port, ScaledValueField /** * Configure a touch sensor. * Configure the sensor on the specified port as a touch sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorTouch(_port) __SetSensorTouch(_port) /** * Configure a light sensor. * Configure the sensor on the specified port as an NXT light sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorLight(_port) __SetSensorLight(_port) /** * Configure a sound sensor. * Configure the sensor on the specified port as a sound sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorSound(_port) __SetSensorSound(_port) /** * Configure an I2C sensor. * Configure the sensor on the specified port as a 9V powered I2C digital sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorLowspeed(_port) __SetSensorLowspeed(_port) /** * Configure an ultrasonic sensor. * Configure the sensor on the specified port as an ultrasonic sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorUltrasonic(_port) __SetSensorLowspeed(_port) /** * Configure an EMeter sensor. * Configure the sensor on the specified port as an EMeter sensor. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorEMeter(_port) __SetSensorLowspeed(_port) /** * Configure a temperature sensor. * Configure the sensor on the specified port as a temperature sensor. Use this * to setup the temperature sensor rather than \ref SetSensorLowspeed so that * the sensor is properly configured in 12-bit conversion mode. * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorTemperature(_port) \ __SetSensorLowspeed(_port) \ __MSWriteToRegister(_port, LEGO_ADDR_TEMP, TEMP_REG_CONFIG, TEMP_RES_12BIT, __WDSC_LSStatus) #if __FIRMWARE_VERSION > 107 /** * Configure an NXT 2.0 full color sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in full color mode. Requires an NXT 2.0 compatible firmware. * \param _port The port to configure. See \ref NBCInputPortConstants. * * \warning This function requires an NXT 2.0 compatible firmware. */ #define SetSensorColorFull(_port) __SetSensorColorFull(_port) /** * Configure an NXT 2.0 red light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in red light mode. Requires an NXT 2.0 compatible firmware. * \param _port The port to configure. See \ref NBCInputPortConstants. * * \warning This function requires an NXT 2.0 compatible firmware. */ #define SetSensorColorRed(_port) __SetSensorColorRed(_port) /** * Configure an NXT 2.0 green light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in green light mode. Requires an NXT 2.0 compatible firmware. * \param _port The port to configure. See \ref NBCInputPortConstants. * * \warning This function requires an NXT 2.0 compatible firmware. */ #define SetSensorColorGreen(_port) __SetSensorColorGreen(_port) /** * Configure an NXT 2.0 blue light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in blue light mode. Requires an NXT 2.0 compatible firmware. * \param _port The port to configure. See \ref NBCInputPortConstants. * * \warning This function requires an NXT 2.0 compatible firmware. */ #define SetSensorColorBlue(_port) __SetSensorColorBlue(_port) /** * Configure an NXT 2.0 no light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in no light mode. Requires an NXT 2.0 compatible firmware. * \param _port The port to configure. See \ref NBCInputPortConstants. * * \warning This function requires an NXT 2.0 compatible firmware. */ #define SetSensorColorNone(_port) __SetSensorColorNone(_port) #endif /** * Reset the sensor port. * Sets the invalid data flag on the specified port and waits for it to * become valid again. After changing the type or the mode of a sensor * port you must call this function to give the firmware time to reconfigure * the sensor port. * \param _port The port to reset. See \ref NBCInputPortConstants. */ #define ResetSensor(_port) __ResetSensor(_port) #if __FIRMWARE_VERSION > 107 /** * Read LEGO color sensor raw values. * This function lets you read the LEGO color sensor. It returns an array * containing raw color values for red, green, blue, and none indices. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _rawVals An array containing four raw color values. See \ref InputColorIdxConstants. * \param _result The function call result. * \warning This function requires an NXT 2.0 compatible firmware. */ #define ReadSensorColorRaw(_port, _rawVals, _result) __ReadSensorColorRaw(_port, _rawVals, _result) /** * Read LEGO color sensor extra. * This function lets you read the LEGO color sensor. It returns the color value, * and three arrays containing raw, normalized, and scaled color values for * red, green, blue, and none indices. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _colorval The color value. See \ref InputColorValueConstants. * \param _rawVals An array containing four raw color values. See \ref InputColorIdxConstants. * \param _normVals An array containing four normalized color values. See \ref InputColorIdxConstants. * \param _scaledVals An array containing four scaled color values. See \ref InputColorIdxConstants. * \param _result The function call result. * \warning This function requires an NXT 2.0 compatible firmware. */ #define ReadSensorColorEx(_port, _colorval, _rawVals, _normVals, _scaledVals, _result) \ __ReadSensorColorEx(_port, _colorval, _rawVals, _normVals, _scaledVals, _result) #endif /** * Get the custom sensor zero offset. * Return the custom sensor zero offset value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _n The custom sensor zero offset. */ #define GetInCustomZeroOffset(_p, _n) __GetInCustomZeroOffset(_p, _n) /** * Read sensor boolean value. * Return the boolean value of a sensor on the specified port. Boolean * conversion is either done based on preset cutoffs, or a slope parameter * specified by calling SetSensorMode. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The sensor's boolean value. */ #define GetInSensorBoolean(_p, _n) __GetInSensorBoolean(_p, _n) /** * Read sensor digital pins direction. * Return the digital pins direction value of a sensor on the specified port. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The sensor's digital pins direction. */ #define GetInDigiPinsDirection(_p, _n) __GetInDigiPinsDirection(_p, _n) /** * Read sensor digital pins status. * Return the digital pins status value of a sensor on the specified port. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The sensor's digital pins status. */ #define GetInDigiPinsStatus(_p, _n) __GetInDigiPinsStatus(_p, _n) /** * Read sensor digital pins output level. * Return the digital pins output level value of a sensor on the specified port. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The sensor's digital pins output level. */ #define GetInDigiPinsOutputLevel(_p, _n) __GetInDigiPinsOutputLevel(_p, _n) /** * Get the custom sensor percent full scale. * Return the custom sensor percent full scale value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _n The custom sensor percent full scale. */ #define GetInCustomPercentFullScale(_p, _n) __GetInCustomPercentFullScale(_p, _n) /** * Get the custom sensor active status. * Return the custom sensor active status value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _n The custom sensor active status. */ #define GetInCustomActiveStatus(_p, _n) __GetInCustomActiveStatus(_p, _n) #if __FIRMWARE_VERSION > 107 /** * Read a LEGO color sensor calibration point value. * This function lets you directly access a specific LEGO color calibration point value. * The port, point, and color index must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _np The calibration point. See \ref InputColorCalibrationConstants. Must be a constant. * \param _nc The color index. See \ref InputColorIdxConstants. Must be a constant. * \param _n The calibration point value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorCalibration(_p, _np, _nc, _n) __GetInColorCalibration(_p, _np, _nc, _n) /** * Read a LEGO color sensor calibration limit value. * This function lets you directly access a specific LEGO color calibration limit value. * The port and the point must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _np The calibration point. See \ref InputColorCalibrationConstants. Must be a constant. * \param _n The calibration limit value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorCalLimits(_p, _np, _n) __GetInColorCalLimits(_p, _np, _n) /** * Read a LEGO color sensor AD raw value. * This function lets you directly access a specific LEGO color sensor AD raw value. Both the * port and the color index must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _nc The color index. See \ref InputColorIdxConstants. Must be a constant. * \param _n The AD raw value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorADRaw(_p, _nc, _n) __GetInColorADRaw(_p, _nc, _n) /** * Read a LEGO color sensor raw value. * This function lets you directly access a specific LEGO color sensor raw value. Both the * port and the color index must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _nc The color index. See \ref InputColorIdxConstants. Must be a constant. * \param _n The raw value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorSensorRaw(_p, _nc, _n) __GetInColorSensorRaw(_p, _nc, _n) /** * Read a LEGO color sensor scaled value. * This function lets you directly access a specific LEGO color sensor scaled value. Both the * port and the color index must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _nc The color index. See \ref InputColorIdxConstants. Must be a constant. * \param _n The scaled value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorSensorValue(_p, _nc, _n) __GetInColorSensorValue(_p, _nc, _n) /** * Read a LEGO color sensor boolean value. * This function lets you directly access a specific LEGO color sensor boolean value. Both the * port and the color index must be constants. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _nc The color index. See \ref InputColorIdxConstants. Must be a constant. * \param _n The boolean value. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorBoolean(_p, _nc, _n) __GetInColorBoolean(_p, _nc, _n) /** * Read LEGO color sensor calibration state. * This function lets you directly access the LEGO color calibration state. * The port must be a constant. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The calibration state. * \warning This function requires an NXT 2.0 compatible firmware. */ #define GetInColorCalibrationState(_p, _n) __GetInColorCalibrationState(_p, _n) #endif /** * Set custom zero offset. * Sets the zero offset value of a custom sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new zero offset value. */ #define SetInCustomZeroOffset(_p, _n) __setInCustomZeroOffset(_p, _n) /** * Set sensor boolean value. * Sets the boolean value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new boolean value. */ #define SetInSensorBoolean(_p, _n) __setInSensorBoolean(_p, _n) /** * Set digital pins direction. * Sets the digital pins direction value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new digital pins direction value. */ #define SetInDigiPinsDirection(_p, _n) __setInDigiPinsDirection(_p, _n) /** * Set digital pins status. * Sets the digital pins status value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new digital pins status value. */ #define SetInDigiPinsStatus(_p, _n) __setInDigiPinsStatus(_p, _n) /** * Set digital pins output level. * Sets the digital pins output level value of a sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new digital pins output level value. */ #define SetInDigiPinsOutputLevel(_p, _n) __setInDigiPinsOutputLevel(_p, _n) /** * Set percent full scale. * Sets the percent full scale value of a custom sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new percent full scale value. */ #define SetInCustomPercentFullScale(_p, _n) __setInCustomPercentFullScale(_p, _n) /** * Set active status. * Sets the active status value of a custom sensor. * * \param _p The sensor port. See \ref NBCInputPortConstants. Must be a constant. * \param _n The new active status value. */ #define SetInCustomActiveStatus(_p, _n) __setInCustomActiveStatus(_p, _n) /** @} */ // end of InputModuleFunctions group /** @} */ // end of InputModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// LOWSPEED MODULE /////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup LowSpeedModule * @{ */ /** @defgroup LowSpeedModuleFunctions LowSpeed module functions * Functions for accessing and modifying low speed module features. * @{ */ /** * Read ultrasonic sensor value. * Return the ultrasonic sensor distance value. Since an * ultrasonic sensor is an I2C digital sensor its value cannot be read using * the standard Sensor(n) value. * The port must be configured as a Lowspeed port before using this function. * \param _port The port to which the ultrasonic sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _value The ultrasonic sensor distance value (0..255) */ #define ReadSensorUS(_port, _value) __ReadSensorUS(_port, _value) /** * Read multiple ultrasonic sensor values. * Return eight ultrasonic sensor distance values. * \param _port The port to which the ultrasonic sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _values An array of bytes that will contain the 8 distance values * read from the ultrasonic sensor. * \param _result A status code indicating whether the read completed successfully or not. * See \ref TCommLSRead for possible Result values. */ #define ReadSensorUSEx(_port, _values, _result) __ReadSensorUSEx(_port, _values, _result) /** * Read the LEGO EMeter values. * Read all the LEGO EMeter register values. * They must all be read at once to ensure data coherency. * * \param _port The port to which the LEGO EMeter sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _vIn Input voltage * \param _aIn Input current * \param _vOut Output voltage * \param _aOut Output current * \param _joules The number of joules stored in E-Meter * \param _wIn The number of watts generated * \param _wOut The number of watts consumed * \param _result A status code indicating whether the read completed successfully or not. * See \ref TCommLSRead for possible Result values. */ #define ReadSensorEMeter(_port, _vIn, _aIn, _vOut, _aOut, _joules, _wIn, _wOut, _result) __ReadSensorEMeter(_port, _vIn, _aIn, _vOut, _aOut, _joules, _wIn, _wOut, _result) /** * Configure LEGO Temperature sensor options. * Set various LEGO Temperature sensor options. * * \param _port The port to which the LEGO EMeter sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _config The temperature sensor configuration settings. See * \ref TempI2CConstants for configuration constants that can be ORed or added * together. * \param _result A status code indicating whether the read completed successfully or not. * See \ref TCommLSRead for possible Result values. */ #define ConfigureTemperatureSensor(_port, _config, _result) __TempSendCmd(_port, _config, _result) /** * Read the LEGO Temperature sensor value. * Return the temperature sensor value in degrees celcius. Since a * temperature sensor is an I2C digital sensor its value cannot be read using * the standard Sensor(n) value. * The port must be configured as a temperature sensor port before using this * function. Use \ref SetSensorTemperature to configure the port. * \param _port The port to which the temperature sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _temp The temperature sensor value in degrees celcius. */ #define ReadSensorTemperature(_port, _temp) __ReadSensorTemperature(_port, _temp) /** * Get lowspeed status. * This method checks the status of the I2C communication on the specified * port. If the last operation on this port was a successful LowspeedWrite * call that requested response data from the device then bytesready will * be set to the number of bytes in the internal read buffer. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _bready The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref LowspeedRead or \ref LowspeedWrite while LowspeedStatus returns * \ref STAT_COMM_PENDING. * \sa LowspeedRead, LowspeedWrite, and LowspeedCheckStatus */ #define LowspeedStatus(_port, _bready, _result) __lowspeedStatus(_port, _bready, _result) /** * Check lowspeed status. * This method checks the status of the I2C communication on the specified * port. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref LowspeedRead or \ref LowspeedWrite while LowspeedCheckStatus returns * \ref STAT_COMM_PENDING. * \sa LowspeedRead, LowspeedWrite, and LowspeedStatus */ #define LowspeedCheckStatus(_port, _result) __lowspeedCheckStatus(_port, _result) /** * Get lowspeed bytes ready. * This method checks the number of bytes that are ready to be read on the * specified port. If the last operation on this port was a successful * LowspeedWrite call that requested response data from the device then the * return value will be the number of bytes in the internal read buffer. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _bready The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \sa LowspeedRead, LowspeedWrite, and LowspeedStatus */ #define LowspeedBytesReady(_port, _bready) __lowspeedBytesReady(_port, _bready) /** * Write lowspeed data. * This method starts a transaction to write the bytes contained in the array * buffer to the I2C device on the specified port. It also tells the I2C device * the number of bytes that should be included in the response. The maximum * number of bytes that can be written or read is 16. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _retlen The number of bytes that should be returned by the I2C device. * \param _buffer A byte array containing the address of the I2C device, the I2C * device register at which to write data, and up to 14 bytes of data to be * written at the specified register. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSWrite for possible Result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa LowspeedRead, LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ #define LowspeedWrite(_port, _retlen, _buffer, _result) __lowspeedWrite(_port, _retlen, _buffer, _result) /** * Read lowspeed data. * Read the specified number of bytes from the I2C device on the specified * port and store the bytes read in the byte array buffer provided. The maximum * number of bytes that can be written or read is 16. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _buflen The initial size of the output buffer. * \param _buffer A byte array that contains the data read from the internal I2C * buffer. If the return value is negative then the output buffer will be empty. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSRead for possible Result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa LowspeedWrite, LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ #define LowspeedRead(_port, _buflen, _buffer, _result) __lowspeedRead(_port, _buflen, _buffer, _result) /** * Perform an I2C write/read transaction. * This method writes the bytes contained in the input buffer (inbuf) to the * I2C device on the specified port, checks for the specified number of bytes * to be ready for reading, and then tries to read the specified number (count) * of bytes from the I2C device into the output buffer (outbuf). * * This is a higher-level wrapper around the three main I2C functions. It also * maintains a "last good read" buffer and returns values from that buffer if * the I2C communication transaction fails. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _inbuf A byte array containing the address of the I2C device, the I2C * device register at which to write data, and up to 14 bytes of data to be * written at the specified register. * \param _count The number of bytes that should be returned by the I2C device. * On output count is set to the number of bytes in outbuf. * \param _outbuf A byte array that contains the data read from the internal I2C * buffer. * \param _result Returns true or false indicating whether the I2C transaction * succeeded or failed. * \sa LowspeedRead, LowspeedWrite, LowspeedCheckStatus, LowspeedBytesReady, * and LowspeedStatus */ #define ReadI2CBytes(_port, _inbuf, _count, _outbuf, _result) __ReadI2CBytes(_port, _inbuf, _count, _outbuf, _result) /** * Read I2C device information. * Read standard I2C device information: version, vendor, and device ID. The * I2C device uses the specified address. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _i2caddr The I2C device address. * \param _info A value indicating the type of device information you are requesting. * See \ref GenericI2CConstants. * \param _strVal A string containing the requested device information. */ #define ReadI2CDeviceInfo(_port, _i2caddr, _info, _strVal) __ReadI2CDeviceInfo(_port, _i2caddr, _info, _strVal) /** * Read I2C device version. * Read standard I2C device version. The I2C device uses the specified address. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _i2caddr The I2C device address. * \param _strVal A string containing the device version. */ #define ReadI2CVersion(_port, _i2caddr, _strVal) ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_VERSION, _strVal) /** * Read I2C device vendor. * Read standard I2C device vendor. The I2C device uses the specified address. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _i2caddr The I2C device address. * \param _strVal A string containing the device vendor. */ #define ReadI2CVendorId(_port, _i2caddr, _strVal) ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_VENDOR_ID, _strVal) /** * Read I2C device identifier. * Read standard I2C device identifier. The I2C device uses the specified address. * * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _i2caddr The I2C device address. * \param _strVal A string containing the device identifier. */ #define ReadI2CDeviceId(_port, _i2caddr, _strVal) ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_DEVICE_ID, _strVal) /** * Read I2C register. * Read a single byte from an I2C device register. * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _i2caddr The I2C device address. * \param _reg The I2C device register from which to read a single byte. * \param _out The single byte read from the I2C device. * \param _result A status code indicating whether the read completed successfully or not. * See \ref TCommLSRead for possible Result values. */ #define ReadI2CRegister(_port, _i2caddr, _reg, _out, _result) __MSReadValue(_port, _i2caddr, _reg, 1, _out, _result) /** * Write I2C register. * Write a single byte to an I2C device register. * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _i2caddr The I2C device address. * \param _reg The I2C device register to which to write a single byte. * \param _val The byte to write to the I2C device. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define WriteI2CRegister(_port, _i2caddr, _reg, _val, _result) __MSWriteToRegister(_port, _i2caddr, _reg, _val, _result) /** * Send an I2C command. * Send a command to an I2C device at the standard command register: \ref I2C_REG_CMD. * The I2C device uses the specified address. * \param _port The port to which the I2C device is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param _i2caddr The I2C device address. * \param _cmd The command to send to the I2C device. * \param _result A status code indicating whether the write completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define I2CSendCommand(_port, _i2caddr, _cmd, _result) __I2CSendCmd(_port, _i2caddr, _cmd, _result) /** @defgroup LowLevelLowSpeedModuleFunctions Low level LowSpeed module functions * Low level functions for accessing low speed module features. * @{ */ /** * Get I2C input buffer data. * This method reads count bytes of data from the I2C input buffer for the * specified port and writes it to the buffer provided. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _offset A constant offset into the I2C input buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the I2C input buffer. */ #define GetLSInputBuffer(_p, _offset, _cnt, _data) __getLSInputBuffer(_p, _offset, _cnt, _data) /** * Get I2C input buffer in-pointer. * This method returns the value of the input pointer of the I2C input * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C input buffer's in-pointer value. */ #define GetLSInputBufferInPtr(_p, _n) __GetLSInputBufferInPtr(_p, _n) /** * Get I2C input buffer out-pointer. * This method returns the value of the output pointer of the I2C input * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C input buffer's out-pointer value. */ #define GetLSInputBufferOutPtr(_p, _n) __GetLSInputBufferOutPtr(_p, _n) /** * Get I2C input buffer bytes to rx. * This method returns the value of the bytes to rx field of the I2C input * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C input buffer's bytes to rx value. */ #define GetLSInputBufferBytesToRx(_p, _n) __GetLSInputBufferBytesToRx(_p, _n) /** * Get I2C output buffer data. * This method reads cnt bytes of data from the I2C output buffer for the * specified port and writes it to the buffer provided. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _offset A constant offset into the I2C output buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the I2C output buffer. */ #define GetLSOutputBuffer(_p, _offset, _cnt, _data) __getLSOutputBuffer(_p, _offset, _cnt, _data) /** * Get I2C output buffer in-pointer. * This method returns the value of the input pointer of the I2C output * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C output buffer's in-pointer value. */ #define GetLSOutputBufferInPtr(_p, _n) __GetLSOutputBufferInPtr(_p, _n) /** * Get I2C output buffer out-pointer. * This method returns the value of the output pointer of the I2C output * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C output buffer's out-pointer value. */ #define GetLSOutputBufferOutPtr(_p, _n) __GetLSOutputBufferOutPtr(_p, _n) /** * Get I2C output buffer bytes to rx. * This method returns the value of the bytes to rx field of the I2C output * buffer for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C output buffer's bytes to rx value. */ #define GetLSOutputBufferBytesToRx(_p, _n) __GetLSOutputBufferBytesToRx(_p, _n) /** * Get I2C mode. * This method returns the value of the I2C mode for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C port mode. See \ref LowSpeedModeConstants. */ #define GetLSMode(_p, _n) __GetLSMode(_p, _n) /** * Get I2C channel state. * This method returns the value of the I2C channel state for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C port channel state. See \ref LowSpeedChannelStateConstants. */ #define GetLSChannelState(_p, _n) __GetLSChannelState(_p, _n) /** * Get I2C error type. * This method returns the value of the I2C error type for the specified port. * \param _p A constant port number (S1..S4). See \ref NBCInputPortConstants. * \param _n The I2C port error type. See \ref LowSpeedErrorTypeConstants. */ #define GetLSErrorType(_p, _n) __GetLSErrorType(_p, _n) /** * Get I2C state. * This method returns the value of the I2C state. * \param _n The I2C state. See \ref LowSpeedStateConstants. */ #define GetLSState(_n) __GetLSState(_n) /** * Get I2C speed. * This method returns the value of the I2C speed. * \param _n The I2C speed. * * \warning This function is unimplemented within the firmware. */ #define GetLSSpeed(_n) __GetLSSpeed(_n) #ifdef __ENHANCED_FIRMWARE /** * Get I2C no restart on read setting. * This method returns the value of the I2C no restart on read field. * \param _n The I2C no restart on read field. See \ref LowSpeedNoRestartConstants. */ #define GetLSNoRestartOnRead(_n) __GetLSNoRestartOnRead(_n) #endif /** @} */ // end of LowLevelLowSpeedModuleFunctions group /** @} */ // end of LowSpeedModuleFunctions group /** @} */ // end of LowSpeedModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// DISPLAY MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup DisplayModule * @{ */ /** @defgroup DisplayModuleFunctions Display module functions * Functions for accessing and modifying display module features. * @{ */ /** * Clear a line on the LCD screen. * This function lets you clear a single line on the NXT LCD. * \param _line The line you want to clear. See \ref LineConstants. */ #define ClearLine(_line) __TextOutEx(0, _line, __BlankLine, 0) /** * Draw a point with drawing options. * This function lets you draw a point on the screen at x, y. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawPoint * * \param _x The x value for the point. * \param _y The y value for the point. * \param _options The optional drawing options. */ #define PointOutEx(_x,_y,_options) __PointOutEx(_x,_y,_options) /** * Draw a point. * This function lets you draw a point on the screen at x, y. * \sa TDrawPoint * * \param _x The x value for the point. * \param _y The y value for the point. */ #define PointOut(_x,_y) __PointOutEx(_x,_y,0) /** * Clear LCD screen. * This function lets you clear the NXT LCD to a blank screen. */ #define ClearScreen() __PointOutEx(200, 200, 1) /** * Draw a line with drawing options. * This function lets you draw a line on the screen from x1, y1 to x2, y2. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawLine * * \param _x1 The x value for the start of the line. * \param _y1 The y value for the start of the line. * \param _x2 The x value for the end of the line. * \param _y2 The y value for the end of the line. * \param _options The optional drawing options. */ #define LineOutEx(_x1,_y1,_x2,_y2,_options) __LineOutEx(_x1,_y1,_x2,_y2,_options) /** * Draw a line. * This function lets you draw a line on the screen from x1, y1 to x2, y2. * \sa TDrawLine * * \param _x1 The x value for the start of the line. * \param _y1 The y value for the start of the line. * \param _x2 The x value for the end of the line. * \param _y2 The y value for the end of the line. */ #define LineOut(_x1,_y1,_x2,_y2) __LineOutEx(_x1,_y1,_x2,_y2,0) /** * Draw a rectangle with drawing options. * This function lets you draw a rectangle on the screen at x, y with the * specified width and height. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawRect * * \param _x The x value for the top left corner of the rectangle. * \param _y The y value for the top left corner of the rectangle. * \param _w The width of the rectangle. * \param _h The height of the rectangle. * \param _options The optional drawing options. */ #define RectOutEx(_x,_y,_w,_h,_options) __RectOutEx(_x,_y,_w,_h,_options) /** * Draw a rectangle. * This function lets you draw a rectangle on the screen at x, y with the * specified width and height. * \sa TDrawRect * * \param _x The x value for the top left corner of the rectangle. * \param _y The y value for the top left corner of the rectangle. * \param _w The width of the rectangle. * \param _h The height of the rectangle. */ #define RectOut(_x,_y,_w,_h) __RectOutEx(_x,_y,_w,_h,0) /** * Draw a circle with drawing options. * This function lets you draw a circle on the screen with its center at the * specified x and y location, using the specified radius. Also specify * drawing options. Valid display option constants are listed in the * \ref DisplayDrawOptionConstants group. * \sa TDrawCircle * * \param _x The x value for the center of the circle. * \param _y The y value for the center of the circle. * \param _r The radius of the circle. * \param _options The optional drawing options. */ #define CircleOutEx(_x,_y,_r,_options) __CircleOutEx(_x,_y,_r,_options) /** * Draw a circle. * This function lets you draw a circle on the screen with its center at the * specified x and y location, using the specified radius. * \sa TDrawCircle * * \param _x The x value for the center of the circle. * \param _y The y value for the center of the circle. * \param _r The radius of the circle. */ #define CircleOut(_x,_y,_r) __CircleOutEx(_x,_y,_r,0) /** * Draw a number with drawing options. * Draw a numeric value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawText * * \param _x The x value for the start of the number output. * \param _y The text line number for the number output. * \param _num The value to output to the LCD screen. Any numeric type is supported. * \param _options The optional drawing options. */ #define NumOutEx(_x,_y,_num,_options) __NumOutEx(_x,_y,_num,_options) /** * Draw a number. * Draw a numeric value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * \sa TDrawText * * \param _x The x value for the start of the number output. * \param _y The text line number for the number output. * \param _num The value to output to the LCD screen. Any numeric type is supported. */ #define NumOut(_x,_y,_num) __NumOutEx(_x,_y,_num,0) /** * Draw text. * Draw a text value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawText * * \param _x The x value for the start of the text output. * \param _y The text line number for the text output. * \param _txt The text to output to the LCD screen. * \param _options The optional drawing options. */ #define TextOutEx(_x,_y,_txt,_options) __TextOutEx(_x,_y,_txt,_options) /** * Draw text. * Draw a text value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * \sa TDrawText * * \param _x The x value for the start of the text output. * \param _y The text line number for the text output. * \param _txt The text to output to the LCD screen. */ #define TextOut(_x,_y,_txt) __TextOutEx(_x,_y,_txt,0) /** * Draw a graphic image with parameters and drawing options. * Draw a graphic image file on the screen at the specified x and y location using * an array of parameters. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa TDrawGraphic * * \param _x The x value for the position of the graphic image. * \param _y The y value for the position of the graphic image. * \param _file The filename of the RIC graphic image. * \param _vars The byte array of parameters. * \param _options The drawing options. */ #define GraphicOutEx(_x,_y,_file,_vars,_options) __GraphicOutEx(_x,_y,_file,_vars,_options) /** * Draw a graphic image. * Draw a graphic image file on the screen at the specified x and y location. * If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa TDrawGraphic * * \param _x The x value for the position of the graphic image. * \param _y The y value for the position of the graphic image. * \param _file The filename of the RIC graphic image. */ #define GraphicOut(_x,_y,_file) __GraphicOutEx(_x,_y,_file,__GraphicOutEmptyVars,0) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Draw a graphic image from byte array with parameters and drawing options. * Draw a graphic image byte array on the screen at the specified x and y * location using an array of parameters and drawing options. * Valid display option constants are listed in the * \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa TDrawGraphicArray * * \param _x The x value for the position of the graphic image. * \param _y The y value for the position of the graphic image. * \param _data The byte array of the RIC graphic image. * \param _vars The byte array of parameters. * \param _options The drawing options. */ #define GraphicArrayOutEx(_x,_y,_data,_vars,_options) __GraphicArrayOutEx(_x,_y,_data,_vars,_options) /** * Draw a graphic image from byte array. * Draw a graphic image byte array on the screen at the specified x and y * location. If the file cannot be found then nothing will be drawn and no * errors will be reported. * \sa TDrawGraphicArray * * \param _x The x value for the position of the graphic image. * \param _y The y value for the position of the graphic image. * \param _data The byte array of the RIC graphic image. */ #define GraphicArrayOut(_x,_y,_data) __GraphicArrayOutEx(_x,_y,_data,__GraphicOutEmptyVars,0) /** * Draw an ellipse with drawing options. * This function lets you draw an ellipse on the screen with its center at the * specified x and y location, using the specified radii. Also specify * drawing options. Valid display option constants are listed in the * \ref DisplayDrawOptionConstants group. * \sa SysDrawEllipse, DrawEllipseType * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the center of the ellipse. * \param _y The y value for the center of the ellipse. * \param _rX The x axis radius. * \param _rY The y axis radius. * \param _options The drawing options. */ #define EllipseOutEx(_x,_y,_rX,_rY,_options) __EllipseOutEx(_x,_y,_rX,_rY,_options) /** * Draw an ellipse. * This function lets you draw an ellipse on the screen with its center at the * specified x and y location, using the specified radii. * \sa TDrawEllipse * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the center of the ellipse. * \param _y The y value for the center of the ellipse. * \param _rX The x axis radius. * \param _rY The y axis radius. */ #define EllipseOut(_x,_y,_rX,_rY) __EllipseOutEx(_x,_y,_rX,_rY,0) /** * Draw a polygon with drawing options. * This function lets you draw a polygon on the screen using an array of points. * Also specify drawing options. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa TDrawPolygon * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _points An array of \ref TLocation points that define the polygon. * \param _options The drawing options. */ #define PolyOutEx(_points,_options) __PolyOutEx(_points,_options) /** * Draw a polygon. * This function lets you draw a polygon on the screen using an array of points. * \sa TDrawPolygon * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _points An array of LocationType points that define the polygon. */ #define PolyOut(_points) __PolyOutEx(_points,0) /** * Draw text with font and drawing options. * Draw a text value on the screen at the specified x and y location using * a custom RIC font. Also specify drawing options. Valid display option * constants are listed in the \ref DisplayDrawOptionConstants group. See the * \ref DisplayFontDrawOptionConstants for options specific to the font * drawing functions. * \sa FontNumOut, TDrawFont * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the start of the text output. * \param _y The y value for the start of the text output. * \param _fnt The filename of the RIC font. * \param _txt The text to output to the LCD screen. * \param _options The drawing options. */ #define FontTextOutEx(_x,_y,_fnt,_txt,_options) __FontTextOutEx(_x,_y,_fnt,_txt,_options) /** * Draw text with font. * Draw a text value on the screen at the specified x and y location using * a custom RIC font. * \sa FontNumOut, TDrawFont * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the start of the text output. * \param _y The y value for the start of the text output. * \param _fnt The filename of the RIC font. * \param _txt The text to output to the LCD screen. */ #define FontTextOut(_x,_y,_fnt,_txt) __FontTextOutEx(_x,_y,_fnt,_txt,0) /** * Draw a number with font and drawing options. * Draw a numeric value on the screen at the specified x and y location using * a custom RIC font. Also specify drawing options. Valid display option * constants are listed in the \ref DisplayDrawOptionConstants group. See the * \ref DisplayFontDrawOptionConstants for options specific to the font * drawing functions. * \sa FontTextOut, TDrawFont * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the start of the number output. * \param _y The y value for the start of the number output. * \param _fnt The filename of the RIC font. * \param _num The value to output to the LCD screen. Any numeric type is supported. * \param _options The optional drawing options. */ #define FontNumOutEx(_x,_y,_fnt,_num,_options) __FontNumOutEx(_x,_y,_fnt,_num,_options) /** * Draw a number with font. * Draw a numeric value on the screen at the specified x and y location using * a custom RIC font. * \sa FontTextOut, TDrawFont * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _x The x value for the start of the number output. * \param _y The y value for the start of the number output. * \param _fnt The filename of the RIC font. * \param _num The value to output to the LCD screen. Any numeric type is supported. */ #define FontNumOut(_x,_y,_fnt,_num) __FontNumOutEx(_x,_y,_fnt,_num,0) #endif /** * Read the display erase mask value. * This function lets you read the current display erase mask value. * \param _n The current display erase mask value. */ #define GetDisplayEraseMask(_n) __GetDisplayEraseMask(_n) /** * Read the display update mask value. * This function lets you read the current display update mask value. * \param _n The current display update mask. */ #define GetDisplayUpdateMask(_n) __GetDisplayUpdateMask(_n) /** * Read the display font memory address. * This function lets you read the current display font memory address. * \param _n The current display font memory address. */ #define GetDisplayFont(_n) __GetDisplayFont(_n) /** * Read the display memory address. * This function lets you read the current display memory address. * \param _n The current display memory address. */ #define GetDisplayDisplay(_n) __GetDisplayDisplay(_n) /** * Read the display flags. * This function lets you read the current display flags. * Valid flag values are listed in the \ref DisplayFlagsGroup group. * \param _n The current display flags. */ #define GetDisplayFlags(_n) __GetDisplayFlags(_n) /** * Read the display text lines center flags. * This function lets you read the current display text lines center flags. * \param _n The current display text lines center flags. */ #define GetDisplayTextLinesCenterFlags(_n) __GetDisplayTextLinesCenterFlags(_n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Read the display contrast setting. * This function lets you read the current display contrast setting. * \param _n The current display contrast (byte). * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define GetDisplayContrast(_n) __GetDisplayContrast(_n) #endif /** * Read pixel data from the normal display buffer. * Read "cnt" bytes from the normal display memory into the data array. Start * reading from the specified x, line coordinate. Each byte of data read from * screen memory is a vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param _x The desired x position from which to read pixel data. * \param _line The desired line from which to read pixel data. * \param _cnt The number of bytes of pixel data to read. * \param _data The array of bytes into which pixel data is read. */ #define GetDisplayNormal(_x, _line, _cnt, _data) __getDisplayNormal(_x, _line, _cnt, _data) /** * Read pixel data from the popup display buffer. * Read "cnt" bytes from the popup display memory into the data array. Start * reading from the specified x, line coordinate. Each byte of data read from * screen memory is a vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param _x The desired x position from which to read pixel data. * \param _line The desired line from which to read pixel data. * \param _cnt The number of bytes of pixel data to read. * \param _data The array of bytes into which pixel data is read. */ #define GetDisplayPopup(_x, _line, _cnt, _data) __getDisplayPopup(_x, _line, _cnt, _data) /** * Set the display font memory address. * This function lets you set the current display font memory address. * * \param _n The new display font memory address. */ #define SetDisplayFont(_n) __setDisplayFont(_n) /** * Set the display memory address. * This function lets you set the current display memory address. * * \param _n The new display memory address. */ #define SetDisplayDisplay(_n) __setDisplayDisplay(_n) /** * Set the display erase mask. * This function lets you set the current display erase mask. * * \param _n The new display erase mask. */ #define SetDisplayEraseMask(_n) __setDisplayEraseMask(_n) /** * Set the display flags. * This function lets you set the current display flags. * * \param _n The new display flags. See \ref DisplayFlagsGroup. */ #define SetDisplayFlags(_n) __setDisplayFlags(_n) /** * Set the display text lines center flags. * This function lets you set the current display text lines center flags. * * \param _n The new display text lines center flags. */ #define SetDisplayTextLinesCenterFlags(_n) __setDisplayTextLinesCenterFlags(_n) /** * Set the display update mask. * This function lets you set the current display update mask. * * \param _n The new display update mask. */ #define SetDisplayUpdateMask(_n) __setDisplayUpdateMask(_n) #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Set the display contrast. * This function lets you set the display contrast setting. * * \param _n The desired display contrast. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define SetDisplayContrast(_n) __setDisplayContrast(_n) #endif /** * Write pixel data to the normal display buffer. * Write "cnt" bytes to the normal display memory from the data array. Start * writing at the specified x, line coordinate. Each byte of data is a * vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param _x The desired x position where you wish to write pixel data. * \param _line The desired line where you wish to write pixel data. * \param _cnt The number of bytes of pixel data to write. * \param _data The array of bytes from which pixel data is read. */ #define SetDisplayNormal(_x, _line, _cnt, _data) __setDisplayNormal(_x, _line, _cnt, _data) /** * Write pixel data to the popup display buffer. * Write "cnt" bytes to the popup display memory from the data array. Start * writing at the specified x, line coordinate. Each byte of data is a * vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param _x The desired x position where you wish to write pixel data. * \param _line The desired line where you wish to write pixel data. * \param _cnt The number of bytes of pixel data to write. * \param _data The array of bytes from which pixel data is read. */ #define SetDisplayPopup(_x, _line, _cnt, _data) __setDisplayPopup(_x, _line, _cnt, _data) /** @} */ // end of DisplayModuleFunctions group /** @} */ // end of DisplayModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// SOUND MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup SoundModule * @{ */ /** @defgroup SoundModuleFunctions Sound module functions * Functions for accessing and modifying sound module features. * @{ */ /** * Play a tone with extra options. * Play a single tone of the specified frequency, duration, and volume. The * frequency is in Hz (see the \ref ToneConstants group). The duration is in * 1000ths of a second (see the \ref TimeConstants group). Volume should be a * number from 0 (silent) to 4 (loudest). Play the tone repeatedly if loop is * true. * * \param _freq The desired tone frequency, in Hz. * \param _dur The desired tone duration, in ms. * \param _vol The desired tone volume. * \param _loop A boolean flag indicating whether to play the tone repeatedly. */ #define PlayToneEx(_freq,_dur,_vol,_loop) __PlayToneEx(_freq,_dur,_vol,_loop) /** * Play a tone. * Play a single tone of the specified frequency and duration. The frequency is * in Hz (see the \ref ToneConstants group). The duration is in 1000ths of a * second (see the \ref TimeConstants group). The tone is played at the loudest * sound level supported by the firmware and it is not looped. * * \param _freq The desired tone frequency, in Hz. * \param _dur The desired tone duration, in ms. */ #define PlayTone(_freq,_dur) __PlayToneEx(_freq,_dur,4,0) /** * Play a file. * Play the specified file. The filename may be any valid string expression. * The sound file can either be an RSO file containing PCM or compressed ADPCM * samples or it can be an NXT melody (RMD) file containing frequency and * duration values. * * \param _file The name of the sound or melody file to play. */ #define PlayFile(_file) __PlayFileEx(_file,4,0) /** * Play a file with extra options. * Play the specified file. The filename may be any valid string expression. * Volume should be a number from 0 (silent) to 4 (loudest). Play the file * repeatedly if loop is true. * The sound file can either be an RSO file containing PCM or compressed ADPCM * samples or it can be an NXT melody (RMD) file containing frequency and * duration values. * * \param _file The name of the sound or melody file to play. * \param _vol The desired tone volume. * \param _loop A boolean flag indicating whether to play the file repeatedly. */ #define PlayFileEx(_file,_vol,_loop) __PlayFileEx(_file,_vol,_loop) /** * Get sound module state and flags. * Return the current sound module state and flags. * See the \ref SoundStateConstants group. * * \sa SetSoundState * \param _state The current sound module state. * \param _flags The current sound module flags. */ #define GetSoundState(_state, _flags) __GetSoundState(_state, _flags) /** * Set sound module state and flags. * Set the sound module state and flags. * See the \ref SoundStateConstants group. * * \sa GetSoundState * \param _state The sound module state. * \param _flags The sound module flags. * \param _result The function call result. */ #define SetSoundState(_state, _flags, _result) __setSoundState(_state, _flags, _result) /** * Get sound frequency. * Return the current sound frequency. * * \sa SetSoundFrequency * \param _n The current sound frequency. */ #define GetSoundFrequency(_n) __GetSoundFrequency(_n) /** * Get sound duration. * Return the current sound duration. * * \sa SetSoundDuration * \param _n The current sound duration. */ #define GetSoundDuration(_n) __GetSoundDuration(_n) /** * Get sample rate. * Return the current sound sample rate. * * \sa SetSoundSampleRate * \param _n The current sound sample rate. */ #define GetSoundSampleRate(_n) __GetSoundSampleRate(_n) /** * Get sound mode. * Return the current sound mode. See the \ref SoundModeConstants group. * * \sa SetSoundMode * \param _n The current sound mode. */ #define GetSoundMode(_n) __GetSoundMode(_n) /** * Get volume. * Return the current sound volume. * * \sa SetSoundVolume * \param _n The current sound volume. */ #define GetSoundVolume(_n) __GetSoundVolume(_n) /** * Set sound duration. * Set the sound duration. * * \sa GetSoundDuration * \param _n The new sound duration */ #define SetSoundDuration(_n) __setSoundDuration(_n) /** * Set sound module flags. * Set the sound module flags. See the \ref SoundFlagsConstants group. * * \param _n The new sound module flags */ #define SetSoundFlags(_n) __setSoundFlags(_n) /** * Set sound frequency. * Set the sound frequency. * * \sa GetSoundFrequency * \param _n The new sound frequency */ #define SetSoundFrequency(_n) __setSoundFrequency(_n) /** * Set sound mode. * Set the sound mode. See the \ref SoundModeConstants group. * * \sa GetSoundMode * \param _n The new sound mode */ #define SetSoundMode(_n) __setSoundMode(_n) /** * Set sound module state. * Set the sound module state. See the \ref SoundStateConstants group. * * \sa GetSoundState * \param _n The new sound state */ #define SetSoundModuleState(_n) __setSoundModuleState(_n) /** * Set sample rate. * Set the sound sample rate. * * \sa GetSoundSampleRate * \param _n The new sample rate */ #define SetSoundSampleRate(_n) __setSoundSampleRate(_n) /** * Set sound volume. * Set the sound volume. * * \sa GetSoundVolume * \param _n The new volume */ #define SetSoundVolume(_n) __setSoundVolume(_n) /** @} */ // end of SoundModuleFunctions group /** @} */ // end of SoundModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// COMMAND MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup CommandModule * @{ */ /** @defgroup CommandModuleFunctions Command module functions * Functions for accessing and modifying Command module features. * @{ */ /** * Set IOMap bytes by name. * Modify one or more bytes of data in an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to start writing, the number of bytes to * write at that location, and a byte array containing the new data. * \param _modName The module name of the IOMap to modify. See \ref ModuleNameConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the data should be written * \param _cnt The number of bytes to write at the specified IOMap * offset. * \param _arrIn The byte array containing the data to write to the IOMap */ #define SetIOMapBytes(_modName, _offset, _cnt, _arrIn) __SetIOMapBytes(_modName, _offset, _cnt, _arrIn) /** * Set IOMap value by name. * Set one of the fields of an IOMap structure to a new value. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to write the value along with a variable * containing the new value. * \param _modName The module name of the IOMap to modify. See \ref ModuleNameConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the new value should be written * \param _n A variable containing the new value to write to the IOMap */ #define SetIOMapValue(_modName, _offset, _n) __SetIOMapValue(_modName, _offset, _n) #ifdef __ENHANCED_FIRMWARE /** * Set IOMap bytes by ID. * Modify one or more bytes of data in an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to start writing, the number of bytes to * write at that location, and a byte array containing the new data. * \param _modID The module ID of the IOMap to modify. See \ref ModuleIDConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the data should be written. * \param _cnt The number of bytes to write at the specified IOMap * offset. * \param _arrIn The byte array containing the data to write to the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ #define SetIOMapBytesByID(_modID, _offset, _cnt, _arrIn) __SetIOMapBytesByID(_modID, _offset, _cnt, _arrIn) /** * Set IOMap value by ID. * Set one of the fields of an IOMap structure to a new value. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to write the value along with a variable * containing the new value. * \param _modID The module ID of the IOMap to modify. See \ref ModuleIDConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the new value should be written. * \param _n A variable containing the new value to write to the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ #define SetIOMapValueByID(_modID, _offset, _n) __SetIOMapValueByID(_modID, _offset, _n) /** * Set Command module IOMap value. * Set one of the fields of the Command module IOMap structure to a new value. * You provide the offset into the Command module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Command * module IOMap structure where the new value should be written. See \ref CommandIOMAP. * \param _n A variable containing the new value to write to the Command * module IOMap. */ #define SetCommandModuleValue(_offset, _n) SetIOMapValueByID(CommandModuleID, _offset, _n) /** * Set IOCtrl module IOMap value. * Set one of the fields of the IOCtrl module IOMap structure to a new value. * You provide the offset into the IOCtrl module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the IOCtrl * module IOMap structure where the new value should be written. See \ref IOCtrlIOMAP. * \param _n A variable containing the new value to write to the IOCtrl * module IOMap. */ #define SetIOCtrlModuleValue(_offset, _n) SetIOMapValueByID(IOCtrlModuleID, _offset, _n) /** * Set Loader module IOMap value. * Set one of the fields of the Loader module IOMap structure to a new value. * You provide the offset into the Loader module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Loader * module IOMap structure where the new value should be written. See \ref LoaderIOMAP. * \param _n A variable containing the new value to write to the Loader * module IOMap. */ #define SetLoaderModuleValue(_offset, _n) SetIOMapValueByID(LoaderModuleID, _offset, _n) /** * Set Ui module IOMap value. * Set one of the fields of the Ui module IOMap structure to a new value. * You provide the offset into the Ui module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Ui * module IOMap structure where the new value should be written. See \ref UiIOMAP. * \param _n A variable containing the new value to write to the Ui * module IOMap. */ #define SetUIModuleValue(_offset, _n) SetIOMapValueByID(UIModuleID, _offset, _n) /** * Set Sound module IOMap value. * Set one of the fields of the Sound module IOMap structure to a new value. * You provide the offset into the Sound module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Sound * module IOMap structure where the new value should be written. See \ref SoundIOMAP. * \param _n A variable containing the new value to write to the Sound * module IOMap. */ #define SetSoundModuleValue(_offset, _n) SetIOMapValueByID(SoundModuleID, _offset, _n) /** * Set Button module IOMap value. * Set one of the fields of the Button module IOMap structure to a new value. * You provide the offset into the Button module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Button * module IOMap structure where the new value should be written. See \ref ButtonIOMAP. * \param _n A variable containing the new value to write to the Button * module IOMap. */ #define SetButtonModuleValue(_offset, _n) SetIOMapValueByID(ButtonModuleID, _offset, _n) /** * Set Input module IOMap value. * Set one of the fields of the Input module IOMap structure to a new value. * You provide the offset into the Input module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Input * module IOMap structure where the new value should be written. See \ref InputIOMAP. * \param _n A variable containing the new value to write to the Input * module IOMap. */ #define SetInputModuleValue(_offset, _n) SetIOMapValueByID(InputModuleID, _offset, _n) /** * Set Output module IOMap value. * Set one of the fields of the Output module IOMap structure to a new value. * You provide the offset into the Output module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Output * module IOMap structure where the new value should be written. See \ref OutputIOMAP. * \param _n A variable containing the new value to write to the Output * module IOMap. */ #define SetOutputModuleValue(_offset, _n) SetIOMapValueByID(OutputModuleID, _offset, _n) /** * Set Lowspeed module IOMap value. * Set one of the fields of the Lowspeed module IOMap structure to a new value. * You provide the offset into the Lowspeed module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the new value should be written. See \ref LowSpeedIOMAP. * \param _n A variable containing the new value to write to the Lowspeed * module IOMap. */ #define SetLowSpeedModuleValue(_offset, _n) SetIOMapValueByID(LowSpeedModuleID, _offset, _n) /** * Set Display module IOMap value. * Set one of the fields of the Display module IOMap structure to a new value. * You provide the offset into the Display module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Display * module IOMap structure where the new value should be written. See \ref DisplayIOMAP. * \param _n A variable containing the new value to write to the Display * module IOMap. */ #define SetDisplayModuleValue(_offset, _n) SetIOMapValueByID(DisplayModuleID, _offset, _n) /** * Set Comm module IOMap value. * Set one of the fields of the Comm module IOMap structure to a new value. * You provide the offset into the Comm module IOMap structure where you * want to write the value along with a variable containing the new value. * \param _offset The number of bytes offset from the start of the Comm * module IOMap structure where the new value should be written. See \ref CommIOMAP. * \param _n A variable containing the new value to write to the Comm * module IOMap. */ #define SetCommModuleValue(_offset, _n) SetIOMapValueByID(CommModuleID, _offset, _n) /** * Set Command module IOMap bytes. * Modify one or more bytes of data in the Command module IOMap structure. You * provide the offset into the Command module IOMap structure where you want * to start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param _offset The number of bytes offset from the start of the Command module * IOMap structure where the data should be written. See \ref CommandIOMAP. * \param _cnt The number of bytes to write at the specified Command module * IOMap offset. * \param _arrIn The byte array containing the data to write to the Command * module IOMap. */ #define SetCommandModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(CommandModuleID, _offset, _cnt, _arrIn) /** * Set Lowspeed module IOMap bytes. * Modify one or more bytes of data in the Lowspeed module IOMap structure. You * provide the offset into the Lowspeed module IOMap structure where you want * to start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param _offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the data should be written. See \ref LowSpeedIOMAP. * \param _cnt The number of bytes to write at the specified Lowspeed module * IOMap offset. * \param _arrIn The byte array containing the data to write to the Lowspeed * module IOMap. */ #define SetLowSpeedModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(LowSpeedModuleID, _offset, _cnt, _arrIn) /** * Set Display module IOMap bytes. * Modify one or more bytes of data in the Display module IOMap structure. You * provide the offset into the Display module IOMap structure where you want to * start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param _offset The number of bytes offset from the start of the Display module * IOMap structure where the data should be written. See \ref DisplayIOMAP. * \param _cnt The number of bytes to write at the specified Display module * IOMap offset. * \param _arrIn The byte array containing the data to write to the Display * module IOMap. */ #define SetDisplayModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(DisplayModuleID, _offset, _cnt, _arrIn) /** * Set Comm module IOMap bytes. * Modify one or more bytes of data in an IOMap structure. You provide the * offset into the Comm module IOMap structure where you want to start writing, * the number of bytes to write at that location, and a byte array containing * the new data. * \param _offset The number of bytes offset from the start of the Comm module * IOMap structure where the data should be written. See \ref CommIOMAP. * \param _cnt The number of bytes to write at the specified Comm module IOMap * offset. * \param _arrIn The byte array containing the data to write to the Comm module * IOMap. */ #define SetCommModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(CommModuleID, _offset, _cnt, _arrIn) #else #define SetCommandModuleValue(_offset, _n) SetIOMapValue(CommandModuleName, _offset, _n) #define SetIOCtrlModuleValue(_offset, _n) SetIOMapValue(IOCtrlModuleName, _offset, _n) #define SetLoaderModuleValue(_offset, _n) SetIOMapValue(LoaderModuleName, _offset, _n) #define SetUIModuleValue(_offset, _n) SetIOMapValue(UIModuleName, _offset, _n) #define SetSoundModuleValue(_offset, _n) SetIOMapValue(SoundModuleName, _offset, _n) #define SetButtonModuleValue(_offset, _n) SetIOMapValue(ButtonModuleName, _offset, _n) #define SetInputModuleValue(_offset, _n) SetIOMapValue(InputModuleName, _offset, _n) #define SetOutputModuleValue(_offset, _n) SetIOMapValue(OutputModuleName, _offset, _n) #define SetLowSpeedModuleValue(_offset, _n) SetIOMapValue(LowSpeedModuleName, _offset, _n) #define SetDisplayModuleValue(_offset, _n) SetIOMapValue(DisplayModuleName, _offset, _n) #define SetCommModuleValue(_offset, _n) SetIOMapValue(CommModuleName, _offset, _n) #define SetCommandModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(CommandModuleName, _offset, _cnt, _arrIn) #define SetLowSpeedModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(LowSpeedModuleName, _offset, _cnt, _arrIn) #define SetDisplayModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(DisplayModuleName, _offset, _cnt, _arrIn) #define SetCommModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(CommModuleName, _offset, _cnt, _arrIn) #endif /** * Get IOMap bytes by name. * Read one or more bytes of data from an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to start reading, the number of bytes to * read from that location, and a byte array where the data will be stored. * \param _modName The module name of the IOMap. See \ref ModuleNameConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the data should be read * \param _cnt The number of bytes to read from the specified IOMap * offset. * \param _arrOut A byte array that will contain the data read from the IOMap */ #define GetIOMapBytes(_modName, _offset, _cnt, _arrOut) __getIOMapBytes(_modName, _offset, _cnt, _arrOut) /** * Get IOMap value by name. * Read a value from an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to read the value along with a variable * that will contain the IOMap value. * \param _modName The module name of the IOMap. See \ref ModuleNameConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read * \param _n A variable that will contain the value read from the IOMap */ #define GetIOMapValue(_modName, _offset, _n) __getIOMapValue(_modName, _offset, _n) #ifdef __ENHANCED_FIRMWARE /** * Get IOMap bytes by ID. * Read one or more bytes of data from an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to start reading, the number of bytes to * read from that location, and a byte array where the data will be stored. * \param _modID The module ID of the IOMap. See \ref ModuleIDConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the data should be read. * \param _cnt The number of bytes to read from the specified IOMap * offset. * \param _arrOut A byte array that will contain the data read from the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ #define GetIOMapBytesByID(_modID, _offset, _cnt, _arrOut) __getIOMapBytesByID(_modID, _offset, _cnt, _arrOut) /** * Get IOMap value by ID. * Read a value from an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to read the value along with a variable * that will contain the IOMap value. * \param _modID The module ID of the IOMap. See \ref ModuleIDConstants. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. * \param _n A variable that will contain the value read from the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ #define GetIOMapValueByID(_modID, _offset, _n) __getIOMapValueByID(_modID, _offset, _n) /** * Get Command module IOMap value. * Read a value from the Command module IOMap structure. You provide the * offset into the Command module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref CommandIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetCommandModuleValue(_offset, _n) GetIOMapValueByID(CommandModuleID, _offset, _n) /** * Get Loader module IOMap value. * Read a value from the Loader module IOMap structure. You provide the * offset into the Loader module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref LoaderIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetLoaderModuleValue(_offset, _n) GetIOMapValueByID(LoaderModuleID, _offset, _n) /** * Get Sound module IOMap value. * Read a value from the Sound module IOMap structure. You provide the * offset into the Sound module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref SoundIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetSoundModuleValue(_offset, _n) GetIOMapValueByID(SoundModuleID, _offset, _n) /** * Get Button module IOMap value. * Read a value from the Button module IOMap structure. You provide the * offset into the Button module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref ButtonIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetButtonModuleValue(_offset, _n) GetIOMapValueByID(ButtonModuleID, _offset, _n) /** * Get Ui module IOMap value. * Read a value from the Ui module IOMap structure. You provide the * offset into the Ui module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref UiIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetUIModuleValue(_offset, _n) GetIOMapValueByID(UIModuleID, _offset, _n) /** * Get Input module IOMap value. * Read a value from the Input module IOMap structure. You provide the * offset into the Input module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref InputIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetInputModuleValue(_offset, _n) GetIOMapValueByID(InputModuleID, _offset, _n) /** * Get Output module IOMap value. * Read a value from the Output module IOMap structure. You provide the * offset into the Output module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref OutputIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetOutputModuleValue(_offset, _n) GetIOMapValueByID(OutputModuleID, _offset, _n) /** * Get LowSpeed module IOMap value. * Read a value from the LowSpeed module IOMap structure. You provide the * offset into the Command module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref LowSpeedIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetLowSpeedModuleValue(_offset, _n) GetIOMapValueByID(LowSpeedModuleID, _offset, _n) /** * Get Display module IOMap value. * Read a value from the Display module IOMap structure. You provide the * offset into the Display module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref DisplayIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetDisplayModuleValue(_offset, _n) GetIOMapValueByID(DisplayModuleID, _offset, _n) /** * Get Comm module IOMap value. * Read a value from the Comm module IOMap structure. You provide the * offset into the Comm module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param _offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref CommIOMAP. * \param _n A variable that will contain the value read from the IOMap. */ #define GetCommModuleValue(_offset, _n) GetIOMapValueByID(CommModuleID, _offset, _n) #else #define GetCommandModuleValue(_offset, _n) GetIOMapValue(CommandModuleName, _offset, _n) #define GetLoaderModuleValue(_offset, _n) GetIOMapValue(LoaderModuleName, _offset, _n) #define GetSoundModuleValue(_offset, _n) GetIOMapValue(SoundModuleName, _offset, _n) #define GetButtonModuleValue(_offset, _n) GetIOMapValue(ButtonModuleName, _offset, _n) #define GetUIModuleValue(_offset, _n) GetIOMapValue(UIModuleName, _offset, _n) #define GetInputModuleValue(_offset, _n) GetIOMapValue(InputModuleName, _offset, _n) #define GetOutputModuleValue(_offset, _n) GetIOMapValue(OutputModuleName, _offset, _n) #define GetLowSpeedModuleValue(_offset, _n) GetIOMapValue(LowSpeedModuleName, _offset, _n) #define GetDisplayModuleValue(_offset, _n) GetIOMapValue(DisplayModuleName, _offset, _n) #define GetCommModuleValue(_offset, _n) GetIOMapValue(CommModuleName, _offset, _n) #endif /** * Get Lowspeed module IOMap bytes. * Read one or more bytes of data from Lowspeed module IOMap structure. * You provide the offset into the Lowspeed module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param _offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the data should be read. See \ref LowSpeedIOMAP. * \param _cnt The number of bytes to read from the specified Lowspeed module * IOMap offset. * \param _arrOut A byte array that will contain the data read from the Lowspeed * module IOMap. */ #define GetLowSpeedModuleBytes(_offset, _cnt, _arrOut) __getLowSpeedModuleBytes(_offset, _cnt, _arrOut) /** * Get Display module IOMap bytes. * Read one or more bytes of data from Display module IOMap structure. * You provide the offset into the Display module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param _offset The number of bytes offset from the start of the Display * module IOMap structure where the data should be read. See \ref DisplayIOMAP. * \param _cnt The number of bytes to read from the specified Display module * IOMap offset. * \param _arrOut A byte array that will contain the data read from the Display * module IOMap. */ #define GetDisplayModuleBytes(_offset, _cnt, _arrOut) __getDisplayModuleBytes(_offset, _cnt, _arrOut) /** * Get Comm module IOMap bytes. * Read one or more bytes of data from Comm module IOMap structure. * You provide the offset into the Comm module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param _offset The number of bytes offset from the start of the Comm module * IOMap structure where the data should be read. See \ref CommIOMAP. * \param _cnt The number of bytes to read from the specified Comm module * IOMap offset. * \param _arrOut A byte array that will contain the data read from the Comm * module IOMap. */ #define GetCommModuleBytes(_offset, _cnt, _arrOut) __getCommModuleBytes(_offset, _cnt, _arrOut) /** * Get Command module IOMap bytes. * Read one or more bytes of data from Command module IOMap structure. * You provide the offset into the Command module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param _offset The number of bytes offset from the start of the Command module * IOMap structure where the data should be read. See \ref CommandIOMAP. * \param _cnt The number of bytes to read from the specified Command module * IOMap offset. * \param _arrOut A byte array that will contain the data read from the Command * module IOMap. */ #define GetCommandModuleBytes(_offset, _cnt, _arrOut) __getCommandModuleBytes(_offset, _cnt, _arrOut) /** * Reset the sleep timer. * This function lets you reset the sleep timer. * */ #define ResetSleepTimer syscall KeepAlive, __KeepAliveArgs /** * Get the first tick. * Return an unsigned 32-bit value, which is the system timing value * (called a "tick") in milliseconds at the time that the program began * running. * * \param _value The tick count at the start of program execution. */ #define GetFirstTick(_value) __GetFirstTick(_value) /** * Wait some milliseconds. * Make a task sleep for specified amount of time (in 1000ths of a second). * * \param _n The number of milliseconds to sleep. */ #define Wait(_n) waitv _n #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Read memory information. * Read the current pool size and dataspace size. Optionally compact the * dataspace before returning the information. Running programs have a maximum * of 32k bytes of memory available. The amount of free RAM can be calculated * by subtracting the value returned by this function from \ref POOL_MAX_SIZE. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _Compact A boolean value indicating whether to compact the dataspace or not. * \param _PoolSize The current pool size. * \param _DataspaceSize The current dataspace size. * \param _Result The function call result. It will be \ref NO_ERR if the compact * operation is not performed. Otherwise it will be the result of the compact * operation. */ #define GetMemoryInfo(_Compact,_PoolSize,_DataspaceSize,_Result) __GetMemoryInfo(_Compact,_PoolSize,_DataspaceSize,_Result) /** * Read last response information. * Read the last direct or system command response packet received by the NXT. * Optionally clear the response after retrieving the information. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+. * * \param _Clear A boolean value indicating whether to clear the response or not. * \param _Length The response packet length. * \param _Command The original command byte. * \param _Buffer The response packet buffer. * \param _Result The response status code. */ #define GetLastResponseInfo(_Clear,_Length,_Command,_Buffer,_Result) __GetLastResponseInfo(_Clear,_Length,_Command,_Buffer,_Result) #endif /** @} */ // end of CommandModuleFunctions group /** @} */ // end of CommandModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// BUTTON MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup ButtonModule * @{ */ /** @defgroup ButtonModuleFunctions Button module functions * Functions for accessing and modifying Button module features. * @{ */ /** * Read button information. * Read the specified button. Set the pressed and count parameters with the * current state of the button. Optionally reset the press count after * reading it. * * \param _idx The button to check. See \ref ButtonNameConstants. * \param _reset Whether or not to reset the press counter. * \param _pressed The button pressed state. * \param _count The button press count. * \param _result The function call result. */ #define ReadButtonEx(_idx, _reset, _pressed, _count, _result) __ReadButtonEx(_idx, _reset, _pressed, _count, _result) /** * Get button press count. * Return the press count of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button press count. */ #define GetButtonPressCount(_b, _n) __GetButtonPressCount(_b, _n) /** * Get button long press count. * Return the long press count of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button long press count. */ #define GetButtonLongPressCount(_b, _n) __GetButtonLongPressCount(_b, _n) /** * Get button short release count. * Return the short release count of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button short release count. */ #define GetButtonShortReleaseCount(_b, _n) __GetButtonShortReleaseCount(_b, _n) /** * Get button long release count. * Return the long release count of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button long release count. */ #define GetButtonLongReleaseCount(_b, _n) __GetButtonLongReleaseCount(_b, _n) /** * Get button release count. * Return the release count of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button release count. */ #define GetButtonReleaseCount(_b, _n) __GetButtonReleaseCount(_b, _n) /** * Get button state. * Return the state of the specified button. See \ref ButtonStateConstants. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The button state. */ #define GetButtonState(_b, _n) __GetButtonState(_b, _n) /** * Set button press count. * Set the press count of the specified button. * * \param _b The button number. See \ref ButtonNameConstants. * \param _n The new press count value. */ #define SetButtonPressCount(_b, _n) __setButtonPressCount(_b, _n) /** * Set button long press count. * Set the long press count of the specified button. * * \param _b The button number. See \ref ButtonNameConstants. * \param _n The new long press count value. */ #define SetButtonLongPressCount(_b, _n) __setButtonLongPressCount(_b, _n) /** * Set button short release count. * Set the short release count of the specified button. * * \param _b The button number. See \ref ButtonNameConstants. * \param _n The new short release count value. */ #define SetButtonShortReleaseCount(_b, _n) __setButtonShortReleaseCount(_b, _n) /** * Set button long release count. * Set the long release count of the specified button. * * \param _b The button number. See \ref ButtonNameConstants. * \param _n The new long release count value. */ #define SetButtonLongReleaseCount(_b, _n) __setButtonLongReleaseCount(_b, _n) /** * Set button release count. * Set the release count of the specified button. * * \param _b The button number. See \ref ButtonNameConstants. * \param _n The new release count value. */ #define SetButtonReleaseCount(_b, _n) __setButtonReleaseCount(_b, _n) /** * Set button state. * Set the state of the specified button. * * \param _b The button to check. See \ref ButtonNameConstants. * \param _n The new button state. See \ref ButtonStateConstants. */ #define SetButtonState(_b, _n) __setButtonState(_b, _n) /** @} */ // end of ButtonModuleFunctions group /** @} */ // end of ButtonModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// UI MODULE ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup UiModule * @{ */ /** @defgroup UiModuleFunctions Ui module functions * Functions for accessing and modifying Ui module features. * @{ */ /** * Set command flags. * Set the command flags. * * \param _n The new command flags. See \ref UiFlagsConstants. */ #define SetCommandFlags(_n) __setCommandFlags(_n) /** * Set UI state. * Set the user interface state. * * \param _n A user interface state value. See \ref UiStateConstants. */ #define SetUIState(_n) __setUIState(_n) /** * Set UI button. * Set user interface button information. * * \param _n A user interface button value. See \ref UiButtonConstants. */ #define SetUIButton(_n) __setUIButton(_n) /** * Set VM run state. * Set VM run state information. * * \param _n The desired VM run state. See \ref UiVMRunStateConstants. */ #define SetVMRunState(_n) __setVMRunState(_n) /** * Set battery state. * Set battery state information. * * \param _n The desired battery state (0..4). */ #define SetBatteryState(_n) __setBatteryState(_n) /** * Set bluetooth state. * Set the Bluetooth state. * * \param _n The desired bluetooth state. See \ref UiBluetoothStateConstants. */ #define SetBluetoothState(_n) __setBluetoothState(_n) /** * Set Usb state. * This method sets the value of the Usb state. * \param _n The Usb state. */ #define SetUsbState(_n) __setUsbState(_n) /** * Set sleep timeout. * Set the NXT sleep timeout value to the specified number of minutes. * * \param _n The minutes to wait before sleeping. */ #define SetSleepTimeout(_n) __setSleepTimeout(_n) /** * Set the sleep timer. * Set the system sleep timer to the specified number of minutes. * * \param _n The minutes left on the timer. */ #define SetSleepTimer(_n) __setSleepTimer(_n) /** * Set volume. * Set the user interface volume level. Valid values are from 0 to 4. * * \param _n The new volume level. */ #define SetVolume(_n) __setVolume(_n) /** * Set on-brick program pointer. * Set the current OBP (on-brick program) step. * * \param _n The new on-brick program step. */ #define SetOnBrickProgramPointer(_n) __setOnBrickProgramPointer(_n) /** * Turn off NXT. * Force the NXT to turn off if the specified value is greater than zero. * \param _n If greater than zero the NXT will turn off. */ #define ForceOff(_n) __forceOff(_n) /** * Set abort flag. * Set the enhanced NBC/NXC firmware's program abort flag. By default the * running program can be interrupted by a short press of the escape button. * You can change this to any other button state flag. * * \param _n The new abort flag value. See \ref ButtonStateConstants * * \warning This function requires the enhanced NBC/NXC firmware. */ #define SetAbortFlag(_n) __setAbortFlag(_n) /** * Get battery Level. * Return the battery level in millivolts. * \param _n The battery level */ #define GetBatteryLevel(_n) __GetBatteryLevel(_n) /** * Get command flags. * Return the command flags. * \param _n Command flags. See \ref UiFlagsConstants */ #define GetCommandFlags(_n) __GetCommandFlags(_n) /** * Get UI module state. * Return the user interface state. * \param _n The UI module state. See \ref UiStateConstants. */ #define GetUIState(_n) __GetUIState(_n) /** * Read UI button. * Return user interface button information. * \param _n A UI button value. See \ref UiButtonConstants. */ #define GetUIButton(_n) __GetUIButton(_n) /** * Read VM run state. * Return VM run state information. * \param _n VM run state. See \ref UiVMRunStateConstants. */ #define GetVMRunState(_n) __GetVMRunState(_n) /** * Get battery state. * Return battery state information (0..4). * \param _n The battery state (0..4) */ #define GetBatteryState(_n) __GetBatteryState(_n) /** * Get bluetooth state. * Return the bluetooth state. * \param _n The bluetooth state. See \ref UiBluetoothStateConstants. */ #define GetBluetoothState(_n) __GetBluetoothState(_n) /** * Get UI module USB state. * This method returns the UI module USB state. * \param _n The UI module USB state. (0=disconnected, 1=connected, 2=working) */ #define GetUsbState(_n) __GetUsbState(_n) /** * Read sleep timeout. * Return the number of minutes that the NXT will remain on before * it automatically shuts down. * \param _n The sleep timeout value */ #define GetSleepTimeout(_n) __GetSleepTimeout(_n) /** * Read sleep timer. * Return the number of minutes left in the countdown to zero from the * original SleepTimeout value. When the SleepTimer value reaches zero the * NXT will shutdown. * \param _n The sleep timer value */ #define GetSleepTimer(_n) __GetSleepTimer(_n) /** * Read battery type. * Return whether the NXT has a rechargeable battery installed or not. * \param _n Whether the battery is rechargeable or not. (false = no, true = yes) */ #define GetRechargeableBattery(_n) __GetRechargeableBattery(_n) /** * Read volume. * Return the user interface volume level. Valid values are from 0 to 4. * \param _n The UI module volume. (0..4) */ #define GetVolume(_n) __GetVolume(_n) /** * Read the on brick program pointer value. * Return the current OBP (on-brick program) step * * \param _n On brick program pointer (step). */ #define GetOnBrickProgramPointer(_n) __GetOnBrickProgramPointer(_n) /** * Read abort flag. * Return the enhanced NBC/NXC firmware's abort flag. * * \param _n The current abort flag value. See \ref ButtonStateConstants. * \warning This function requires the enhanced NBC/NXC firmware. */ #define GetAbortFlag(_n) __GetAbortFlag(_n) /** @} */ // end of UiModuleFunctions group /** @} */ // end of UiModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// COMM MODULE ///////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup CommModule * @{ */ /** @defgroup CommModuleFunctions Comm module functions * Functions for accessing and modifying Comm module features. * @{ */ /** * Send a message to a queue/mailbox. * Write a message into a local mailbox. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _msg The message to write to the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendMessage(_queue, _msg, _result) __sendMessage(_queue, _msg, _result) /** * Read a message from a queue/mailbox. * Read a message from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param _msg The message that is read from the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define ReceiveMessage(_queue, _clear, _msg, _result) __receiveMessage(_queue, _clear, _msg, _result) /** * Read a boolean value from a queue/mailbox. * Read a boolean value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param _bval The boolean value that is read from the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define ReceiveRemoteBool(_queue, _clear, _bval, _result) __receiveRemoteBool(_queue, _clear, _bval, _result) /** * Read a numeric value from a queue/mailbox. * Read a numeric value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param _val The numeric value that is read from the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define ReceiveRemoteNumber(_queue, _clear, _val, _result) __receiveRemoteNumber(_queue, _clear, _val, _result) /** * Read a string value from a queue/mailbox. * Read a string value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param _str The string value that is read from the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define ReceiveRemoteString(_queue, _clear, _str, _result) __receiveMessage(_queue, _clear, _str, _result) /** * Read a value from a queue/mailbox. * Read a value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. Output the value in string, number, and * boolean form. * * \param _queue The mailbox number. See \ref MailboxConstants. * \param _clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param _str The string value that is read from the mailbox. * \param _val The numeric value that is read from the mailbox. * \param _bval The boolean value that is read from the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define ReceiveRemoteMessageEx(_queue, _clear, _str, _val, _bval, _result) __receiveRemoteMessageEx(_queue, _clear, _str, _val, _bval, _result) /** * Write a string value to a local response mailbox. * Write a string value to a response mailbox (the mailbox number + 10). * * \param _queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param _msg The string value to write. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendResponseString(_queue, _msg, _result) __sendResponseString(_queue, _msg, _result) /** * Write a boolean value to a local response mailbox. * Write a boolean value to a response mailbox (the mailbox number + 10). * * \param _queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param _bval The boolean value to write. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendResponseBool(_queue, _bval, _result) __sendResponseBool(_queue, _bval, _result) /** * Write a numeric value to a local response mailbox. * Write a numeric value to a response mailbox (the mailbox number + 10). * * \param _queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param _val The numeric value to write. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendResponseNumber(_queue, _val, _result) __sendResponseNumber(_queue, _val, _result) /** * Check bluetooth status. * Check the status of the bluetooth subsystem for the specified connection slot. * * \param _conn The connection slot (0..3). Connections 0 through 3 are for * bluetooth connections. See \ref CommConnectionConstants. * \param _result The bluetooth status for the specified connection. */ #define BluetoothStatus(_conn, _result) __bluetoothStatus(_conn, _result) /** * Write to a bluetooth connection. * This method tells the NXT firmware to write the data in the buffer to the * device on the specified Bluetooth connection. Use \ref BluetoothStatus to * determine when this write request is completed. * * \param _conn The connection slot (0..3). Connections 0 through 3 are for * bluetooth connections. See \ref CommConnectionConstants. * \param _buffer The data to be written (up to 128 bytes) * \param _result A char value indicating whether the function call succeeded or not. */ #define BluetoothWrite(_conn, _buffer, _result) __bluetoothWrite(_conn, _buffer, _result) /** * Write to a remote connection. * This method tells the NXT firmware to write the data in the buffer to the * device on the specified connection. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _buffer The data to be written (up to 128 bytes) * \param _result A char value indicating whether the function call succeeded or not. * * \warning Writing to the RS485 hi-speed connection requires the enhanced * NBC/NXC firmware */ #define RemoteConnectionWrite(_conn, _buffer, _result) __connectionRawWrite(_conn, _buffer, _result) /** * Check if remote connection is idle. * Check whether a Bluetooth or RS485 hi-speed port connection is idle, * i.e., not currently sending data. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A boolean value indicating whether the connection is idle or busy. * * \warning Checking the status of the RS485 hi-speed connection requires the * enhanced NBC/NXC firmware */ #define RemoteConnectionIdle(_conn, _result) __remoteConnectionIdle(_conn, _result) /** * Send a boolean value to a remote mailbox. * Send a boolean value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _queue The mailbox number. See \ref MailboxConstants. * \param _bval The boolean value to send. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendRemoteBool(_conn, _queue, _bval, _result) __sendRemoteBool(_conn, _queue, _bval, _result) /** * Send a numeric value to a remote mailbox. * Send a numeric value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _queue The mailbox number. See \ref MailboxConstants. * \param _val The numeric value to send. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendRemoteNumber(_conn, _queue, _val, _result) __sendRemoteNumber(_conn, _queue, _val, _result) /** * Send a string value to a remote mailbox. * Send a string value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _queue The mailbox number. See \ref MailboxConstants. * \param _str The string value to send. * \param _result A char value indicating whether the function call succeeded or not. */ #define SendRemoteString(_conn, _queue, _str, _result) __sendRemoteString(_conn, _queue, _str, _result) /** @defgroup CommModuleDCFunctions Direct Command functions * Functions for sending direct commands to another NXT. * @{ */ /** * Send a MessageRead message. * This method sends a MessageRead direct command to the device on the * specified connection. Use \ref RemoteConnectionIdle to determine when this write * request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _queue The mailbox to read. See \ref MailboxConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteMessageRead(_conn, _queue, _result) __remoteMessageRead(_conn, _queue, _result) /** * Send a MessageWrite message. * This method sends a MessageWrite direct command to the device on the * specified connection. Use \ref RemoteConnectionIdle to determine when this write * request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _queue The mailbox to write. See \ref MailboxConstants. * \param _msg The message to write to the mailbox. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteMessageWrite(_conn, _queue, _msg, _result) __sendRemoteString(_conn, _queue, _msg, _result) /** * Send a StartProgram message. * Send the StartProgram direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to start running. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteStartProgram(_conn, _filename, _result) __remoteStartProgram(_conn, _filename, _result) /** * Send a StopProgram message. * Send the StopProgram direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteStopProgram(_conn, _result) __connectionSCDCWrite(_conn, __DCStopProgramPacket, _result) /** * Send a PlaySoundFile message. * Send the PlaySoundFile direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the sound file to play. * \param _bloop A boolean value indicating whether to loop the sound file or not. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePlaySoundFile(_conn, _filename, _bloop, _result) __remotePlaySoundFile(_conn, _filename, _bloop, _result) /** * Send a PlayTone message. * Send the PlayTone direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _frequency The frequency of the tone. * \param _duration The duration of the tone. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePlayTone(_conn, _frequency, _duration, _result) __remotePlayTone(_conn, _frequency, _duration, _result) /** * Send a StopSound message. * Send the StopSound direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteStopSound(_conn, _result) __connectionSCDCWrite(_conn, __DCStopSoundPacket, _result) /** * Send a KeepAlive message. * This method sends a KeepAlive direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteKeepAlive(_conn, _result) __connectionSCDCWrite(_conn, __DCKeepAlivePacket, _result) /** * Send a ResetScaledValue message. * Send the ResetScaledValue direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The input port to reset. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteResetScaledValue(_conn, _port, _result) __remoteResetScaledValue(_conn, _port, _result) /** * Send a ResetMotorPosition message. * Send the ResetMotorPosition direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The output port to reset. * \param _brelative A flag indicating whether the counter to reset is relative. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteResetMotorPosition(_conn, _port, _brelative, _result) __remoteResetMotorPosition(_conn, _port, _brelative, _result) /** * Send a SetInputMode message. * Send the SetInputMode direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The input port to configure. See \ref NBCInputPortConstants. * \param _type The sensor type. See \ref NBCSensorTypeConstants. * \param _mode The sensor mode. See \ref NBCSensorModeConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteSetInputMode(_conn, _port, _type, _mode, _result) __remoteSetInputMode(_conn, _port, _type, _mode, _result) /** * Send a SetOutputMode message. * Send the SetOutputMode direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The output port to configure. See \ref OutputPortConstants. * \param _speed The motor speed. (-100..100) * \param _mode The motor mode. See \ref OutModeConstants. * \param _regmode The motor regulation mode. See \ref OutRegModeConstants. * \param _turnpct The motor synchronized turn percentage. (-100..100) * \param _runstate The motor run state. See \ref OutRunStateConstants. * \param _tacholimit The motor tachometer limit. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteSetOutputState(_conn, _port, _speed, _mode, _regmode, _turnpct, _runstate, _tacholimit, _result) \ __remoteSetOutputState(_conn, _port, _speed, _mode, _regmode, _turnpct, _runstate, _tacholimit, _result) #ifdef __ENHANCED_FIRMWARE /** * Send a GetOutputState message. * Send the GetOutputState direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _params The input and output parameters for the function call. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetOutputState(_conn, _params, _result) \ compchktype _params, TOutputState \ __remoteGetOutputState(_conn, _params, _result) /** * Send a GetInputValues message. * Send the GetInputValues direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _params The input and output parameters for the function call. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetInputValues(_conn, _params, _result) \ compchktype _params, TInputValues \ __remoteGetInputValues(_conn, _params, _result) /** * Send a GetBatteryLevel message. * This method sends a GetBatteryLevel direct command to the device on the specified * connection. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _value The battery level value. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetBatteryLevel(_conn, _value, _result) __remoteGetBatteryLevel(_conn, _value, _result) /** * Send a LSGetStatus message. * This method sends a LSGetStatus direct command to the device on the specified * connection. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _value The count of available bytes to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteLowspeedGetStatus(_conn, _value, _result) __remoteLowspeedGetStatus(_conn, _value, _result) /** * Send a LowspeedRead message. * Send the LowspeedRead direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The input port from which to read I2C data. See \ref NBCInputPortConstants. * \param _bread The number of bytes read. * \param _data A byte array containing the data read from the I2C device. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteLowspeedRead(_conn, _port, _bread, _data, _result) __remoteLowspeedRead(_conn, _port, _bread, _data, _result) /** * Send a GetCurrentProgramName message. * This method sends a GetCurrentProgramName direct command to the device on the specified * connection. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _name The current program name. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetCurrentProgramName(_conn, _name, _result) __remoteGetCurrentProgramName(_conn, _name, _result) /** * Send a DatalogRead message. * Send the DatalogRead direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _remove Remove the datalog message from the queue after reading it (true or false). * \param _cnt The number of bytes read from the datalog. * \param _log A byte array containing the datalog contents. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDatalogRead(_conn, _remove, _cnt, _log, _result) __remoteDatalogRead(_conn, _remove, _cnt, _log, _result) /** * Send a GetContactCount message. * This method sends a GetContactCount direct command to the device on the specified * connection. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _cnt The number of contacts. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetContactCount(_conn, _cnt, _result) __remoteGetContactCount(_conn, _cnt, _result) /** * Send a GetContactName message. * Send the GetContactName direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _idx The index of the contact. * \param _name The name of the specified contact. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetContactName(_conn, _idx, _name, _result) __remoteGetContactName(_conn, _idx, _name, _result) /** * Send a GetConnectionCount message. * This method sends a GetConnectionCount direct command to the device on the specified * connection. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _cnt The number of connections. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetConnectionCount(_conn, _cnt, _result) __remoteGetConnectionCount(_conn, _cnt, _result) /** * Send a GetConnectionName message. * Send the GetConnectionName direct command on the specified connection slot. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _idx The index of the connection. * \param _name The name of the specified connection. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetConnectionName(_conn, _idx, _name, _result) __remoteGetConnectionName(_conn, _idx, _name, _result) #else /** * Send a GetOutputState message. * Send the GetOutputState direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The output port from which to read state information. See \ref OutputPortConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetOutputState(_conn, _port, _result) __remoteGetOutputState(_conn, _port, _result) /** * Send a GetInputValues message. * Send the GetInputValues direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The input port from which to read sensor values. See \ref NBCInputPortConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetInputValues(_conn, _port, _result) __remoteGetInputValues(_conn, _port, _result) /** * Send a GetBatteryLevel message. * This method sends a GetBatteryLevel direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetBatteryLevel(_conn, _result) __remoteGetBatteryLevel(_conn, _result) /** * Send a LSGetStatus message. * This method sends a LSGetStatus direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteLowspeedGetStatus(_conn, _result) __remoteLowspeedGetStatus(_conn, _result) /** * Send a LowspeedRead message. * Send the LowspeedRead direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The input port from which to read I2C data. See \ref NBCInputPortConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteLowspeedRead(_conn, _port, _result) __remoteLowspeedRead(_conn, _port, _result) /** * Send a GetCurrentProgramName message. * This method sends a GetCurrentProgramName direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetCurrentProgramName(_conn, _result) __remoteGetCurrentProgramName(_conn, _result) /** * Send a DatalogRead message. * Send the DatalogRead direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _remove Remove the datalog message from the queue after reading it (true or false). * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDatalogRead(_conn, _remove, _result) __remoteDatalogRead(_conn, _remove, _result) /** * Send a GetContactCount message. * This method sends a GetContactCount direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetContactCount(_conn, _result) __remoteGetContactCount(_conn, _result) /** * Send a GetContactName message. * Send the GetContactName direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _idx The index of the contact. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetContactName(_conn, _idx, _result) __remoteGetContactName(_conn, _idx, _result) /** * Send a GetConnectionCount message. * This method sends a GetConnectionCount direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write * request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetConnectionCount(_conn, _result) __remoteGetConnectionCount(_conn, _result) /** * Send a GetConnectionName message. * Send the GetConnectionName direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _idx The index of the connection. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetConnectionName(_conn, _idx, _result) __remoteGetConnectionName(_conn, _idx, _result) #endif /** * Send a ResetTachoCount message. * Send the ResetTachoCount direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The output port to reset the tachometer count on. See \ref OutputPortConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteResetTachoCount(_conn, _port, _result) __remoteResetTachoCount(_conn, _port, _result) /** * Send a GetProperty message. * Send the GetProperty direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _property The property to read. See \ref RCPropertyConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetProperty(_conn, _property, _result) __remoteGetProperty(_conn, _property, _result) /** * Send a DatalogSetTimes message. * Send the DatalogSetTimes direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _synctime The datalog sync time. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDatalogSetTimes(_conn, _synctime, _result) __remoteDatalogSetTimes(_conn, _synctime, _result) /** * Send a SetProperty message. * Send the SetProperty direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _prop The property to set. See \ref RCPropertyConstants. * \param _value The new property value. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteSetProperty(_conn, _prop, _value, _result) __remoteSetProperty(_conn, _prop, _value, _result) /** * Send a LowspeedWrite message. * Send the LowspeedWrite direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _port The I2C port. See \ref NBCInputPortConstants. * \param _txlen The number of bytes you are writing to the I2C device. * \param _rxlen The number of bytes want to read from the I2C device. * \param _data A byte array containing the data you are writing to the device. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteLowspeedWrite(_conn, _port, _txlen, _rxlen, _data, _result) __remoteLowspeedWrite(_conn, _port, _txlen, _rxlen, _data, _result) /** @} */ // end of CommModuleDCFunctions group /** @defgroup CommModuleSCFunctions System Command functions * Functions for sending system commands to another NXT. * @{ */ #ifdef __ENHANCED_FIRMWARE /** * Send an OpenRead message. * Send the OpenRead system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the file to open for reading. * \param _handle The handle of the file. * \param _size The size of the file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenRead(_conn, _filename, _handle, _size, _result) __remoteOpenRead(_conn, _filename, _handle, _size, _result) /** * Send an OpenAppendData message. * Send the OpenAppendData system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the file to open for appending. * \param _handle The handle of the file. * \param _size The size of the file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenAppendData(_conn, _filename, _handle, _size, _result) __remoteOpenAppendData(_conn, _filename, _handle, _size, _result) /** * Send a DeleteFile message. * Send the DeleteFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to delete. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDeleteFile(_conn, _filename, _result) __remoteDeleteFile(_conn, _filename, _result) /** * Send a FindFirstFile message. * Send the FindFirstFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _mask The filename mask for the files you want to find. * \param _handle The handle of the found file. * \param _name The name of the found file. * \param _size The size of the found file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteFindFirstFile(_conn, _mask, _handle, _name, _size, _result) __remoteFindFirstFile(_conn, _mask, _handle, _name, _size, _result) /** * Send a GetFirmwareVersion message. * This method sends a GetFirmwareVersion system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _pmin The protocol minor version byte. * \param _pmaj The protocol major version byte. * \param _fmin The firmware minor version byte. * \param _fmaj The firmware major version byte. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetFirmwareVersion(_conn, _pmin, _pmaj, _fmin, _fmaj, _result) __remoteGetFirmwareVersion(_conn, _pmin, _pmaj, _fmin, _fmaj, _result) /** * Send a GetBluetoothAddress message. * This method sends a GetBluetoothAddress system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _btaddr The bluetooth address of the remote device. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetBluetoothAddress(_conn, _btaddr, _result) __remoteGetBluetoothAddress(_conn, _btaddr, _result) /** * Send a GetDeviceInfo message. * This method sends a GetDeviceInfo system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _name The name of the remote device. * \param _btaddr The bluetooth address of the remote device. * \param _btsignal The signal strength of each connection on the remote device. * \param _freemem The number of bytes of free flash memory on the remote device. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetDeviceInfo(_conn, _name, _btaddr, _btsignal, _freemem, _result) __remoteGetDeviceInfo(_conn, _name, _btaddr, _btsignal, _freemem, _result) /** * Send a DeleteUserFlash message. * This method sends a DeleteUserFlash system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDeleteUserFlash(_conn, _result) __remoteDeleteUserFlash(_conn, _result) /** * Send an OpenWrite message. * Send the OpenWrite system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWrite(_conn, _filename, _size, _result) __remoteOpenWrite(_conn, _filename, _size, _result) /** * Send an OpenWriteLinear message. * Send the OpenWriteLinear system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWriteLinear(_conn, _filename, _size, _result) __remoteOpenWriteLinear(_conn, _filename, _size, _result) /** * Send an OpenWriteData message. * Send the OpenWriteData system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWriteData(_conn, _filename, _size, _result) __remoteOpenWriteData(_conn, _filename, _size, _result) /** * Send a CloseFile message. * Send the CloseFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file to close. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteCloseFile(_conn, _handle, _result) __remoteCloseFile(_conn, _handle, _result) /** * Send a FindNextFile message. * Send the FindNextFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle returned by the last \ref FindFirstFile or FindNextFile call. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteFindNextFile(_conn, _handle, _result) __remoteFindNextFile(_conn, _handle, _result) /** * Send a PollCommandLength message. * Send the PollCommandLength system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _bufnum The poll buffer you want to query (0=USBPoll, 1=HiSpeed). * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePollCommandLength(_conn, _bufnum, _result) __remotePollCommandLength(_conn, _bufnum, _result) /** * Send a Write message. * Send the Write system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file you are writing to. * \param _data A byte array containing the data you are writing. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteWrite(_conn, _handle, _data, _result) __remoteWrite(_conn, _handle, _data, _result) /** * Send a Read message. * Send the Read system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file you are reading from. * \param _numbytes The number of bytes you want to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteRead(_conn, _handle, _numbytes, _result) __remoteRead(_conn, _handle, _numbytes, _result) /** * Send an IOMapRead message. * Send the IOMapRead system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _id The ID of the module from which to read data. * \param _offset The offset into the IOMap structure from which to read. * \param _numbytes The number of bytes of data to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteIOMapRead(_conn, _id, _offset, _numbytes, _result) __remoteIOMapRead(_conn, _id, _offset, _numbytes, _result) /** * Send a PollCommand message. * Send the PollCommand system command on the specified connection slot to * write the data provided. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _bufnum The buffer from which to read data (0=USBPoll, 1=HiSpeed). * \param _len The number of bytes to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePollCommand(_conn, _bufnum, _len, _result) __remotePollCommand(_conn, _bufnum, _len, _result) /** * Send a RenameFile message. * Send the RenameFile system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _oldname The old filename. * \param _newname The new filename. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteRenameFile(_conn, _oldname, _newname, _result) __remoteRenameFile(_conn, _oldname, _newname, _result) #else /** * Send an OpenRead message. * Send the OpenRead system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for reading. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenRead(_conn, _filename, _result) __remoteOpenRead(_conn, _filename, _result) /** * Send an OpenAppendData message. * Send the OpenAppendData system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for appending. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenAppendData(_conn, _filename, _result) __remoteOpenAppendData(_conn, _filename, _result) /** * Send a DeleteFile message. * Send the DeleteFile system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to delete. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDeleteFile(_conn, _filename, _result) __remoteDeleteFile(_conn, _filename, _result) /** * Send a FindFirstFile message. * Send the FindFirstFile system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _mask The filename mask for the files you want to find. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteFindFirstFile(_conn, _mask, _result) __remoteFindFirstFile(_conn, _mask, _result) /** * Send a GetFirmwareVersion message. * This method sends a GetFirmwareVersion system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetFirmwareVersion(_conn, _result) __connectionSCDCWrite(_conn, __SCGetFirmwareVerPacket, _result) /** * Send a GetBluetoothAddress message. * This method sends a GetBluetoothAddress system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetBluetoothAddress(_conn, _result) __connectionSCDCWrite(_conn, __SCBTGetAddressPacket, _result) /** * Send a GetDeviceInfo message. * This method sends a GetDeviceInfo system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteGetDeviceInfo(_conn, _result) __connectionSCDCWrite(_conn, __SCGetDeviceInfoPacket, _result) /** * Send a DeleteUserFlash message. * This method sends a DeleteUserFlash system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteDeleteUserFlash(_conn, _result) __connectionSCDCWrite(_conn, __SCDeleteUserFlashPacket, _result) /** * Send an OpenWrite message. * Send the OpenWrite system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWrite(_conn, _filename, _size, _result) __remoteOpenWrite(_conn, _filename, _size, _result) /** * Send an OpenWriteLinear message. * Send the OpenWriteLinear system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWriteLinear(_conn, _filename, _size, _result) __remoteOpenWriteLinear(_conn, _filename, _size, _result) /** * Send an OpenWriteData message. * Send the OpenWriteData system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _filename The name of the program to open for writing (i.e., create the file). * \param _size The size for the new file. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteOpenWriteData(_conn, _filename, _size, _result) __remoteOpenWriteData(_conn, _filename, _size, _result) /** * Send a CloseFile message. * Send the CloseFile system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file to close. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteCloseFile(_conn, _handle, _result) __remoteCloseFile(_conn, _handle, _result) /** * Send a FindNextFile message. * Send the FindNextFile system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle returned by the last \ref FindFirstFile or FindNextFile call. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteFindNextFile(_conn, _handle, _result) __remoteFindNextFile(_conn, _handle, _result) /** * Send a PollCommandLength message. * Send the PollCommandLength system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _bufnum The poll buffer you want to query (0=USBPoll, 1=HiSpeed). * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePollCommandLength(_conn, _bufnum, _result) __remotePollCommandLength(_conn, _bufnum, _result) /** * Send a Write message. * Send the Write system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file you are writing to. * \param _data A byte array containing the data you are writing. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteWrite(_conn, _handle, _data, _result) __remoteWrite(_conn, _handle, _data, _result) /** * Send a Read message. * Send the Read system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _handle The handle of the file you are reading from. * \param _numbytes The number of bytes you want to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteRead(_conn, _handle, _numbytes, _result) __remoteRead(_conn, _handle, _numbytes, _result) /** * Send an IOMapRead message. * Send the IOMapRead system command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _id The ID of the module from which to read data. * \param _offset The offset into the IOMap structure from which to read. * \param _numbytes The number of bytes of data to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteIOMapRead(_conn, _id, _offset, _numbytes, _result) __remoteIOMapRead(_conn, _id, _offset, _numbytes, _result) /** * Send a PollCommand message. * Send the PollCommand system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _bufnum The buffer from which to read data (0=USBPoll, 1=HiSpeed). * \param _len The number of bytes to read. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemotePollCommand(_conn, _bufnum, _len, _result) __remotePollCommand(_conn, _bufnum, _len, _result) #endif /** * Send a BluetoothFactoryReset message. * This method sends a BluetoothFactoryReset system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteBluetoothFactoryReset(_conn, _result) __connectionSCDCWrite(_conn, __SCBTFactoryResetPacket, _result) /** * Send an IOMapWrite value message. * Send the IOMapWrite system command on the specified connection slot to * write the value provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _id The ID of the module to which to write data. * \param _offset The offset into the IOMap structure to which to write. * \param _value A scalar variable containing the value you are writing to the IOMap structure. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteIOMapWriteValue(_conn, _id, _offset, _value, _result) __remoteIOMapWriteValue(_conn, _id, _offset, _value, _result) /** * Send an IOMapWrite bytes message. * Send the IOMapWrite system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _id The ID of the module to which to write data. * \param _offset The offset into the IOMap structure to which to write. * \param _data A byte array containing the data you are writing to the IOMap structure. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteIOMapWriteBytes(_conn, _id, _offset, _data, _result) __remoteIOMapWriteBytes(_conn, _id, _offset, _data, _result) /** * Send a SetBrickName message. * Send the SetBrickName system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param _conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param _name The new brick name. * \param _result A char value indicating whether the function call succeeded or not. */ #define RemoteSetBrickName(_conn, _name, _result) __remoteSetBrickName(_conn, _name, _result) /** @} */ // end of CommModuleSCFunctions group /** * Use the RS485 port. * Configure port 4 for RS485 usage. * */ #define UseRS485() __UseRS485() #ifdef __ENHANCED_FIRMWARE /** * Check RS485 status. * Check the status of the RS485 hi-speed port. * * \param _sendingData A boolean value set to true on output if data is being sent. * \param _dataAvail A boolean value set to true on output if data is available to be read. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Status(_sendingData, _dataAvail) __RS485Status(_sendingData, _dataAvail) /** * Write RS485 data. * Write data to the RS485 hi-speed port. * * \param _buffer A byte array containing the data to write to the RS485 port. * \param _status A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Write(_buffer, _status) __RS485Write(_buffer, _status) /** * Read RS485 data. * Read data from the RS485 hi-speed port. * * \param _buffer A byte array that will contain the data read from the RS485 port. * \param _status A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Read(_buffer, _status) __RS485Read(_buffer, _status) #if __FIRMWARE_VERSION > 107 /** * Control the RS485 port. * Control the RS485 hi-speed port using the specified parameters. * * \param _cmd The control command to send to the port. See \ref CommHiSpeedCtrlConstants. * \param _baud The baud rate for the RS485 port. See \ref CommHiSpeedBaudConstants. * \param _mode The RS485 port mode (data bits, stop bits, parity). See \ref * CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, \ref * CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * \param _result A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Control(_cmd, _baud, _mode, _result) __RS485Control(_cmd, _baud, _mode, _result) /** * Configure RS485 UART. * Configure the RS485 UART parameters, including baud rate, data bits, * stop bits, and parity. * * \param _baud The baud rate for the RS485 port. See \ref CommHiSpeedBaudConstants. * \param _mode The RS485 port mode (data bits, stop bits, parity). See \ref * CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, \ref * CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * \param _result A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Uart(_baud, _mode, _result) __RS485Control(HS_CTRL_UART, _baud, _mode, _result) /** * Initialize RS485 port. * Initialize the RS485 UART port to its default values. The baud rate is * set to 921600 and the mode is set to 8N1 (8 data bits, no parity, 1 stop bit). * Data cannot be sent or received over the RS485 port until the UART is * initialized and the port has been configured for RS485 usage. * * \param _result A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Initialize(_result) __RS485Control(HS_CTRL_UART, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, _result) /** * Enable RS485. * Turn on the RS485 hi-speed port so that it can be used. * * \param _result A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Enable(_result) __RS485Control(HS_CTRL_INIT, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, _result) /** * Disable RS485. * Turn off the RS485 port. * * \param _result A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define RS485Disable(_result) __RS485Control(HS_CTRL_EXIT, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, _result) #else #define RS485Control(_cmd, _baud, _result) __RS485Control(_cmd, _baud, _result) #define RS485Uart(_baud, _result) __RS485Control(HS_CTRL_UART, _baud, _result) #define RS485Initialize(_result) __RS485Control(HS_CTRL_UART, HS_BAUD_DEFAULT, _result) #define RS485Enable(_result) __RS485Control(HS_CTRL_INIT, HS_BAUD_DEFAULT, _result) #define RS485Disable(_result) __RS485Control(HS_CTRL_EXIT, HS_BAUD_DEFAULT, _result) #endif /** * Write RS485 boolean. * Write a boolean value to the RS485 hi-speed port. * * \param _bval A boolean value to write over the RS485 port. * \param _status A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define SendRS485Bool(_bval, _status) __sendRS485Bool(_bval, _status) /** * Write RS485 numeric. * Write a numeric value to the RS485 hi-speed port. * * \param _val A numeric value to write over the RS485 port. * \param _status A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define SendRS485Number(_val, _status) __sendRS485Number(_val, _status) /** * Write RS485 string. * Write a string value to the RS485 hi-speed port. * * \param _str A string value to write over the RS485 port. * \param _status A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ #define SendRS485String(_str, _status) __sendRS485String(_str, _status) #endif /** * Get bluetooth device name. * This method returns the name of the device at the specified index in the * Bluetooth device table. * \param _p The device table index. * \param _str The device name of the specified bluetooth device. */ #define GetBTDeviceName(_p, _str) __GetBTDeviceName(_p, _str) /** * Get bluetooth device class. * This method returns the class of the device at the specified index within * the Bluetooth device table. * \param _p The device table index. * \param _n The device class of the specified bluetooth device. */ #define GetBTDeviceClass(_p, _n) __GetBTDeviceClass(_p, _n) /** * Get bluetooth device address. * This method reads the address of the device at the specified index within * the Bluetooth device table and stores it in the data buffer provided. * \param _p The device table index. * \param _btaddr The byte array reference that will contain the device address. */ #define GetBTDeviceAddress(_p, _btaddr) __getBTDeviceAddress(_p, _btaddr) /** * Get bluetooth device status. * This method returns the status of the device at the specified index within * the Bluetooth device table. * \param _p The device table index. * \param _n The status of the specified bluetooth device. */ #define GetBTDeviceStatus(_p, _n) __GetBTDeviceStatus(_p, _n) /** * Get bluetooth device name. * This method returns the name of the device at the specified index in the * Bluetooth connection table. * \param _p The connection slot (0..3). * \param _str The name of the bluetooth device at the specified connection slot. */ #define GetBTConnectionName(_p, _str) __GetBTConnectionName(_p, _str) /** * Get bluetooth device class. * This method returns the class of the device at the specified index within * the Bluetooth connection table. * \param _p The connection slot (0..3). * \param _n The class of the bluetooth device at the specified connection slot. */ #define GetBTConnectionClass(_p, _n) __GetBTConnectionClass(_p, _n) /** * Get bluetooth device pin code. * This method returns the pin code of the device at the specified index in the * Bluetooth connection table. * \param _p The connection slot (0..3). * \param _code The pin code for the bluetooth device at the specified connection slot. */ #define GetBTConnectionPinCode(_p, _code) __GetBTConnectionPinCode(_p, _code) /** * Get bluetooth device address. * This method reads the address of the device at the specified index within * the Bluetooth connection table and stores it in the data buffer provided. * \param _p The connection slot (0..3). * \param _btaddr The byte array reference that will contain the device address. */ #define GetBTConnectionAddress(_p, _btaddr) __getBTConnectionAddress(_p, _btaddr) /** * Get bluetooth device handle number. * This method returns the handle number of the device at the specified index within * the Bluetooth connection table. * \param _p The connection slot (0..3). * \param _n The handle number of the bluetooth device at the specified connection slot. */ #define GetBTConnectionHandleNum(_p, _n) __GetBTConnectionHandleNum(_p, _n) /** * Get bluetooth device stream status. * This method returns the stream status of the device at the specified index within * the Bluetooth connection table. * \param _p The connection slot (0..3). * \param _n The stream status of the bluetooth device at the specified connection slot. */ #define GetBTConnectionStreamStatus(_p, _n) __GetBTConnectionStreamStatus(_p, _n) /** * Get bluetooth device link quality. * This method returns the link quality of the device at the specified index within * the Bluetooth connection table. * \param _p The connection slot (0..3). * \param _n The link quality of the specified connection slot (unimplemented). * \warning This function is not implemented at the firmware level. */ #define GetBTConnectionLinkQuality(_p, _n) __GetBTConnectionLinkQuality(_p, _n) /** * Get NXT name. * This method returns the name of the NXT. * \param _str The NXT's bluetooth name. */ #define GetBrickDataName(_str) GetCommModuleBytes(CommOffsetBrickDataName, 16, _str) /** * Get NXT bluecore version. * This method returns the bluecore version of the NXT. * \param _n The NXT's bluecore version number. */ #define GetBrickDataBluecoreVersion(_n) \ compchk EQ, sizeof(_n), 2 \ GetCommModuleValue(CommOffsetBrickDataBluecoreVersion, _n) /** * Get NXT address. * This method reads the address of the NXT and stores it in the data buffer * provided. * \param _btaddr The byte array reference that will contain the device address. */ #define GetBrickDataAddress(_btaddr) GetCommModuleBytes(CommOffsetBrickDataBdAddr, 7, _btaddr) /** * Get NXT bluetooth state status. * This method returns the Bluetooth state status of the NXT. * \param _n The NXT's bluetooth state status. */ #define GetBrickDataBtStateStatus(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBrickDataBtStateStatus, _n) /** * Get NXT bluetooth hardware status. * This method returns the Bluetooth hardware status of the NXT. * \param _n The NXT's bluetooth hardware status. */ #define GetBrickDataBtHardwareStatus(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBrickDataBtHwStatus, _n) /** * Get NXT bluetooth timeout value. * This method returns the Bluetooth timeout value of the NXT. * \param _n The NXT's bluetooth timeout value. */ #define GetBrickDataTimeoutValue(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBrickDataTimeOutValue, _n) /** * Get bluetooth input buffer data. * This method reads count bytes of data from the Bluetooth input buffer and * writes it to the buffer provided. * * \param _offset A constant offset into the bluetooth input buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the bluetooth input buffer. */ #define GetBTInputBuffer(_offset, _cnt, _data) __getBTInputBuffer(_offset, _cnt, _data) /** * Get bluetooth input buffer in-pointer. * This method returns the value of the input pointer of the Bluetooth input * buffer. * \param _n The bluetooth input buffer's in-pointer value. */ #define GetBTInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtInBufInPtr, _n) /** * Get bluetooth input buffer out-pointer. * This method returns the value of the output pointer of the Bluetooth input * buffer. * \param _n The bluetooth input buffer's out-pointer value. */ #define GetBTInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtInBufOutPtr, _n) /** * Get bluetooth output buffer data. * This method reads count bytes of data from the Bluetooth output buffer and * writes it to the buffer provided. * * \param _offset A constant offset into the bluetooth output buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the bluetooth output buffer. */ #define GetBTOutputBuffer(_offset, _cnt, _data) __getBTOutputBuffer(_offset, _cnt, _data) /** * Get bluetooth output buffer in-pointer. * This method returns the value of the input pointer of the Bluetooth output * buffer. * \param _n The bluetooth output buffer's in-pointer value. */ #define GetBTOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtOutBufInPtr, _n) /** * Get bluetooth output buffer out-pointer. * This method returns the value of the output pointer of the Bluetooth output * buffer. * \param _n The bluetooth output buffer's out-pointer value. */ #define GetBTOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtOutBufOutPtr, _n) /** * Get hi-speed port input buffer data. * This method reads count bytes of data from the hi-speed port input buffer and * writes it to the buffer provided. * * \param _offset A constant offset into the hi-speed port input buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the hi-speed port input buffer. */ #define GetHSInputBuffer(_offset, _cnt, _data) __getHSInputBuffer(_offset, _cnt, _data) /** * Get hi-speed port input buffer in-pointer. * This method returns the value of the input pointer of the hi-speed port input * buffer. * \param _n The hi-speed port input buffer's in-pointer value. */ #define GetHSInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsInBufInPtr, _n) /** * Get hi-speed port input buffer out-pointer. * This method returns the value of the output pointer of the hi-speed port input * buffer. * \param _n The hi-speed port input buffer's out-pointer value. */ #define GetHSInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsInBufOutPtr, _n) /** * Get hi-speed port output buffer data. * This method reads count bytes of data from the hi-speed port output buffer and * writes it to the buffer provided. * * \param _offset A constant offset into the hi-speed port output buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the hi-speed port output buffer. */ #define GetHSOutputBuffer(_offset, _cnt, _data) __getHSOutputBuffer(_offset, _cnt, _data) /** * Get hi-speed port output buffer in-pointer. * This method returns the value of the input pointer of the hi-speed port output * buffer. * \param _n The hi-speed port output buffer's in-pointer value. */ #define GetHSOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsOutBufInPtr, _n) /** * Get hi-speed port output buffer out-pointer. * This method returns the value of the output pointer of the hi-speed port output * buffer. * \param _n The hi-speed port output buffer's out-pointer value. */ #define GetHSOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsOutBufOutPtr, _n) /** * Get usb input buffer data. * This method reads count bytes of data from the usb input buffer and * writes it to the buffer provided. * * \param _offset A constant offset into the usb input buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the usb input buffer. */ #define GetUSBInputBuffer(_offset, _cnt, _data) __getUSBInputBuffer(_offset, _cnt, _data) /** * Get usb port input buffer in-pointer. * This method returns the value of the input pointer of the usb port input * buffer. * \param _n The USB port input buffer's in-pointer value. */ #define GetUSBInputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbInBufInPtr, _n) /** * Get usb port input buffer out-pointer. * This method returns the value of the output pointer of the usb port input * buffer. * \param _n The USB port input buffer's out-pointer value. */ #define GetUSBInputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbInBufOutPtr, _n) /** * Get usb output buffer data. * This method reads count bytes of data from the usb output buffer and * writes it to the buffer provided. * \param _offset A constant offset into the usb output buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the usb output buffer. */ #define GetUSBOutputBuffer(_offset, _cnt, _data) __getUSBOutputBuffer(_offset, _cnt, _data) /** * Get usb port output buffer in-pointer. * This method returns the value of the input pointer of the usb port output * buffer. * \param _n The USB port output buffer's in-pointer value. */ #define GetUSBOutputBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbOutBufInPtr, _n) /** * Get usb port output buffer out-pointer. * This method returns the value of the output pointer of the usb port output * buffer. * \param _n The USB port output buffer's out-pointer value. */ #define GetUSBOutputBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbOutBufOutPtr, _n) /** * Get usb poll buffer data. * This method reads count bytes of data from the usb poll buffer and * writes it to the buffer provided. * \param _offset A constant offset into the usb poll buffer. * \param _cnt The number of bytes to read. * \param _data The byte array reference which will contain the data read from * the usb poll buffer. */ #define GetUSBPollBuffer(_offset, _cnt, _data) __getUSBPollBuffer(_offset, _cnt, _data) /** * Get usb port poll buffer in-pointer. * This method returns the value of the input pointer of the usb port poll * buffer. * \param _n The USB port poll buffer's in-pointer value. */ #define GetUSBPollBufferInPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbPollBufInPtr, _n) /** * Get usb port poll buffer out-pointer. * This method returns the value of the output pointer of the usb port poll * buffer. * \param _n The USB port poll buffer's out-pointer value. */ #define GetUSBPollBufferOutPtr(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbPollBufOutPtr, _n) /** * Get bluetooth device count. * This method returns the number of devices defined within the Bluetooth * device table. * \return The count of known bluetooth devices. */ #define GetBTDeviceCount(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtDeviceCnt, _n) /** * Get bluetooth device name count. * This method returns the number of device names defined within the Bluetooth * device table. This usually has the same value as BTDeviceCount but it can * differ in some instances. * \param _n The count of known bluetooth device names. */ #define GetBTDeviceNameCount(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtDeviceNameCnt, _n) /** * Get hi-speed port flags. * This method returns the value of the hi-speed port flags. * \param _n The hi-speed port flags. See \ref CommHiSpeedFlagsConstants. */ #define GetHSFlags(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsFlags, _n) /** * Get hi-speed port speed. * This method returns the value of the hi-speed port speed (baud rate). * \param _n The hi-speed port speed (baud rate). See \ref CommHiSpeedBaudConstants. */ #define GetHSSpeed(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsSpeed, _n) /** * Get hi-speed port state. * This method returns the value of the hi-speed port state. * \param _n The hi-speed port state. See \ref CommHiSpeedStateConstants. */ #define GetHSState(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsState, _n) /** * Get USB state. * This method returns the value of the USB state. * \param _n The USB state. */ #define GetUSBState(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetUsbState, _n) #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) /** * Get hi-speed port mode. * This method returns the value of the hi-speed port mode. * \param _n The hi-speed port mode (data bits, stop bits, parity). See * \ref CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, * \ref CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define GetHSMode(_n) \ compchk EQ, sizeof(_n), 2 \ GetCommModuleValue(CommOffsetHsMode, _n) /** * Get Bluetooth data mode. * This method returns the value of the Bluetooth data mode. * \param _n The Bluetooth data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define GetBTDataMode(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetBtDataMode, _n) /** * Get hi-speed port data mode. * This method returns the value of the hi-speed port data mode. * \param _n The hi-speed port data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define GetHSDataMode(_n) \ compchk EQ, sizeof(_n), 1 \ GetCommModuleValue(CommOffsetHsDataMode, _n) #endif /** * Set bluetooth input buffer data. * Write cnt bytes of data to the bluetooth input buffer at offset. * \param _offset A constant offset into the input buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetBTInputBuffer(_offset, _cnt, _data) __setBTInputBuffer(_offset, _cnt, _data) /** * Set bluetooth input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param _n The new in-pointer value (0..127). */ #define SetBTInputBufferInPtr(_n) __setBTInputBufferInPtr(_n) /** * Set bluetooth input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param _n The new out-pointer value (0..127). */ #define SetBTInputBufferOutPtr(_n) __setBTInputBufferOutPtr(_n) /** * Set bluetooth output buffer data. * Write cnt bytes of data to the bluetooth output buffer at offset. * \param _offset A constant offset into the output buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetBTOutputBuffer(_offset, _cnt, _data) __setBTOutputBuffer(_offset, _cnt, _data) /** * Set bluetooth output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param _n The new in-pointer value (0..127). */ #define SetBTOutputBufferInPtr(_n) __setBTOutputBufferInPtr(_n) /** * Set bluetooth output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param _n The new out-pointer value (0..127). */ #define SetBTOutputBufferOutPtr(_n) __setBTOutputBufferOutPtr(_n) /** * Set hi-speed port input buffer data. * Write cnt bytes of data to the hi-speed port input buffer at offset. * \param _offset A constant offset into the input buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetHSInputBuffer(_offset, _cnt, _data) __setHSInputBuffer(_offset, _cnt, _data) /** * Set hi-speed port input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param _n The new in-pointer value (0..127). */ #define SetHSInputBufferInPtr(_n) __setHSInputBufferInPtr(_n) /** * Set hi-speed port input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param _n The new out-pointer value (0..127). */ #define SetHSInputBufferOutPtr(_n) __setHSInputBufferOutPtr(_n) /** * Set hi-speed port output buffer data. * Write cnt bytes of data to the hi-speed port output buffer at offset. * \param _offset A constant offset into the output buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetHSOutputBuffer(_offset, _cnt, _data) __setHSOutputBuffer(_offset, _cnt, _data) /** * Set hi-speed port output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param _n The new in-pointer value (0..127). */ #define SetHSOutputBufferInPtr(_n) __setHSOutputBufferInPtr(_n) /** * Set hi-speed port output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param _n The new out-pointer value (0..127). */ #define SetHSOutputBufferOutPtr(_n) __setHSOutputBufferOutPtr(_n) /** * Set USB input buffer data. * Write cnt bytes of data to the USB input buffer at offset. * \param _offset A constant offset into the input buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetUSBInputBuffer(_offset, _cnt, _data) __setUSBInputBuffer(_offset, _cnt, _data) /** * Set USB input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param _n The new in-pointer value (0..63). */ #define SetUSBInputBufferInPtr(_n) __setUSBInputBufferInPtr(_n) /** * Set USB input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param _n The new out-pointer value (0..63). */ #define SetUSBInputBufferOutPtr(_n) __setUSBInputBufferOutPtr(_n) /** * Set USB output buffer data. * Write cnt bytes of data to the USB output buffer at offset. * \param _offset A constant offset into the output buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetUSBOutputBuffer(_offset, _cnt, _data) __setUSBOutputBuffer(_offset, _cnt, _data) /** * Set USB output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param _n The new in-pointer value (0..63). */ #define SetUSBOutputBufferInPtr(_n) __setUSBOutputBufferInPtr(_n) /** * Set USB output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param _n The new out-pointer value (0..63). */ #define SetUSBOutputBufferOutPtr(_n) __setUSBOutputBufferOutPtr(_n) /** * Set USB poll buffer data. * Write cnt bytes of data to the USB poll buffer at offset. * \param _offset A constant offset into the poll buffer * \param _cnt The number of bytes to write * \param _data A byte array containing the data to write */ #define SetUSBPollBuffer(_offset, _cnt, _data) __setUSBPollBuffer(_offset, _cnt, _data) /** * Set USB poll buffer in-pointer. * Set the value of the poll buffer in-pointer. * \param _n The new in-pointer value (0..63). */ #define SetUSBPollBufferInPtr(_n) __setUSBPollBufferInPtr(_n) /** * Set USB poll buffer out-pointer. * Set the value of the poll buffer out-pointer. * \param _n The new out-pointer value (0..63). */ #define SetUSBPollBufferOutPtr(_n) __setUSBPollBufferOutPtr(_n) /** * Set hi-speed port flags. * This method sets the value of the hi-speed port flags. * \param _n The hi-speed port flags. See \ref CommHiSpeedFlagsConstants. */ #define SetHSFlags(_n) __setHSFlags(_n) /** * Set hi-speed port speed. * This method sets the value of the hi-speed port speed (baud rate). * \param _n The hi-speed port speed (baud rate). See \ref CommHiSpeedBaudConstants. */ #define SetHSSpeed(_n) __setHSSpeed(_n) /** * Set hi-speed port state. * This method sets the value of the hi-speed port state. * \param _n The hi-speed port state. See \ref CommHiSpeedStateConstants. */ #define SetHSState(_n) __setHSState(_n) /** * Set USB state. * This method sets the value of the USB state. * \param _n The USB state. */ #define SetUSBState(_n) __setUSBState(_n) #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) /** * Set hi-speed port mode. * This method sets the value of the hi-speed port mode. * \param _n The hi-speed port mode (data bits, stop bits, parity). See * \ref CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, * \ref CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define SetHSMode(_n) __setHSMode(_n) /** * Set Bluetooth data mode. * This method sets the value of the Bluetooth data mode. * \param _n The Bluetooth data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define SetBTDataMode(_n) __setBTDataMode(_n) /** * Set hi-speed port data mode. * This method sets the value of the hi-speed port data mode. * \param _n The hi-speed port data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ #define SetHSDataMode(_n) __setHSDataMode(_n) #endif /** @} */ // end of CommModuleFunctions group /** @} */ // end of CommModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// IOCTRL MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup IOCtrlModule * @{ */ /** @defgroup IOCtrlModuleFunctions IOCtrl module functions * Functions for accessing and modifying IOCtrl module features. * @{ */ /** * Power down the NXT. * This function powers down the NXT. * The running program will terminate as a result of this action. */ #define PowerDown SetIOCtrlModuleValue(IOCtrlOffsetPowerOn, IOCTRL_POWERDOWN) /** * Reboot the NXT in firmware download mode. * This function lets you reboot the NXT into SAMBA or firmware download mode. * The running program will terminate as a result of this action. */ #define RebootInFirmwareMode SetIOCtrlModuleValue(IOCtrlOffsetPowerOn, IOCTRL_BOOT) /** @} */ // end of IOCtrlModuleFunctions group /** @} */ // end of IOCtrlModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// LOADER MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup LoaderModule * @{ */ /** @defgroup LoaderModuleFunctions Loader module functions * Functions for accessing and modifying Loader module features. * @{ */ /** * Get free flash memory. * Get the number of bytes of flash memory that are available for use. * * \param _value The number of bytes of unused flash memory. */ #define GetFreeMemory(_value) __GetFreeMemory(_value) /** * Create a file. * Create a new file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param _fname The name of the file to create. * \param _fsize The size of the file. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. */ #define CreateFile(_fname, _fsize, _handle, _result) __createFile(_fname, _fsize, _handle, _result) /** * Open a file for appending. * Open an existing file with the specified filename for writing. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. * The filename parameter must be a constant or a variable. * * \param _fname The name of the file to open. * \param _fsize The size of the file returned by the function. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. */ #define OpenFileAppend(_fname, _fsize, _handle, _result) __openFileAppend(_fname, _fsize, _handle, _result) /** * Open a file for reading. * Open an existing file with the specified filename for reading. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param _fname The name of the file to open. * \param _fsize The size of the file returned by the function. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. */ #define OpenFileRead(_fname, _fsize, _handle, _result) __openFileRead(_fname, _fsize, _handle, _result) /** * Close a file. * Close the file associated with the specified file handle. The loader * result code is returned as the value of the function call. The handle * parameter must be a constant or a variable. * * \param _handle The file handle. * \param _result The function call result. See \ref LoaderErrors. */ #define CloseFile(_handle, _result) __closeFile(_handle, _result) /** * Resolve a handle. * Resolve a file handle from the specified filename. The file handle is * returned in the second parameter, which must be a variable. A boolean * value indicating whether the handle can be used to write to the file or * not is returned in the last parameter, which must be a variable. The * loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param _fname The name of the file for which to resolve a handle. * \param _handle The file handle output from the function call. * \param _writeable A boolean flag indicating whether the handle is * to a file open for writing (true) or reading (false). * \param _result The function call result. See \ref LoaderErrors. */ #define ResolveHandle(_fname, _handle, _writeable, _result) __resolveHandle(_fname, _handle, _writeable, _result) /** * Rename a file. * Rename a file from the old filename to the new filename. The loader * param _result code is returned as the value of the function call. The filename * parameters must be constants or variables. * * \param _oldname The old filename. * \param _newname The new filename. * \param _result The function call result. See \ref LoaderErrors. */ #define RenameFile(_oldname, _newname, _result) __renameFile(_oldname, _newname, _result) /** * Delete a file. * Delete the specified file. The loader result code is returned as the * value of the function call. The filename parameter must be a constant or a * variable. * * \param _fname The name of the file to delete. * \param _result The function call result. See \ref LoaderErrors. */ #define DeleteFile(_fname, _result) __deleteFile(_fname, _result) /** * Resize a file. * Resize the specified file. The loader result code is returned as the * value of the function call. The filename parameter must be a constant or a * variable. * * \param _fname The name of the file to resize. * \param _newsize The new size for the file. * \param _result The function call result. See \ref LoaderErrors. */ #define ResizeFile(_fname, _newsize, _result) __fileResize(_fname, _newsize, _result) #ifdef __ENHANCED_FIRMWARE /** * Create a linear file. * Create a new linear file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param _fname The name of the file to create. * \param _fsize The size of the file. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ #define CreateFileLinear(_fname, _fsize, _handle, _result) __createFileLinear(_fname, _fsize, _handle, _result) /** * Create a non-linear file. * Create a new non-linear file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param _fname The name of the file to create. * \param _fsize The size of the file. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ #define CreateFileNonLinear(_fname, _fsize, _handle, _result) __createFileNonLinear(_fname, _fsize, _handle, _result) /** * Open a linear file for reading. * Open an existing linear file with the specified filename for reading. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param _fname The name of the file to open. * \param _fsize The size of the file returned by the function. * \param _handle The file handle output from the function call. * \param _result The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ #define OpenFileReadLinear(_fname, _fsize, _handle, _result) __openFileReadLinear(_fname, _fsize, _handle, _result) /** * Start searching for files. * This function lets you begin iterating through files stored on the NXT. * * \param _fname On input this contains the filename pattern you are searching * for. On output this contains the name of the first file found that matches * the pattern. * \param _handle The search handle input to and output from the function call. * \param _result The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ #define FindFirstFile(_fname, _handle, _result) __findFirstFile(_fname, _handle, _result) /** * Continue searching for files. * This function lets you continue iterating through files stored on the NXT. * * \param _fname On output this contains the name of the next file found that * matches the pattern used when the search began by calling \ref FindFirstFile. * \param _handle The search handle input to and output from the function call. * \param _result The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ #define FindNextFile(_fname, _handle, _result) __findNextFile(_fname, _handle, _result) #endif /** * Calculate the size of a variable. * Calculate the number of bytes required to store the contents of the * variable passed into the function. * * \param _n The variable. * \param _result The number of bytes occupied by the variable. */ #define SizeOf(_n, _result) __sizeOF(_n, _result) /** * Read a value from a file. * Read a value from the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * variable. The type of the value parameter determines the number of bytes of * data read. * * \param _handle The file handle. * \param _n The variable to store the data read from the file. * \param _result The function call result. See \ref LoaderErrors. */ #define Read(_handle, _n, _result) __readValue(_handle, _n, _result) /** * Read a value from a file plus line ending. * Read a value from the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * variable. The type of the value parameter determines the number of bytes * of data read. The ReadLn function reads two additional bytes from the * file which it assumes are a carriage return and line feed pair. * * \param _handle The file handle. * \param _n The variable to store the data read from the file. * \param _result The function call result. See \ref LoaderErrors. */ #define ReadLn(_handle, _n, _result) __readLnValue(_handle, _n, _result) /** * Read bytes from a file. * Read the specified number of bytes from the file associated with the * specified handle. The handle parameter must be a variable. The length * parameter must be a variable. The buf parameter must be an array or a * string variable. The actual number of bytes read is returned in the * length parameter. * * \param _handle The file handle. * \param _len The number of bytes to read. Returns the number of bytes actually read. * \param _buf The byte array where the data is stored on output. * \param _result The function call result. See \ref LoaderErrors. */ #define ReadBytes(_handle, _len, _buf, _result) __readBytes(_handle, _len, _buf, _result) /** * Read a string from a file plus line ending. * Read a string from the file associated with the specified handle. * The handle parameter must be a variable. The output parameter must be a * variable. Appends bytes to the output variable until a line ending (CRLF) * is reached. The line ending is also read but it is not appended to the * output parameter. * * \param _handle The file handle. * \param _output The variable to store the string read from the file. * \param _result The function call result. See \ref LoaderErrors. */ #define ReadLnString(_handle, _output, _result) __readLnString(_handle, _output, _result) /** * Write value to file. * Write a value to the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * constant, a constant expression, or a variable. The type of the value * parameter determines the number of bytes of data written. * * \param _handle The file handle. * \param _n The value to write to the file. * \param _result The function call result. See \ref LoaderErrors. */ #define Write(_handle, _n, _result) __writeValue(_handle, _n, _result) /** * Write a value and new line to a file. * Write a value to the file associated with the specified handle. The * handle parameter must be a variable. The value parameter must be a constant, * a constant expression, or a variable. The type of the value parameter * determines the number of bytes of data written. This function also * writes a carriage return and a line feed to the file following the numeric * data. * * \param _handle The file handle. * \param _n The value to write to the file. * \param _result The function call result. See \ref LoaderErrors. */ #define WriteLn(_handle, _n, _result) __writeLnValue(_handle, _n, _result) /** * Write string to a file. * Write the string to the file associated with the specified handle. The * handle parameter must be a variable. The count parameter must be a variable. * The str parameter must be a string variable or string constant. The actual * number of bytes written is returned in the cnt parameter. * * \param _handle The file handle. * \param _str The string to write to the file. * \param _cnt The number of bytes actually written to the file. * \param _result The function call result. See \ref LoaderErrors. */ #define WriteString(_handle, _str, _cnt, _result) __writeString(_handle, _str, _cnt, _result) /** * Write string and new line to a file. * Write the string to the file associated with the specified handle. The * handle parameter must be a variable. The count parameter must be a variable. * The str parameter must be a string variable or string constant. This * function also writes a carriage return and a line feed to the file following * the string data. The total number of bytes written is returned in the * cnt parameter. * * \param _handle The file handle. * \param _str The string to write to the file. * \param _cnt The number of bytes actually written to the file. * \param _result The function call result. See \ref LoaderErrors. */ #define WriteLnString(_handle, _str, _cnt, _result) __writeLnString(_handle, _str, _cnt, _result) /** * Write bytes to file. * Write the contents of the data array to the file associated with the * specified handle. The handle parameter must be a variable. The cnt * parameter must be a variable. The data parameter must be a byte array. The * actual number of bytes written is returned in the cnt parameter. * * \param _handle The file handle. * \param _buf The byte array or string containing the data to write. * \param _cnt The number of bytes actually written to the file. * \param _result The function call result. See \ref LoaderErrors. */ #define WriteBytes(_handle, _buf, _cnt, _result) __writeBytes(_handle, _buf, _cnt, _result) /** * Write bytes to a file with limit. * Write the specified number of bytes to the file associated with the * specified handle. The handle parameter must be a variable. The len * parameter must be a variable. The buf parameter must be a byte array or a * string variable or string constant. The actual number of bytes written is * returned in the len parameter. * * \param _handle The file handle. * \param _len The maximum number of bytes to write on input. Returns the * actual number of bytes written. * \param _buf The byte array or string containing the data to write. * \param _result The function call result. See \ref LoaderErrors. */ #define WriteBytesEx(_handle, _len, _buf, _result) __writeBytesEx(_handle, _len, _buf, _result) /** @} */ // end of LoaderModuleFunctions group /** @} */ // end of LoaderModule group /** @} */ // end of NXTFirmwareModules group /** @addtogroup StandardCAPIFunctions * @{ */ /** @defgroup cstdlibAPI cstdlib API * Standard C cstdlib API functions. * @{ */ /** * Generate an unsigned random number. * Return an unsigned 16-bit random number. The * returned value will range between 0 and n (exclusive). * * \param _arg An unsigned random number. * \param _max The maximum unsigned value desired. */ #define Random(_arg,_max) __Random(_arg,_max) /** * Generate signed random number. * Return a signed 16-bit random number. * * \param _arg A signed random number */ #define SignedRandom(_arg) __SignedRandom(_arg) /** @} */ // end of cstdlibAPI group /** @defgroup cmathAPI cmath API * Standard C cmath API functions. * @{ */ /** * Convert from BCD to decimal * Return the decimal equivalent of the binary coded decimal value provided. * * \param _bcd The value you want to convert from bcd to decimal. * \param _result The decimal equivalent of the binary coded decimal byte. */ #define bcd2dec(_bcd, _result) __bcd2dec(_bcd, _result) /** @} */ // end of cmathAPI group /** @} */ // end of StandardCAPIFunctions group /** @addtogroup ThirdPartyDevices * @{ */ /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// HiTechnic API //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup HiTechnicAPI * @{ */ /** * Set sensor as HiTechnic Gyro. * Configure the sensor on the specified port as a HiTechnic Gyro sensor. * * \param _port The sensor port. See \ref NBCInputPortConstants. */ #define SetSensorHTGyro(_port) __SetSensorHTGyro(_port) /** * Read HiTechnic Gyro sensor. * Read the HiTechnic Gyro sensor on the specified port. The offset value * should be calculated by averaging several readings with an offset of zero * while the sensor is perfectly still. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _offset The zero offset. * \param _val The Gyro sensor reading. */ #define ReadSensorHTGyro(_p, _offset, _val) __ReadSensorHTGyro(_p, _offset, _val) /** * Set sensor as HiTechnic Magnet. * Configure the sensor on the specified port as a HiTechnic Magnet sensor. * * \param _port The sensor port. See \ref NBCInputPortConstants. */ #define SetSensorHTMagnet(_port) __SetSensorHTGyro(_port) /** * Read HiTechnic Magnet sensor. * Read the HiTechnic Magnet sensor on the specified port. The offset value * should be calculated by averaging several readings with an offset of zero * while the sensor is perfectly still. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _offset The zero offset. * \param _val The Magnet sensor reading. */ #define ReadSensorHTMagnet(_p, _offset, _val) __ReadSensorHTGyro(_p, _offset, _val) /** * Set sensor as HiTechnic EOPD. * Configure the sensor on the specified port as a HiTechnic EOPD sensor. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _bStd Configure in standard or long-range mode. */ #define SetSensorHTEOPD(_port, _bStd) __SetSensorHTEOPD(_port, _bStd) /** * Read HiTechnic EOPD sensor. * Read the HiTechnic EOPD sensor on the specified port. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _val The EOPD sensor reading. */ #define ReadSensorHTEOPD(_port, _val) __ReadSensorHTEOPD(_port, _val) /** * Read HiTechnic touch multiplexer. * Read touch sensor values from the HiTechnic touch multiplexer device. * * \param _p The sensor port. See \ref NBCInputPortConstants. * \param _t1 The value of touch sensor 1. * \param _t2 The value of touch sensor 2. * \param _t3 The value of touch sensor 3. * \param _t4 The value of touch sensor 4. */ #define ReadSensorHTTouchMultiplexer(_p, _t1, _t2, _t3, _t4) __ReadSensorHTTouchMultiplexer(_p, _t1, _t2, _t3, _t4) /** * HTPowerFunctionCommand function. * Execute a pair of Power Function motor commands on the specified channel * using the HiTechnic iRLink device. Commands for outa and outb are * \ref PF_CMD_STOP, \ref PF_CMD_REV, \ref PF_CMD_FWD, and \ref PF_CMD_BRAKE. * Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _outa The Power Function command for output A. See \ref PFCmdConstants. * \param _outb The Power Function command for output B. See \ref PFCmdConstants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPowerFunctionCommand(_port, _channel, _outa, _outb, _result) \ __HTPFComboDirect(_port, _channel, _outa, _outb, _result) /** * HTIRTrain function. * Control an IR Train receiver set to the specified channel using the * HiTechnic iRLink device. Valid func values are \ref TRAIN_FUNC_STOP, * \ref TRAIN_FUNC_INCR_SPEED, \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. * Valid channel values are \ref TRAIN_CHANNEL_1 through \ref TRAIN_CHANNEL_3 and * \ref TRAIN_CHANNEL_ALL. The port must be configured as a Lowspeed port before * using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The IR Train channel. See \ref IRTrainChannels. * \param _func The IR Train function. See \ref IRTrainFuncs * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTIRTrain(_port, _channel, _func, _result) \ __HTIRTrain(_port, _channel, _func, FALSE, _result) /** * HTPFComboDirect function. * Execute a pair of Power Function motor commands on the specified channel * using the HiTechnic iRLink device. Commands for outa and outb are * \ref PF_CMD_STOP, \ref PF_CMD_REV, \ref PF_CMD_FWD, and \ref PF_CMD_BRAKE. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _outa The Power Function command for output A. See \ref PFCmdConstants. * \param _outb The Power Function command for output B. See \ref PFCmdConstants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFComboDirect(_port, _channel, _outa, _outb, _result) \ __HTPFComboDirect(_port, _channel, _outa, _outb, _result) /** * HTPFComboPWM function. * Control the speed of both outputs on a Power Function receiver set to the * specified channel using the HiTechnic iRLink device. Valid output values * are \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _outa The Power Function PWM command for output A. See \ref PFPWMOptions. * \param _outb The Power Function PWM command for output B. See \ref PFPWMOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFComboPWM(_port, _channel, _outa, _outb, _result) \ __HTPFComboPWM(_port, _channel, _outa, _outb, _result) /** * HTPFRawOutput function. * Control a Power Function receiver set to the specified channel using the * HiTechnic iRLink device. Build the raw data stream using the 3 nibbles * (4 bit values). The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _nibble0 The first raw data nibble. * \param _nibble1 The second raw data nibble. * \param _nibble2 The third raw data nibble. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFRawOutput(_port, _nibble0, _nibble1, _nibble2, _result) \ __HTPFRawOutput(_port, _nibble0, _nibble1, _nibble2, _result) /** * HTPFRepeat function. * Repeat sending the last Power Function command using the HiTechnic * IRLink device. Specify the number of times to repeat the command and the * number of milliseconds of delay between each repetition. The port must be * configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _count The number of times to repeat the command. * \param _delay The number of milliseconds to delay between each repetition. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFRepeat(_port, _count, _delay, _result) \ __HTPFRepeatLastCommand(_port, _count, _delay, _result) /** * HTPFSingleOutputCST function. * Control a single output on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are \ref PF_CST_CLEAR1_CLEAR2, * \ref PF_CST_SET1_CLEAR2, \ref PF_CST_CLEAR1_SET2, \ref PF_CST_SET1_SET2, * \ref PF_CST_INCREMENT_PWM, \ref PF_CST_DECREMENT_PWM, \ref PF_CST_FULL_FWD, * \ref PF_CST_FULL_REV, and \ref PF_CST_TOGGLE_DIR. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _func The Power Function CST function. See \ref PFCSTOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFSingleOutputCST(_port, _channel, _out, _func, _result) \ __HTPFSingleOutput(_port, _channel, _out, _func, TRUE, _result) /** * HTPFSingleOutputPWM function. * Control the speed of a single output on a Power Function receiver set to * the specified channel using the HiTechnic iRLink device. Select the * desired output using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are * \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _func The Power Function PWM function. See \ref PFPWMOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFSingleOutputPWM(_port, _channel, _out, _func, _result) \ __HTPFSingleOutput(_port, _channel, _out, _func, FALSE, _result) /** * HTPFSinglePin function. * Control a single pin on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Select the desired pin using \ref PF_PIN_C1 or * \ref PF_PIN_C2. Valid functions are \ref PF_FUNC_NOCHANGE, \ref PF_FUNC_CLEAR, * \ref PF_FUNC_SET, and \ref PF_FUNC_TOGGLE. Valid channels are \ref PF_CHANNEL_1 through * \ref PF_CHANNEL_4. Specify whether the mode by passing true (continuous) or * false (timeout) as the final parameter. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _pin The Power Function pin. See \ref PFPinConstants. * \param _func The Power Function single pin function. See \ref PFPinFuncs. * \param _cont Control whether the mode is continuous or timeout. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFSinglePin(_port, _channel, _out, _pin, _func, _cont, _result) \ __HTPFSinglePin(_port, _channel, _out, _pin, _func, _cont, _result) /** * HTPFTrain function. * Control both outputs on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device as if it were an IR Train * receiver. Valid function values are \ref TRAIN_FUNC_STOP, \ref TRAIN_FUNC_INCR_SPEED, * \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _func The Power Function train function. See \ref IRTrainFuncs. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define HTPFTrain(_port, _channel, _func, _result) \ __HTIRTrain(_port, _channel, _func, TRUE, _result) /** * HTRCXSetIRLinkPort function. * Set the global port in advance of using the HTRCX* and HTScout* API * functions for sending RCX and Scout messages over the HiTechnic iRLink * device. The port must be configured as a Lowspeed port before using any of * the HiTechnic RCX and Scout iRLink functions. * * \param _port The sensor port. See \ref NBCInputPortConstants. */ #define HTRCXSetIRLinkPort(_port) __HTRCXSetIRLinkPort(_port) /** * HTRCXBatteryLevel function. * Send the BatteryLevel command to an RCX to read the current battery level. * * \param _result The RCX battery level. */ #define HTRCXBatteryLevel(_result) __HTRCXBatteryLevel(_result) /** * HTRCXPoll function * Send the Poll command to an RCX to read a signed 2-byte value at the * specified source and value combination. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. * \param _result The value read from the specified port and value. */ #define HTRCXPoll(_src, _value, _result) __HTRCXPoll(_src, _value, _result) /** * HTRCXPollMemory function. * Send the PollMemory command to an RCX. * * \param _memaddress The RCX memory address. * \param _result The value read from the specified address. */ #define HTRCXPollMemory(_memaddress, _result) __HTRCXPollMemory(_memaddress, _result) /** * HTRCXAddToDatalog function. * Send the AddToDatalog command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define HTRCXAddToDatalog(_src, _value) __HTRCXAddToDatalog(_src, _value) /** * HTRCXClearAllEvents function. * Send the ClearAllEvents command to an RCX. */ #define HTRCXClearAllEvents() __HTRCXOpNoArgs(RCX_ClearAllEventsOp) /** * HTRCXClearCounter function. * Send the ClearCounter command to an RCX. * * \param _counter The counter to clear. */ #define HTRCXClearCounter(_counter) __HTRCXClearCounter(_counter) /** * HTRCXClearMsg function. * Send the ClearMsg command to an RCX. */ #define HTRCXClearMsg() __HTRCXOpNoArgs(RCX_ClearMsgOp) /** * HTRCXClearSensor function. * Send the ClearSensor command to an RCX. * * \param _port The RCX port number. */ #define HTRCXClearSensor(_port) __HTRCXClearSensor(_port) /** * HTRCXClearSound function. * Send the ClearSound command to an RCX. */ #define HTRCXClearSound() __HTRCXOpNoArgs(RCX_ClearSoundOp) /** * HTRCXClearTimer function. * Send the ClearTimer command to an RCX. * * \param _timer The timer to clear. */ #define HTRCXClearTimer(_timer) __HTRCXClearTimer(_timer) /** * HTRCXCreateDatalog function. * Send the CreateDatalog command to an RCX. * * \param _size The new datalog size. */ #define HTRCXCreateDatalog(_size) __HTRCXCreateDatalog(_size) /** * HTRCXDecCounter function. * Send the DecCounter command to an RCX. * * \param _counter The counter to decrement. */ #define HTRCXDecCounter(_counter) __HTRCXDecCounter(_counter) /** * HTRCXDeleteSub function. * Send the DeleteSub command to an RCX. * * \param _s The subroutine number to delete. */ #define HTRCXDeleteSub(_s) __HTRCXDeleteSub(_s) /** * HTRCXDeleteSubs function. * Send the DeleteSubs command to an RCX. */ #define HTRCXDeleteSubs() __HTRCXOpNoArgs(RCX_DeleteSubsOp) /** * HTRCXDeleteTask function. * Send the DeleteTask command to an RCX. * * \param _t The task number to delete. */ #define HTRCXDeleteTask(_t) __HTRCXDeleteTask(_t) /** * HTRCXDeleteTasks function. * Send the DeleteTasks command to an RCX. */ #define HTRCXDeleteTasks() __HTRCXOpNoArgs(RCX_DeleteTasksOp) /** * HTRCXDisableOutput function. * Send the DisableOutput command to an RCX. * * \param _outputs The RCX output(s) to disable. See \ref RCXOutputConstants. */ #define HTRCXDisableOutput(_outputs) __HTRCXSetGlobalOutput(_outputs, RCX_OUT_OFF) /** * HTRCXEnableOutput function. * Send the EnableOutput command to an RCX. * * \param _outputs The RCX output(s) to enable. See \ref RCXOutputConstants. */ #define HTRCXEnableOutput(_outputs) __HTRCXSetGlobalOutput(_outputs, RCX_OUT_ON) /** * HTRCXEvent function. * Send the Event command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define HTRCXEvent(_src, _value) __HTRCXEvent(_src, _value) /** * HTRCXFloat function. * Send commands to an RCX to float the specified outputs. * * \param _outputs The RCX output(s) to float. See \ref RCXOutputConstants. */ #define HTRCXFloat(_outputs) __HTRCXSetOutput(_outputs, RCX_OUT_FLOAT) /** * HTRCXFwd function. * Send commands to an RCX to set the specified outputs to the forward direction. * * \param _outputs The RCX output(s) to set forward. See \ref RCXOutputConstants. */ #define HTRCXFwd(_outputs) __HTRCXSetDirection(_outputs, RCX_OUT_FWD) /** * HTRCXIncCounter function. * Send the IncCounter command to an RCX. * * \param _counter The counter to increment. */ #define HTRCXIncCounter(_counter) __HTRCXIncCounter(_counter) /** * HTRCXInvertOutput function. * Send the InvertOutput command to an RCX. * * \param _outputs The RCX output(s) to invert. See \ref RCXOutputConstants. */ #define HTRCXInvertOutput(_outputs) __HTRCXSetGlobalDirection(_outputs, RCX_OUT_REV) /** * HTRCXMuteSound function. * Send the MuteSound command to an RCX. */ #define HTRCXMuteSound() __HTRCXOpNoArgs(RCX_MuteSoundOp) /** * HTRCXObvertOutput function. * Send the ObvertOutput command to an RCX. * * \param _outputs The RCX output(s) to obvert. See \ref RCXOutputConstants. */ #define HTRCXObvertOutput(_outputs) __HTRCXSetGlobalDirection(_outputs, RCX_OUT_FWD) /** * HTRCXOff function. * Send commands to an RCX to turn off the specified outputs. * * \param _outputs The RCX output(s) to turn off. See \ref RCXOutputConstants. */ #define HTRCXOff(_outputs) __HTRCXSetOutput(_outputs, RCX_OUT_OFF) /** * HTRCXOn function. * Send commands to an RCX to turn on the specified outputs. * * \param _outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. */ #define HTRCXOn(_outputs) __HTRCXSetOutput(_outputs, RCX_OUT_ON) /** * HTRCXOnFor function. * Send commands to an RCX to turn on the specified outputs in the forward * direction for the specified duration. * * \param _outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. * \param _ms The number of milliseconds to leave the outputs on */ #define HTRCXOnFor(_outputs, _ms) __HTRCXOnFor(_outputs, _ms) /** * HTRCXOnFwd function. * Send commands to an RCX to turn on the specified outputs in the forward * direction. * * \param _outputs The RCX output(s) to turn on in the forward direction. See \ref RCXOutputConstants. */ #define HTRCXOnFwd(_outputs) __HTRCXOnFwd(_outputs) /** * HTRCXOnRev function. * Send commands to an RCX to turn on the specified outputs in the reverse direction. * * \param _outputs The RCX output(s) to turn on in the reverse direction. See \ref RCXOutputConstants. */ #define HTRCXOnRev(_outputs) __HTRCXOnRev(_outputs) /** * HTRCXPBTurnOff function. * Send the PBTurnOff command to an RCX. */ #define HTRCXPBTurnOff() __HTRCXOpNoArgs(RCX_PBTurnOffOp) /** * HTRCXPing function. * Send the Ping command to an RCX. */ #define HTRCXPing() __HTRCXOpNoArgs(RCX_PingOp) /** * HTRCXPlaySound function. * Send the PlaySound command to an RCX. * * \param _snd The sound number to play. */ #define HTRCXPlaySound(_snd) __HTRCXPlaySound(_snd) /** * HTRCXPlayTone function. * Send the PlayTone command to an RCX. * * \param _freq The frequency of the tone to play. * \param _duration The duration of the tone to play. */ #define HTRCXPlayTone(_freq, _duration) __HTRCXPlayTone(_freq, _duration) /** * HTRCXPlayToneVar function. * Send the PlayToneVar command to an RCX. * * \param _varnum The variable containing the tone frequency to play. * \param _duration The duration of the tone to play. */ #define HTRCXPlayToneVar(_varnum, _duration) __HTRCXPlayToneVar(_varnum, _duration) /** * HTRCXRemote function. * Send the Remote command to an RCX. * * \param _cmd The RCX IR remote command to send. See \ref RCXRemoteConstants. */ #define HTRCXRemote(_cmd) __HTRCXRemote(_cmd) /** * HTRCXRev function. * Send commands to an RCX to set the specified outputs to the reverse direction. * * \param _outputs The RCX output(s) to reverse direction. See \ref RCXOutputConstants. */ #define HTRCXRev(_outputs) __HTRCXSetDirection(_outputs, RCX_OUT_REV) /** * HTRCXSelectDisplay function. * Send the SelectDisplay command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define HTRCXSelectDisplay(_src, _value) __HTRCXSelectDisplay(_src, _value) /** * HTRCXSelectProgram function. * Send the SelectProgram command to an RCX. * * \param _prog The program number to select. */ #define HTRCXSelectProgram(_prog) __HTRCXSelectProgram(_prog) /** * HTRCXSendSerial function. * Send the SendSerial command to an RCX. * * \param _first The first byte address. * \param _count The number of bytes to send. */ #define HTRCXSendSerial(_first, _count) __HTRCXSendSerial(_first, _count) /** * HTRCXSetDirection function. * Send the SetDirection command to an RCX to configure the direction of the specified outputs. * * \param _outputs The RCX output(s) to set direction. See \ref RCXOutputConstants. * \param _dir The RCX output direction. See \ref RCXOutputDirection. */ #define HTRCXSetDirection(_outputs, _dir) __HTRCXSetDirection(_outputs, _dir) /** * HTRCXSetEvent function. * Send the SetEvent command to an RCX. * * \param _evt The event number to set. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _type The event type. */ #define HTRCXSetEvent(_evt, _src, _type) __HTRCXSetEvent(_evt, _src, _type) /** * HTRCXSetGlobalDirection function. * Send the SetGlobalDirection command to an RCX. * * \param _outputs The RCX output(s) to set global direction. See \ref RCXOutputConstants. * \param _dir The RCX output direction. See \ref RCXOutputDirection. */ #define HTRCXSetGlobalDirection(_outputs, _dir) __HTRCXSetGlobalDirection(_outputs, _dir) /** * HTRCXSetGlobalOutput function. * Send the SetGlobalOutput command to an RCX. * * \param _outputs The RCX output(s) to set global mode. See \ref RCXOutputConstants. * \param _mode The RCX output mode. See \ref RCXOutputMode. */ #define HTRCXSetGlobalOutput(_outputs, _mode) __HTRCXSetGlobalOutput(_outputs, _mode) /** * HTRCXSetMaxPower function. * Send the SetMaxPower command to an RCX. * * \param _outputs The RCX output(s) to set max power. See \ref RCXOutputConstants. * \param _pwrsrc The RCX source. See \ref RCXSourceConstants. * \param _pwrval The RCX value. */ #define HTRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) __HTRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) /** * HTRCXSetMessage function. * Send the SetMessage command to an RCX. * * \param _msg The numeric message to send. */ #define HTRCXSetMessage(_msg) __HTRCXSetMessage(_msg) /** * HTRCXSetOutput function. * Send the SetOutput command to an RCX to configure the mode of the specified outputs * * \param _outputs The RCX output(s) to set mode. See \ref RCXOutputConstants. * \param _mode The RCX output mode. See \ref RCXOutputMode. */ #define HTRCXSetOutput(_outputs, _mode) __HTRCXSetOutput(_outputs, _mode) /** * HTRCXSetPower function. * Send the SetPower command to an RCX to configure the power level of the specified outputs. * * \param _outputs The RCX output(s) to set power. See \ref RCXOutputConstants. * \param _pwrsrc The RCX source. See \ref RCXSourceConstants. * \param _pwrval The RCX value. */ #define HTRCXSetPower(_outputs, _pwrsrc, _pwrval) __HTRCXSetPower(_outputs, _pwrsrc, _pwrval) /** * HTRCXSetPriority function. * Send the SetPriority command to an RCX. * * \param _p The new task priority. */ #define HTRCXSetPriority(_p) __HTRCXSetPriority(_p) /** * HTRCXSetSensorMode function. * Send the SetSensorMode command to an RCX. * * \param _port The RCX sensor port. * \param _mode The RCX sensor mode. */ #define HTRCXSetSensorMode(_port, _mode) __HTRCXSetSensorMode(_port, _mode) /** * HTRCXSetSensorType function. * Send the SetSensorType command to an RCX. * * \param _port The RCX sensor port. * \param _type The RCX sensor type. */ #define HTRCXSetSensorType(_port, _type) __HTRCXSetSensorType(_port, _type) /** * HTRCXSetSleepTime function. * Send the SetSleepTime command to an RCX. * * \param _t The new sleep time value. */ #define HTRCXSetSleepTime(_t) __HTRCXSetSleepTime(_t) /** * HTRCXSetTxPower function. * Send the SetTxPower command to an RCX. * * \param _pwr The IR transmit power level. */ #define HTRCXSetTxPower(_pwr) __HTRCXSetTxPower(_pwr) /** * HTRCXSetWatch function. * Send the SetWatch command to an RCX. * * \param _hours The new watch time hours value. * \param _minutes The new watch time minutes value. */ #define HTRCXSetWatch(_hours, _minutes) __HTRCXSetWatch(_hours, _minutes) /** * HTRCXStartTask function. * Send the StartTask command to an RCX. * * \param _t The task number to start. */ #define HTRCXStartTask(_t) __HTRCXStartTask(_t) /** * HTRCXStopAllTasks function. * Send the StopAllTasks command to an RCX. */ #define HTRCXStopAllTasks() __HTRCXOpNoArgs(RCX_StopAllTasksOp) /** * HTRCXStopTask function. * Send the StopTask command to an RCX. * * \param _t The task number to stop. */ #define HTRCXStopTask(_t) __HTRCXStopTask(_t) /** * HTRCXToggle function. * Send commands to an RCX to toggle the direction of the specified outputs. * * \param _outputs The RCX output(s) to toggle. See \ref RCXOutputConstants. */ #define HTRCXToggle(_outputs) __HTRCXSetDirection(_outputs, RCX_OUT_TOGGLE) /** * HTRCXUnmuteSound function. * Send the UnmuteSound command to an RCX. */ #define HTRCXUnmuteSound() __HTRCXOpNoArgs(RCX_UnmuteSoundOp) /** * HTScoutCalibrateSensor function. * Send the CalibrateSensor command to a Scout. */ #define HTScoutCalibrateSensor() __HTRCXOpNoArgs(RCX_LSCalibrateOp) /** * HTScoutMuteSound function. * Send the MuteSound command to a Scout. */ #define HTScoutMuteSound() __HTScoutMuteSound() /** * HTScoutSelectSounds function. * Send the SelectSounds command to a Scout. * * \param _grp The Scout sound group to select. */ #define HTScoutSelectSounds(_grp) __HTScoutSelectSounds(_grp) /** * HTScoutSendVLL function. * Send the SendVLL command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSendVLL(_src, _value) __HTScoutSendVLL(_src, _value) /** * HTScoutSetEventFeedback function. * Send the SetEventFeedback command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSetEventFeedback(_src, _value) __HTScoutSetEventFeedback(_src, _value) /** * HTScoutSetLight function. * Send the SetLight command to a Scout. * * \param _x Set the light on or off using this value. See \ref ScoutLightConstants. */ #define HTScoutSetLight(_x) __HTScoutSetLight(_x) /** * HTScoutSetScoutMode function. * Send the SetScoutMode command to a Scout. * * \param _mode Set the scout mode. See \ref ScoutModeConstants. */ #define HTScoutSetScoutMode(_mode) __HTScoutSetScoutMode(_mode) /** * HTScoutSetSensorClickTime function. * Send the SetSensorClickTime command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSetSensorClickTime(_src, _value) __HTScoutSetSensorClickTime(_src, _value) /** * HTScoutSetSensorHysteresis function. * Send the SetSensorHysteresis command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSetSensorHysteresis(_src, _value) __HTScoutSetSensorHysteresis(_src, _value) /** * HTScoutSetSensorLowerLimit function. * Send the SetSensorLowerLimit command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSetSensorLowerLimit(_src, _value) __HTScoutSetSensorLowerLimit(_src, _value) /** * HTScoutSetSensorUpperLimit function. * Send the SetSensorUpperLimit command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define HTScoutSetSensorUpperLimit(_src, _value) __HTScoutSetSensorUpperLimit(_src, _value) /** * HTScoutUnmuteSound function. * Send the UnmuteSound command to a Scout. */ #define HTScoutUnmuteSound() __HTScoutUnmuteSound() /** * Read HiTechnic compass. * Read the compass heading value of the HiTechnic Compass sensor on the * specified port. The port must be configured as a Lowspeed port before * using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The compass heading. */ #define ReadSensorHTCompass(_port, _value) __ReadSensorHTCompass(_port, _value) /** * Read HiTechnic color sensor color number. * Read the color number from the HiTechnic Color sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The color number. */ #define ReadSensorHTColorNum(_port, _value) __ReadSensorHTColorNum(_port, _value) /** * Read HiTechnic IRSeeker direction. * Read the direction value of the HiTechnic IR Seeker on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The IRSeeker direction. */ #define ReadSensorHTIRSeekerDir(_port, _value) __ReadSensorHTIRSeekerDir(_port, _value) /** * Read HiTechnic IRSeeker2 register. * Read a register value from the HiTechnic IR Seeker2 on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _reg The register address. See \ref HTIRSeeker2Constants. * \param _value The IRSeeker2 register value. */ #define ReadSensorHTIRSeeker2Addr(_port, _reg, _value) __ReadSensorHTIRSeeker2Addr(_port, _reg, _value) /** * Read HiTechnic acceleration values. * Read X, Y, and Z axis acceleration values from the HiTechnic Accelerometer * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _x The output x-axis acceleration. * \param _y The output y-axis acceleration. * \param _z The output z-axis acceleration. * \param _result The function call result. */ #define ReadSensorHTAccel(_port, _x, _y, _z, _result) __ReadSensorHTAccel(_port, _x, _y, _z, _result) /** * Read HiTechnic Color values. * Read color number, red, green, and blue values from the HiTechnic Color * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _ColorNum The output color number. * \param _Red The red color value. * \param _Green The green color value. * \param _Blue The blue color value. * \param _result The function call result. */ #define ReadSensorHTColor(_port, _ColorNum, _Red, _Green, _Blue, _result) __ReadSensorHTColor(_port, _ColorNum, _Red, _Green, _Blue, _result) /** * Read HiTechnic Color raw values. * Read the raw red, green, and blue values from the HiTechnic Color sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _Red The raw red color value. * \param _Green The raw green color value. * \param _Blue The raw blue color value. * \param _result The function call result. */ #define ReadSensorHTRawColor(_port, _Red, _Green, _Blue, _result) __ReadSensorHTRawColor(_port, _Red, _Green, _Blue, _result) /** * Read HiTechnic Color normalized values. * Read the color index and the normalized red, green, and blue values from * the HiTechnic Color sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _ColorIdx The output color index. * \param _Red The normalized red color value. * \param _Green The normalized green color value. * \param _Blue The normalized blue color value. * \param _result The function call result. */ #define ReadSensorHTNormalizedColor(_port, _ColorIdx, _Red, _Green, _Blue, _result) __ReadSensorHTNormalizedColor(_port, _ColorIdx, _Red, _Green, _Blue, _result) /** * Read HiTechnic IRSeeker values. * Read direction, and five signal strength values from the HiTechnic * IRSeeker sensor. Returns a boolean value indicating whether or not the * operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _dir The direction. * \param _s1 The signal strength from sensor 1. * \param _s3 The signal strength from sensor 3. * \param _s5 The signal strength from sensor 5. * \param _s7 The signal strength from sensor 7. * \param _s9 The signal strength from sensor 9. * \param _result The function call result. */ #define ReadSensorHTIRSeeker(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) __ReadSensorHTIRSeeker(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) /** * Read HiTechnic IRSeeker2 DC values. * Read direction, five signal strength, and average strength values from the * HiTechnic IRSeeker2 sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _dir The direction. * \param _s1 The signal strength from sensor 1. * \param _s3 The signal strength from sensor 3. * \param _s5 The signal strength from sensor 5. * \param _s7 The signal strength from sensor 7. * \param _s9 The signal strength from sensor 9. * \param _avg The average signal strength. * \param _result The function call result. */ #define ReadSensorHTIRSeeker2DC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _avg, _result) __ReadSensorHTIRSeeker2DC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _avg, _result) /** * Read HiTechnic IRSeeker2 AC values. * Read direction, and five signal strength values from the HiTechnic * IRSeeker2 sensor in AC mode. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _dir The direction. * \param _s1 The signal strength from sensor 1. * \param _s3 The signal strength from sensor 3. * \param _s5 The signal strength from sensor 5. * \param _s7 The signal strength from sensor 7. * \param _s9 The signal strength from sensor 9. * \param _result The function call result. */ #define ReadSensorHTIRSeeker2AC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) __ReadSensorHTIRSeeker2AC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _result) /** * Set HiTechnic IRSeeker2 mode. * Set the mode of the HiTechnic IRSeeker2 sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _mode The IRSeeker2 mode. See \ref HTIRSeeker2Constants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define SetHTIRSeeker2Mode(_port, _mode, _result) __SetHTIRSeeker2Mode(_port, _mode, _result) /** * Set HiTechnic Color2 mode. * Set the mode of the HiTechnic Color2 sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _mode The Color2 mode. See \ref HTColor2Constants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define SetHTColor2Mode(_port, _mode, _result) __SetHTColor2Mode(_port, _mode, _result) /** * Read HiTechnic Color2 active values. * Read color number, red, green, and blue values from the HiTechnic Color2 * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _ColorNum The output color number. * \param _Red The red color value. * \param _Green The green color value. * \param _Blue The blue color value. * \param _White The white color value. * \param _result The function call result. */ #define ReadSensorHTColor2Active(_port, _ColorNum, _Red, _Green, _Blue, _White, _result) __ReadSensorHTColor2Active(_port, _ColorNum, _Red, _Green, _Blue, _White, _result) /** * Read HiTechnic Color2 normalized active values. * Read the color index and the normalized red, green, and blue values from * the HiTechnic Color2 sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _ColorIdx The output color index. * \param _Red The normalized red color value. * \param _Green The normalized green color value. * \param _Blue The normalized blue color value. * \param _result The function call result. */ #define ReadSensorHTNormalizedColor2Active(_port, _ColorIdx, _Red, _Green, _Blue, _result) __ReadSensorHTNormalizedColor2Active(_port, _ColorIdx, _Red, _Green, _Blue, _result) /** * Read HiTechnic Color2 raw values. * Read the raw red, green, and blue values from the HiTechnic Color2 sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _Red The raw red color value. * \param _Green The raw green color value. * \param _Blue The raw blue color value. * \param _White The raw white color value. * \param _result The function call result. */ #define ReadSensorHTRawColor2(_port, _Red, _Green, _Blue, _White, _result) __ReadSensorHTRawColor2(_port, _Red, _Green, _Blue, _White, _result) /** * Read HiTechnic IRReceiver Power Function bytes. * Read Power Function bytes from the HiTechnic IRReceiver sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _pfdata Eight bytes of power function remote IR data. * \param _result The function call result. */ #define ReadSensorHTIRReceiver(_port, _pfdata, _result) __ReadSensorHTIRReceiver(_port, _pfdata, _result) /** * Read HiTechnic IRReceiver Power Function value. * Read a Power Function byte from the HiTechnic IRReceiver sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _reg The power function data offset. See \ref HTIRReceiverConstants. * \param _pfchar A single byte of power function remote IR data. * \param _result The function call result. */ #define ReadSensorHTIRReceiverEx(_port, _reg, _pfchar, _result) __ReadSensorHTIRReceiverEx(_port, _reg, _pfchar, _result) /** * Reset HiTechnic Angle sensor. * Reset the HiTechnic Angle sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _mode The Angle reset mode. See \ref HTAngleConstants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define ResetSensorHTAngle(_port, _mode, _result) __ResetSensorHTAngle(_port, _mode, _result) /** * Read HiTechnic Angle sensor values. * Read values from the HiTechnic Angle sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _Angle Current angle in degrees (0-359). * \param _AccAngle Accumulated angle in degrees (-2147483648 to 2147483647). * \param _RPM rotations per minute (-1000 to 1000). * \param _result The function call result. */ #define ReadSensorHTAngle(_port, _Angle, _AccAngle, _RPM, _result) __ReadSensorHTAngle(_port, _Angle, _AccAngle, _RPM, _result) /** @} */ // end of HiTechnicAPI group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// MindSensors API /////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup MindSensorsAPI * @{ */ /** * Read mindsensors compass value. * Return the Mindsensors Compass sensor value. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The mindsensors compass value */ #define ReadSensorMSCompass(_port, _i2caddr, _value) __ReadSensorMSCompass(_port, _i2caddr, _value) /** * Read mindsensors DROD value. * Return the Mindsensors DROD sensor value. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The mindsensors DROD value */ #define ReadSensorMSDROD(_port, _value) __ReadSensorMSDROD(_port, _value) /** * Configure a mindsensors DROD active sensor. * Configure the specified port for an active mindsensors DROD sensor. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorMSDRODActive(_port) __SetSensorMSDRODActive(_port) /** * Configure a mindsensors DROD inactive sensor. * Configure the specified port for an inactive mindsensors DROD sensor. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorMSDRODInactive(_port) __SetSensorMSDRODInactive(_port) /** * Read mindsensors NXTSumoEyes value. * Return the Mindsensors NXTSumoEyes sensor value. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The mindsensors NXTSumoEyes value */ #define ReadSensorNXTSumoEyes(_port, _value) __ReadSensorNXTSumoEyes(_port, _value) /** * Configure a mindsensors NXTSumoEyes long range sensor. * Configure the specified port for a long range mindsensors NXTSumoEyes sensor. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorNXTSumoEyesLong(_port) __SetSensorNXTSumoEyesLong(_port) /** * Configure a mindsensors NXTSumoEyes short range sensor. * Configure the specified port for a short range mindsensors NXTSumoEyes sensor. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorNXTSumoEyesShort(_port) __SetSensorNXTSumoEyesShort(_port) /** * Read mindsensors raw pressure value. * Return the Mindsensors pressure sensor raw value. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The mindsensors raw pressure value */ #define ReadSensorMSPressureRaw(_port, _value) __ReadSensorMSPressureRaw(_port, _value) /** * Read mindsensors processed pressure value. * Return the Mindsensors pressure sensor processed value. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _value The mindsensors processed pressure value */ #define ReadSensorMSPressure(_port, _value) __ReadSensorMSPressure(_port, _value) /** * Configure a mindsensors pressure sensor. * Configure the specified port for a mindsensors pressure sensor. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorMSPressure(_port) __SetSensorMSPressure(_port) /** * Configure a mindsensors touch sensor multiplexer. * Configure the specified port for a mindsensors touch sensor multiplexer. * * \param _port The port to configure. See \ref NBCInputPortConstants. */ #define SetSensorMSTouchMux(_port) __SetSensorMSTouchMux(_port) /** * Read mindsensors acceleration values. * Read X, Y, and Z axis acceleration values from the mindsensors Accelerometer * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _x The output x-axis acceleration. * \param _y The output y-axis acceleration. * \param _z The output z-axis acceleration. * \param _result The function call result. */ #define ReadSensorMSAccel(_port, _i2caddr, _x, _y, _z, _result) __ReadSensorMSAccel(_port, _i2caddr, _x, _y, _z, _result) /** * Read mindsensors playstation controller values. * Read playstation controller values from the mindsensors playstation * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _b1 The button set 1 values. See \ref MSPSPNXBtnSet1. * \param _b2 The button set 2 values. See \ref MSPSPNXBtnSet2. * \param _xleft The left joystick x value. * \param _yleft The left joystick y value. * \param _xright The right joystick x value. * \param _yright The right joystick y value. * \param _result The function call result. */ #define ReadSensorMSPlayStation(_port, _i2caddr, _b1, _b2, _xleft, _yleft, _xright, _yright, _result) \ __ReadSensorMSPlayStation(_port, _i2caddr, _b1, _b2, _xleft, _yleft, _xright, _yright, _result) /** * Read mindsensors RTClock values. * Read real-time clock values from the Mindsensors RTClock sensor. Returns * a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _sec The seconds. * \param _min The minutes. * \param _hrs The hours. * \param _dow The day of week number. * \param _date The day. * \param _month The month. * \param _year The year. * \param _result The function call result. */ #define ReadSensorMSRTClock(_port, _sec, _min, _hrs, _dow, _date, _month, _year, _result) \ __ReadSensorMSRTClock(_port, _sec, _min, _hrs, _dow, _date, _month, _year, _result) /** * Read mindsensors tilt values. * Read X, Y, and Z axis tilt values from the mindsensors tilt * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _x The output x-axis tilt. * \param _y The output y-axis tilt. * \param _z The output z-axis tilt. * \param _result The function call result. */ #define ReadSensorMSTilt(_port, _i2caddr, _x, _y, _z, _result) __ReadSensorMSTilt(_port, _i2caddr, _x, _y, _z, _result) /** * Send PFMate command. * Send a PFMate command to the power function IR receiver. * Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The power function IR receiver channel. See the \ref PFMateChannelConstants group. * \param _motors The motor(s) to control. See the \ref PFMateMotorConstants group. * \param _cmdA The power function command for motor A. See the \ref PFCmdConstants group. * \param _spdA The power function speed for motor A. * \param _cmdB The power function command for motor B. See the \ref PFCmdConstants group. * \param _spdB The power function speed for motor B. * \param _result The function call result. */ #define PFMateSend(_port, _i2caddr, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB, _result) __PFMateSend(_port, _i2caddr, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB, _result) /** * Send raw PFMate command. * Send a raw PFMate command to the power function IR receiver. * Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The power function IR receiver channel. See the \ref PFMateChannelConstants group. * \param _b1 Raw byte 1. * \param _b2 Raw byte 2. * \param _result The function call result. */ #define PFMateSendRaw(_port, _i2caddr, _channel, _b1, _b2, _result) __PFMateSendRaw(_port, _i2caddr, _channel, _b1, _b2, _result) /** * Read a mindsensors device value. * Read a one, two, or four byte value from a mindsensors sensor. The value must be * stored with the least signficant byte (LSB) first (i.e., little endian). Returns a boolean value * indicating whether or not the operation completed successfully. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _reg The device register to read. * \param _bytes The number of bytes to read. Only 1, 2, or 4 byte values are supported. * \param _out The value read from the device. * \param _result The function call result. */ #define MSReadValue(_port, _i2caddr, _reg, _bytes, _out, _result) __MSReadValue(_port, _i2caddr, _reg, _bytes, _out, _result) /** * Turn on power to device. * Turn the power on for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define MSEnergize(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, MS_CMD_ENERGIZED, _result) /** * Turn off power to device. * Turn power off for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define MSDeenergize(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, MS_CMD_DEENERGIZED, _result) /** * Turn on mindsensors ADPA mode. * Turn ADPA mode on for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define MSADPAOn(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, MS_CMD_ADPA_ON, _result) /** * Turn off mindsensors ADPA mode. * Turn ADPA mode off for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define MSADPAOff(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, MS_CMD_ADPA_OFF, _result) /** * Configure DIST-Nx as GP2D12. * Configure the mindsensors DIST-Nx sensor as GP2D12. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define DISTNxGP2D12(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2D12, _result) /** * Configure DIST-Nx as GP2D120. * Configure the mindsensors DIST-Nx sensor as GP2D120. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define DISTNxGP2D120(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2D120, _result) /** * Configure DIST-Nx as GP2YA02. * Configure the mindsensors DIST-Nx sensor as GP2YA02. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define DISTNxGP2YA02(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2YA02, _result) /** * Configure DIST-Nx as GP2YA21. * Configure the mindsensors DIST-Nx sensor as GP2YA21. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define DISTNxGP2YA21(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2YA21, _result) /** * Read DIST-Nx distance value. * Read the mindsensors DIST-Nx sensor's distance value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The distance value. * \param _result The function call result. */ #define ReadDISTNxDistance(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_DIST, 2, _out, _result) /** * Read DIST-Nx maximum distance value. * Read the mindsensors DIST-Nx sensor's maximum distance value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The maximum distance value. * \param _result The function call result. */ #define ReadDISTNxMaxDistance(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_DIST_MAX, 2, _out, _result) /** * Read DIST-Nx minimum distance value. * Read the mindsensors DIST-Nx sensor's minimum distance value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The minimum distance value. * \param _result The function call result. */ #define ReadDISTNxMinDistance(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_DIST_MIN, 2, _out, _result) /** * Read DIST-Nx module type value. * Read the mindsensors DIST-Nx sensor's module type value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The module type value. * \param _result The function call result. */ #define ReadDISTNxModuleType(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_MODULE_TYPE, 1, _out, _result) /** * Read DIST-Nx num points value. * Read the mindsensors DIST-Nx sensor's num points value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The num points value. * \param _result The function call result. */ #define ReadDISTNxNumPoints(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_NUM_POINTS, 1, _out, _result) /** * Read DIST-Nx voltage value. * Read the mindsensors DIST-Nx sensor's voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The voltage value. * \param _result The function call result. */ #define ReadDISTNxVoltage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, DIST_REG_VOLT, 2, _out, _result) /** * Calibrate ACCL-Nx X-axis. * Calibrate the mindsensors ACCL-Nx sensor X-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateX(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_X_CAL, _result) /** * Stop calibrating ACCL-Nx X-axis. * Stop calibrating the mindsensors ACCL-Nx sensor X-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateXEnd(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_X_CAL_END, _result) /** * Calibrate ACCL-Nx Y-axis. * Calibrate the mindsensors ACCL-Nx sensor Y-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateY(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Y_CAL, _result) /** * Stop calibrating ACCL-Nx Y-axis. * Stop calibrating the mindsensors ACCL-Nx sensor Y-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateYEnd(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Y_CAL_END, _result) /** * Calibrate ACCL-Nx Z-axis. * Calibrate the mindsensors ACCL-Nx sensor Z-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateZ(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Z_CAL, _result) /** * Stop calibrating ACCL-Nx Z-axis. * Stop calibrating the mindsensors ACCL-Nx sensor Z-axis. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxCalibrateZEnd(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Z_CAL_END, _result) /** * Reset ACCL-Nx calibration. * Reset the mindsensors ACCL-Nx sensor calibration to factory settings. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define ACCLNxResetCalibration(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, ACCL_CMD_RESET_CAL, _result) /** * Set ACCL-Nx sensitivity. * Reset the mindsensors ACCL-Nx sensor calibration to factory settings. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _slevel The sensitivity level. See \ref MSACCLNxSLevel. * \param _result The function call result. */ #define SetACCLNxSensitivity(_port, _i2caddr, _slevel, _result) __I2CSendCmd(_port, _i2caddr, _slevel, _result) /** * Read ACCL-Nx sensitivity value. * Read the mindsensors ACCL-Nx sensitivity value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The sensitivity value. * \param _result The function call result. */ #define ReadACCLNxSensitivity(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_sENS_LVL, 1, _out, _result) /** * Read ACCL-Nx X offset value. * Read the mindsensors ACCL-Nx sensor's X offset value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The X offset value. * \param _result The function call result. */ #define ReadACCLNxXOffset(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_X_OFFSET, 2, _out, _result) /** * Read ACCL-Nx X range value. * Read the mindsensors ACCL-Nx sensor's X range value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The X range value. * \param _result The function call result. */ #define ReadACCLNxXRange(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_X_RANGE, 2, _out, _result) /** * Read ACCL-Nx Y offset value. * Read the mindsensors ACCL-Nx sensor's Y offset value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The Y offset value. * \param _result The function call result. */ #define ReadACCLNxYOffset(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_Y_OFFSET, 2, _out, _result) /** * Read ACCL-Nx Y range value. * Read the mindsensors ACCL-Nx sensor's Y range value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The Y range value. * \param _result The function call result. */ #define ReadACCLNxYRange(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_Y_RANGE, 2, _out, _result) /** * Read ACCL-Nx Z offset value. * Read the mindsensors ACCL-Nx sensor's Z offset value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The Z offset value. * \param _result The function call result. */ #define ReadACCLNxZOffset(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_Z_OFFSET, 2, _out, _result) /** * Read ACCL-Nx Z range value. * Read the mindsensors ACCL-Nx sensor's Z range value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The Z range value. * \param _result The function call result. */ #define ReadACCLNxZRange(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, ACCL_REG_Z_RANGE, 2, _out, _result) /** * Configure PSP-Nx in digital mode. * Configure the mindsensors PSP-Nx device in digital mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define PSPNxDigital(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, PSP_CMD_DIGITAL, _result) /** * Configure PSP-Nx in analog mode. * Configure the mindsensors PSP-Nx device in analog mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define PSPNxAnalog(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, PSP_CMD_ANALOG, _result) /** * Read NXTServo servo position value. * Read the mindsensors NXTServo device's servo position value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _out The specified servo's position value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTServoPosition(_port, _i2caddr, _servo, _out, _result) __MSReadValue(_port, _i2caddr, NXTSERVO_REG_S1_POS+(_servo*2), 2, _out, _result) /** * Read NXTServo servo speed value. * Read the mindsensors NXTServo device's servo speed value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _out The specified servo's speed value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTServoSpeed(_port, _i2caddr, _servo, _out, _result) __MSReadValue(_port, _i2caddr, NXTSERVO_REG_S1_SPEED+_servo, 1, _out, _result) /** * Read NXTServo battery voltage value. * Read the mindsensors NXTServo device's battery voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTServo battery voltage. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTServoBatteryVoltage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTSERVO_REG_VOLTAGE, 1, _out, _result) /** * Set NXTServo servo motor speed. * Set the speed of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _speed The servo speed. (0..255) * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTServoSpeed(_port, _i2caddr, _servo, _speed, _result) __MSWriteToRegister(_port, _i2caddr, NXTSERVO_REG_S1_SPEED+_servo, _speed, _result) /** * Set NXTServo servo motor quick position. * Set the quick position of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _qpos The servo quick position. See \ref NXTServoQPos group. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTServoQuickPosition(_port, _i2caddr, _servo, _qpos, _result) __MSWriteToRegister(_port, _i2caddr, NXTSERVO_REG_S1_QPOS+_servo, _qpos, _result) /** * Set NXTServo servo motor position. * Set the position of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _pos The servo position. See \ref NXTServoPos group. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTServoPosition(_port, _i2caddr, _servo, _pos, _result) __MSWriteLEIntToRegister(_port, _i2caddr, _reg, _pos, _result) /** * Reset NXTServo properties. * Reset NXTServo device properties to factory defaults. * Initial position = 1500. Initial speed = 0. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoReset(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_RESET, _result) /** * Halt NXTServo macro. * Halt a macro executing on the NXTServo device. This command re-initializes * the macro environment. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoHaltMacro(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_HALT, _result) /** * Resume NXTServo macro. * Resume a macro executing on the NXTServo device. This command resumes * executing a macro where it was paused last, using the same environment. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoResumeMacro(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_RESUME, _result) /** * Pause NXTServo macro. * Pause a macro executing on the NXTServo device. This command will pause the * currently executing macro, and save the environment for subsequent resumption. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoPauseMacro(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_PAUSE, _result) /** * Initialize NXTServo servo properties. * Store the initial speed and position properties of the servo motor 'n'. * Current speed and position values of the nth servo is read from the * servo speed register and servo position register and written to permanent * memory. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _servo The servo number. See \ref NXTServoNumbers group. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoInit(_port, _i2caddr, _servo, _result) __NXTServoInit(_port, _i2caddr, _servo, _result) /** * Goto NXTServo macro address. * Run the macro found at the specified EEPROM macro address. This command * re-initializes the macro environment. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _macro The EEPROM macro address. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoGotoMacroAddress(_port, _i2caddr, _macro, _result) __NXTServoGotoMacroAddress(_port, _i2caddr, _macro, _result) /** * Edit NXTServo macro. * Put the NXTServo device into macro edit mode. This operation changes the * I2C address of the device to 0x40. Macros are written to EEPROM addresses * between 0x21 and 0xFF. Use \ref NXTServoQuitEdit to return the device to * its normal operation mode. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoEditMacro(_port, _i2caddr, _result) __NXTServoEditMacro(_port, _i2caddr, _result) /** * Quit NXTServo macro edit mode. * Stop editing NXTServo device macro EEPROM memory. Use \ref NXTServoEditMacro * to start editing a macro. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTServoQuitEdit(_port, _result) __MSWriteToRegister(_port, MS_ADDR_NXTSERVO_EM, NXTSERVO_EM_REG_CMD, NXTSERVO_EM_CMD_QUIT, _result) /** * Set NXTHID into ASCII data mode. * Set the NXTHID device into ASCII data mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTHIDAsciiMode(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_ASCII, _result) /** * Set NXTHID into direct data mode. * Set the NXTHID device into direct data mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTHIDDirectMode(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_DIRECT, _result) /** * Transmit NXTHID character. * Transmit a single character to a computer using the NXTHID device. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTHIDTransmit(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_TRANSMIT, _result) /** * Load NXTHID character. * Load a character into the NXTHID device. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _modifier The key modifier. * \param _character The character. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTHIDLoadCharacter(_port, _i2caddr, _modifier, _character, _result) __NXTHIDLoadCharacter(_port, _i2caddr, _modifier, _character, _result) /** * Reset NXTPowerMeter counters. * Reset the NXTPowerMeter counters back to zero. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTPowerMeterResetCounters(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTPM_CMD_RESET, _result) /** * Read NXTPowerMeter present current. * Read the mindsensors NXTPowerMeter device's present current value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter present current. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterPresentCurrent(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_CURRENT, 2, _out, _result) /** * Read NXTPowerMeter present voltage. * Read the mindsensors NXTPowerMeter device's present voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter present voltage. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterPresentVoltage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_VOLTAGE, 2, _out, _result) /** * Read NXTPowerMeter capacity used. * Read the mindsensors NXTPowerMeter device's capacity used since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter capacity used value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterCapacityUsed(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_CAPACITY, 2, _out, _result) /** * Read NXTPowerMeter present power. * Read the mindsensors NXTPowerMeter device's present power value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter present power value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterPresentPower(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_POWER, 2, _out, _result) /** * Read NXTPowerMeter total power consumed. * Read the mindsensors NXTPowerMeter device's total power consumed since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter total power consumed value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterTotalPowerConsumed(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_POWER, 4, _out, _result) /** * Read NXTPowerMeter maximum current. * Read the mindsensors NXTPowerMeter device's maximum current value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter maximum current value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterMaxCurrent(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_MAXCURRENT, 2, _out, _result) /** * Read NXTPowerMeter minimum current. * Read the mindsensors NXTPowerMeter device's minimum current value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter minimum current value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterMinCurrent(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_MINCURRENT, 2, _out, _result) /** * Read NXTPowerMeter maximum voltage. * Read the mindsensors NXTPowerMeter device's maximum voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter maximum voltage value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterMaxVoltage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_MAXVOLTAGE, 2, _out, _result) /** * Read NXTPowerMeter minimum voltage. * Read the mindsensors NXTPowerMeter device's minimum voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter minimum voltage value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterMinVoltage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_MINVOLTAGE, 2, _out, _result) /** * Read NXTPowerMeter elapsed time. * Read the mindsensors NXTPowerMeter device's elapsed time since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter elapsed time value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterElapsedTime(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_TIME, 4, _out, _result) /** * Read NXTPowerMeter error count. * Read the mindsensors NXTPowerMeter device's error count value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTPowerMeter error count value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTPowerMeterErrorCount(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTPM_REG_ERRORCOUNT, 2, _out, _result) /** * Powerdown NXTLineLeader device. * Put the NXTLineLeader to sleep so that it does not consume power when it is * not required. The device wakes up on its own when any I2C communication * happens or you can specifically wake it up by using the \ref NXTLineLeaderPowerUp * command. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderPowerDown(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_POWERDOWN, _result) /** * Powerup NXTLineLeader device. * Wake up the NXTLineLeader device so that it can be used. The device can be * put to sleep using the \ref NXTLineLeaderPowerDown command. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderPowerUp(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_POWERUP, _result) /** * Invert NXTLineLeader colors. * Invert color sensing so that the device can detect a white line on a * black background. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderInvert(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_INVERT, _result) /** * Reset NXTLineLeader color inversion. * Reset the NXTLineLeader color detection back to its default state (black * line on a white background). * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderReset(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_RESET, _result) /** * Take NXTLineLeader line snapshot. * Takes a snapshot of the line under the sensor and tracks that position in * subsequent tracking operations. This function also will set color inversion * if it sees a white line on a black background. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderSnapshot(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_SNAPSHOT, _result) /** * Calibrate NXTLineLeader white color. * Store calibration data for the white color. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderCalibrateWhite(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_WHITE, _result) /** * Calibrate NXTLineLeader black color. * Store calibration data for the black color. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define NXTLineLeaderCalibrateBlack(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_BLACK, _result) /** * Read NXTLineLeader steering. * Read the mindsensors NXTLineLeader device's steering value. This is the power * returned by the sensor to correct your course. Add this value to your left * motor and subtract it from your right motor. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTLineLeader steering value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTLineLeaderSteering(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTLL_REG_STEERING, 1, _out, _result) /** * Read NXTLineLeader average. * Read the mindsensors NXTLineLeader device's average value. The * average is a weighted average of the bits set to 1 based on the position. * The left most bit has a weight of 10, second bit has a weight of 20, and so * forth. When all 8 sensors are over a black surface the average will be 45. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTLineLeader average value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTLineLeaderAverage(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTLL_REG_AVERAGE, 1, _out, _result) /** * Read NXTLineLeader result. * Read the mindsensors NXTLineLeader device's result value. This is a single * byte showing the 8 sensor's readings. Each bit corresponding to the sensor * where the line is seen is set to 1, otherwise it is set to 0. * When all 8 sensors are over a black surface the result will be 255 (b11111111). * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _out The NXTLineLeader result value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define ReadNXTLineLeaderResult(_port, _i2caddr, _out, _result) __MSReadValue(_port, _i2caddr, NXTLL_REG_RESULT, 1, _out, _result) /** * Write NXTLineLeader setpoint. * Write a new setpoint value to the NXTLineLeader device. The Set Point is a * value you can ask sensor to maintain the average to. The default value is * 45, whereby the line is maintained in center of the sensor. If you need to * maintain line towards left of the sensor, set the Set Point to * a lower value (minimum: 10). If you need it to be towards on the right of the * sensor, set it to higher value (maximum: 80). Set point is also useful while * tracking an edge of dark and light areas. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new setpoint value (10..80). * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderSetpoint(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_SETPOINT, _value, _result) /** * Write NXTLineLeader Kp value. * Write a Kp value to the NXTLineLeader device. This value divided by PID * Factor for Kp is the Proportional value for the PID control. Suggested value * is 25 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Kp value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKpValue(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KP_VALUE, _value, _result) /** * Write NXTLineLeader Ki value. * Write a Ki value to the NXTLineLeader device. This value divided by PID * Factor for Ki is the Integral value for the PID control. Suggested value * is 0 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Ki value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKiValue(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KI_VALUE, _value, _result) /** * Write NXTLineLeader Kd value. * Write a Kd value to the NXTLineLeader device. This value divided by PID * Factor for Kd is the Derivative value for the PID control. Suggested value * is 8 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Kd value. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKdValue(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KD_VALUE, _value, _result) /** * Write NXTLineLeader Kp factor. * Write a Kp divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Kp value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Kp factor. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKpFactor(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KP_FACTOR, _value, _result) /** * Write NXTLineLeader Ki factor. * Write a Ki divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Ki value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Ki factor. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKiFactor(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KI_FACTOR, _value, _result) /** * Write NXTLineLeader Kd factor. * Write a Kd divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Kd value. * The port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The new Kd factor. * \param _result A status code indicating whether the operation completed successfully or not. * See \ref TCommLSCheckStatus for possible Result values. */ #define SetNXTLineLeaderKdFactor(_port, _i2caddr, _value, _result) __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KD_FACTOR, _value, _result) /** * Configure NRLink in 2400 baud mode. * Configure the mindsensors NRLink device in 2400 baud mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLink2400(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_2400, _result) /** * Configure NRLink in 4800 baud mode. * Configure the mindsensors NRLink device in 4800 baud mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLink4800(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_4800, _result) /** * Flush NRLink buffers. * Flush the mindsensors NRLink device buffers. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkFlush(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_FLUSH, _result) /** * Configure NRLink in IR long mode. * Configure the mindsensors NRLink device in IR long mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkIRLong(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_IR_LONG, _result) /** * Configure NRLink in IR short mode. * Configure the mindsensors NRLink device in IR short mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkIRShort(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_IR_SHORT, _result) /** * Configure NRLink in power function mode. * Configure the mindsensors NRLink device in power function mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkSetPF(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_PF, _result) /** * Configure NRLink in RCX mode. * Configure the mindsensors NRLink device in RCX mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkSetRCX(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_RCX, _result) /** * Configure NRLink in IR train mode. * Configure the mindsensors NRLink device in IR train mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkSetTrain(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_TRAIN, _result) /** * Configure NRLink in raw IR transmit mode. * Configure the mindsensors NRLink device in raw IR transmit mode. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _result The function call result. */ #define NRLinkTxRaw(_port, _i2caddr, _result) __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_TX_RAW, _result) /** * Read NRLink status. * Read the status of the mindsensors NRLink device. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _value The mindsensors NRLink status. * \param _result The function call result. */ #define ReadNRLinkStatus(_port, _i2caddr, _value, _result) __ReadNRLinkStatus(_port, _i2caddr, _value, _result) /** * Run NRLink macro. * Run the specified mindsensors NRLink device macro. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _macro The address of the macro to execute. * \param _result The function call result. */ #define RunNRLinkMacro(_port, _i2caddr, _macro, _result) __RunNRLinkMacro(_port, _i2caddr, _macro, _result) /** * Write data to NRLink. * Write data to the mindsensors NRLink device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _bytes A byte array containing the data to write. * \param _result The function call result. */ #define WriteNRLinkBytes(_port, _i2caddr, _bytes, _result) __WriteNRLinkBytes(_port, _i2caddr, _bytes, _result) /** * Read data from NRLink. * Read data from the mindsensors NRLink device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _bytes A byte array that will contain the data read from the device on output. * \param _result The function call result. */ #define ReadNRLinkBytes(_port, _i2caddr, _bytes, _result) __ReadNRLinkBytes(_port, _i2caddr, _bytes, _result) /** * MSIRTrain function. * Control an IR Train receiver set to the specified channel using the * mindsensors NRLink device. Valid function values are \ref TRAIN_FUNC_STOP, * \ref TRAIN_FUNC_INCR_SPEED, \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. * Valid channels are \ref TRAIN_CHANNEL_1 through \ref TRAIN_CHANNEL_3 and * \ref TRAIN_CHANNEL_ALL. The port must be configured as a Lowspeed port before * using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The IR Train channel. See \ref IRTrainChannels. * \param _func The IR Train function. See \ref IRTrainFuncs * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSIRTrain(_port, _i2caddr, _channel, _func, _result) \ __MSIRTrain(_port, _i2caddr, _channel, _func, FALSE, _result) /** * MSPFComboDirect function. * Execute a pair of Power Function motor commands on the specified channel * using the mindsensors NRLink device. Commands for outa and outb are * PF_CMD_STOP, PF_CMD_REV, PF_CMD_FWD, and \ref PF_CMD_BRAKE. Valid channels are * PF_CHANNEL_1 through PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _outa The Power Function command for output A. See \ref PFCmdConstants. * \param _outb The Power Function command for output B. See \ref PFCmdConstants. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFComboDirect(_port, _i2caddr, _channel, _outa, _outb, _result) \ __MSPFComboDirect(_port, _i2caddr, _channel, _outa, _outb, _result) /** * MSPFComboPWM function. * Control the speed of both outputs on a Power Function receiver set to the * specified channel using the mindsensors NRLink device. Valid output values * are \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _outa The Power Function PWM command for output A. See \ref PFPWMOptions. * \param _outb The Power Function PWM command for output B. See \ref PFPWMOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFComboPWM(_port, _i2caddr, _channel, _outa, _outb, _result) \ __MSPFComboPWM(_port, _i2caddr, _channel, _outa, _outb, _result) /** * MSPFRawOutput function. * Control a Power Function receiver set to the specified channel using the * mindsensors NRLink device. Build the raw data stream using the 3 nibbles * (4 bit values). The port must be configured as a Lowspeed port before using * this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _nibble0 The first raw data nibble. * \param _nibble1 The second raw data nibble. * \param _nibble2 The third raw data nibble. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFRawOutput(_port, _i2caddr, _nibble0, _nibble1, _nibble2, _result) \ __MSPFRawOutput(_port, _i2caddr, _nibble0, _nibble1, _nibble2, _result) /** * MSPFRepeat function. * Repeat sending the last Power Function command using the mindsensors * NRLink device. Specify the number of times to repeat the command and the * number of milliseconds of delay between each repetition. The port must be * configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _count The number of times to repeat the command. * \param _delay The number of milliseconds to delay between each repetition. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFRepeat(_port, _i2caddr, _count, _delay, _result) \ __MSPFRepeatLastCommand(_port, _i2caddr, _count, _delay, _result) /** * MSPFSingleOutputCST function. * Control a single output on a Power Function receiver set to the specified * channel using the mindsensors NRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are \ref PF_CST_CLEAR1_CLEAR2, * \ref PF_CST_SET1_CLEAR2, \ref PF_CST_CLEAR1_SET2, \ref PF_CST_SET1_SET2, * \ref PF_CST_INCREMENT_PWM, \ref PF_CST_DECREMENT_PWM, \ref PF_CST_FULL_FWD, * \ref PF_CST_FULL_REV, and \ref PF_CST_TOGGLE_DIR. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _func The Power Function CST function. See \ref PFCSTOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFSingleOutputCST(_port, _i2caddr, _channel, _out, _func, _result) \ __MSPFSingleOutput(_port, _i2caddr, _channel, _out, _func, TRUE, _result) /** * MSPFSingleOutputPWM function. * Control the speed of a single output on a Power Function receiver set to * the specified channel using the mindsensors NRLink device. Select the * desired output using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are * \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _func The Power Function PWM function. See \ref PFPWMOptions. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFSingleOutputPWM(_port, _i2caddr, _channel, _out, _func, _result) \ __MSPFSingleOutput(_port, _i2caddr, _channel, _out, _func, FALSE, _result) /** * MSPFSinglePin function. * Control a single pin on a Power Function receiver set to the specified * channel using the mindsensors NRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Select the desired pin using \ref PF_PIN_C1 or * \ref PF_PIN_C2. Valid functions are \ref PF_FUNC_NOCHANGE, \ref PF_FUNC_CLEAR, * \ref PF_FUNC_SET, and \ref PF_FUNC_TOGGLE. Valid channels are \ref PF_CHANNEL_1 through * \ref PF_CHANNEL_4. Specify whether the mode by passing true (continuous) or * false (timeout) as the final parameter. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _out The Power Function output. See \ref PFOutputs. * \param _pin The Power Function pin. See \ref PFPinConstants. * \param _func The Power Function single pin function. See \ref PFPinFuncs. * \param _cont Control whether the mode is continuous or timeout. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFSinglePin(_port, _i2caddr, _channel, _out, _pin, _func, _cont, _result) \ __MSPFSinglePin(_port, _i2caddr, _channel, _out, _pin, _func, _cont, _result) /** * MSPFTrain function. * Control both outputs on a Power Function receiver set to the specified * channel using the mindsensors NRLink device as if it were an IR Train * receiver. Valid function values are \ref TRAIN_FUNC_STOP, \ref TRAIN_FUNC_INCR_SPEED, * \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. Valid channels are * PF_CHANNEL_1 through PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. * \param _channel The Power Function channel. See \ref PFChannelConstants. * \param _func The Power Function train function. See \ref IRTrainFuncs. * \param _result The function call result. \ref NO_ERR or \ref CommandCommErrors. */ #define MSPFTrain(_port, _i2caddr, _channel, _func, _result) \ __MSIRTrain(_port, _i2caddr, _channel, _func, TRUE, _result) /** * MSRCXSetIRLinkPort function. * Set the global port in advance of using the MSRCX* and MSScout* API * functions for sending RCX and Scout messages over the mindsensors NRLink * device. The port must be configured as a Lowspeed port before using any of * the mindsensors RCX and Scout NRLink functions. * * \param _port The sensor port. See \ref NBCInputPortConstants. * \param _i2caddr The sensor I2C address. See sensor documentation for this value. */ #define MSRCXSetNRLinkPort(_port, _i2caddr) __MSRCXSetNRLink(_port, _i2caddr) /** * MSRCXBatteryLevel function. * Send the BatteryLevel command to an RCX to read the current battery level. * * \param _result The RCX battery level. */ #define MSRCXBatteryLevel(_result) __MSRCXBatteryLevel(_result) /** * MSRCXPoll function. * Send the Poll command to an RCX to read a signed 2-byte value at the * specified source and value combination. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. * \param _result The value read from the specified port and value. */ #define MSRCXPoll(_src, _value, _result) __MSRCXPoll(_src, _value, _result) /** * MSRCXPollMemory function. * Send the PollMemory command to an RCX. * * \param _memaddress The RCX memory address. * \param _result The value read from the specified address. */ #define MSRCXPollMemory(_memaddress, _result) __MSRCXPollMemory(_memaddress, _result) /** * MSRCXAbsVar function. * Send the AbsVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXAbsVar(_varnum, _src, _value) __MSRCXVarOp(RCX_AbsVarOp, _varnum, _src, _value) /** * MSRCXAddToDatalog function. * Send the AddToDatalog command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXAddToDatalog(_src, _value) __MSRCXAddToDatalog(_src, _value) /** * MSRCXAndVar function. * Send the AndVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXAndVar(_varnum, _src, _value) __MSRCXVarOp(RCX_AndVarOp, _varnum, _src, _value) /** * MSRCXBoot function. * Send the Boot command to an RCX. */ #define MSRCXBoot() __MSRCXBoot() /** * MSRCXCalibrateEvent function. * Send the CalibrateEvent command to an RCX. * * \param _evt The event number. * \param _low The low threshold. * \param _hi The high threshold. * \param _hyst The hysterisis value. */ #define MSRCXCalibrateEvent(_evt, _low, _hi, _hyst) __MSRCXCalibrateEvent(_evt, _low, _hi, _hyst) /** * MSRCXClearAllEvents function. * Send the ClearAllEvents command to an RCX. */ #define MSRCXClearAllEvents() __MSRCXOpNoArgs(RCX_ClearAllEventsOp) /** * MSRCXClearCounter function. * Send the ClearCounter command to an RCX. * * \param _counter The counter to clear. */ #define MSRCXClearCounter(_counter) __MSRCXClearCounter(_counter) /** * MSRCXClearMsg function. * Send the ClearMsg command to an RCX. */ #define MSRCXClearMsg() __MSRCXOpNoArgs(RCX_ClearMsgOp) /** * MSRCXClearSensor function. * Send the ClearSensor command to an RCX. * * \param _port The RCX port number. */ #define MSRCXClearSensor(_port) __MSRCXClearSensor(_port) /** * MSRCXClearSound function. * Send the ClearSound command to an RCX. */ #define MSRCXClearSound() __MSRCXOpNoArgs(RCX_ClearSoundOp) /** * MSRCXClearTimer function. * Send the ClearTimer command to an RCX. * * \param _timer The timer to clear. */ #define MSRCXClearTimer(_timer) __MSRCXClearTimer(_timer) /** * MSRCXCreateDatalog function. * Send the CreateDatalog command to an RCX. * * \param _size The new datalog size. */ #define MSRCXCreateDatalog(_size) __MSRCXCreateDatalog(_size) /** * MSRCXDecCounter function. * Send the DecCounter command to an RCX. * * \param _counter The counter to decrement. */ #define MSRCXDecCounter(_counter) __MSRCXDecCounter(_counter) /** * MSRCXDeleteSub function. * Send the DeleteSub command to an RCX. * * \param _s The subroutine number to delete. */ #define MSRCXDeleteSub(_s) __MSRCXDeleteSub(_s) /** * MSRCXDeleteSubs function. * Send the DeleteSubs command to an RCX. */ #define MSRCXDeleteSubs() __MSRCXOpNoArgs(RCX_DeleteSubsOp) /** * MSRCXDeleteTask function. * Send the DeleteTask command to an RCX. * * \param _t The task number to delete. */ #define MSRCXDeleteTask(_t) __MSRCXDeleteTask(_t) /** * MSRCXDeleteTasks function. * Send the DeleteTasks command to an RCX. */ #define MSRCXDeleteTasks() __MSRCXOpNoArgs(RCX_DeleteTasksOp) /** * MSRCXDisableOutput function. * Send the DisableOutput command to an RCX. * * \param _outputs The RCX output(s) to disable. See \ref RCXOutputConstants. */ #define MSRCXDisableOutput(_outputs) __MSRCXSetGlobalOutput(_outputs, RCX_OUT_OFF) /** * MSRCXDivVar function. * Send the DivVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXDivVar(_varnum, _src, _value) __MSRCXVarOp(RCX_DivVarOp, _varnum, _src, _value) /** * MSRCXEnableOutput function. * Send the EnableOutput command to an RCX. * * \param _outputs The RCX output(s) to enable. See \ref RCXOutputConstants. */ #define MSRCXEnableOutput(_outputs) __MSRCXSetGlobalOutput(_outputs, RCX_OUT_ON) /** * MSRCXEvent function. * Send the Event command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXEvent(_src, _value) __MSRCXEvent(_src, _value) /** * MSRCXFloat function. * Send commands to an RCX to float the specified outputs. * * \param _outputs The RCX output(s) to float. See \ref RCXOutputConstants. */ #define MSRCXFloat(_outputs) __MSRCXSetOutput(_outputs, RCX_OUT_FLOAT) /** * MSRCXFwd function. * Send commands to an RCX to set the specified outputs to the forward direction. * * \param _outputs The RCX output(s) to set forward. See \ref RCXOutputConstants. */ #define MSRCXFwd(_outputs) __MSRCXSetDirection(_outputs, RCX_OUT_FWD) /** * MSRCXIncCounter function. * Send the IncCounter command to an RCX. * * \param _counter The counter to increment. */ #define MSRCXIncCounter(_counter) __MSRCXIncCounter(_counter) /** * MSRCXInvertOutput function. * Send the InvertOutput command to an RCX. * * \param _outputs The RCX output(s) to invert. See \ref RCXOutputConstants. */ #define MSRCXInvertOutput(_outputs) __MSRCXSetGlobalDirection(_outputs, RCX_OUT_REV) /** * MSRCXMulVar function. * Send the MulVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXMulVar(_varnum, _src, _value) __MSRCXVarOp(RCX_MulVarOp, _varnum, _src, _value) /** * MSRCXMuteSound function. * Send the MuteSound command to an RCX. */ #define MSRCXMuteSound() __MSRCXOpNoArgs(RCX_MuteSoundOp) /** * MSRCXObvertOutput function. * Send the ObvertOutput command to an RCX. * * \param _outputs The RCX output(s) to obvert. See \ref RCXOutputConstants. */ #define MSRCXObvertOutput(_outputs) __MSRCXSetGlobalDirection(_outputs, RCX_OUT_FWD) /** * MSRCXOff function. * Send commands to an RCX to turn off the specified outputs. * * \param _outputs The RCX output(s) to turn off. See \ref RCXOutputConstants. */ #define MSRCXOff(_outputs) __MSRCXSetOutput(_outputs, RCX_OUT_OFF) /** * MSRCXOn function. * Send commands to an RCX to turn on the specified outputs. * * \param _outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. */ #define MSRCXOn(_outputs) __MSRCXSetOutput(_outputs, RCX_OUT_ON) /** * MSRCXOnFor function. * Send commands to an RCX to turn on the specified outputs in the forward * direction for the specified duration. * * \param _outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. * \param _ms The number of milliseconds to leave the outputs on */ #define MSRCXOnFor(_outputs, _ms) __MSRCXOnFor(_outputs, _ms) /** * MSRCXOnFwd function. * Send commands to an RCX to turn on the specified outputs in the forward * direction. * * \param _outputs The RCX output(s) to turn on in the forward direction. See \ref RCXOutputConstants. */ #define MSRCXOnFwd(_outputs) __MSRCXOnFwd(_outputs) /** * MSRCXOnRev function. * Send commands to an RCX to turn on the specified outputs in the reverse direction. * * \param _outputs The RCX output(s) to turn on in the reverse direction. See \ref RCXOutputConstants. */ #define MSRCXOnRev(_outputs) __MSRCXOnRev(_outputs) /** * MSRCXOrVar function. * Send the OrVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXOrVar(_varnum, _src, _value) __MSRCXVarOp(RCX_OrVarOp, _varnum, _src, _value) /** * MSRCXPBTurnOff function. * Send the PBTurnOff command to an RCX. */ #define MSRCXPBTurnOff() __MSRCXOpNoArgs(RCX_PBTurnOffOp) /** * MSRCXPing function. * Send the Ping command to an RCX. */ #define MSRCXPing() __MSRCXOpNoArgs(RCX_PingOp) /** * MSRCXPlaySound function. * Send the PlaySound command to an RCX. * * \param _snd The sound number to play. */ #define MSRCXPlaySound(_snd) __MSRCXPlaySound(_snd) /** * MSRCXPlayTone function. * Send the PlayTone command to an RCX. * * \param _freq The frequency of the tone to play. * \param _duration The duration of the tone to play. */ #define MSRCXPlayTone(_freq, _duration) __MSRCXPlayTone(_freq, _duration) /** * MSRCXPlayToneVar function. * Send the PlayToneVar command to an RCX. * * \param _varnum The variable containing the tone frequency to play. * \param _duration The duration of the tone to play. */ #define MSRCXPlayToneVar(_varnum, _duration) __MSRCXPlayToneVar(_varnum, _duration) /** * MSRCXRemote function. * Send the Remote command to an RCX. * * \param _cmd The RCX IR remote command to send. See \ref RCXRemoteConstants. */ #define MSRCXRemote(_cmd) __MSRCXRemote(_cmd) /** * MSRCXReset function. * Send the Reset command to an RCX. */ #define MSRCXReset() __MSRCXReset() /** * MSRCXRev function. * Send commands to an RCX to set the specified outputs to the reverse direction. * * \param _outputs The RCX output(s) to reverse direction. See \ref RCXOutputConstants. */ #define MSRCXRev(_outputs) __MSRCXSetDirection(_outputs, RCX_OUT_REV) /** * MSRCXSelectDisplay function. * Send the SelectDisplay command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSelectDisplay(_src, _value) __MSRCXSelectDisplay(_src, _value) /** * MSRCXSelectProgram function. * Send the SelectProgram command to an RCX. * * \param _prog The program number to select. */ #define MSRCXSelectProgram(_prog) __MSRCXSelectProgram(_prog) /** * MSRCXSendSerial function. * Send the SendSerial command to an RCX. * * \param _first The first byte address. * \param _count The number of bytes to send. */ #define MSRCXSendSerial(_first, _count) __MSRCXSendSerial(_first, _count) /** * MSRCXSet function. * Send the Set command to an RCX. * * \param _dstsrc The RCX destination source. See \ref RCXSourceConstants. * \param _dstval The RCX destination value. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSet(_dstsrc, _dstval, _src, _value) __MSRCXSet(_dstsrc, _dstval, _src, _value) /** * MSRCXSetDirection function. * Send the SetDirection command to an RCX to configure the direction of the specified outputs. * * \param _outputs The RCX output(s) to set direction. See \ref RCXOutputConstants. * \param _dir The RCX output direction. See \ref RCXOutputDirection. */ #define MSRCXSetDirection(_outputs, _dir) __MSRCXSetDirection(_outputs, _dir) /** * MSRCXSetEvent function. * Send the SetEvent command to an RCX. * * \param _evt The event number to set. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _type The event type. */ #define MSRCXSetEvent(_evt, _src, _type) __MSRCXSetEvent(_evt, _src, _type) /** * MSRCXSetGlobalDirection function. * Send the SetGlobalDirection command to an RCX. * * \param _outputs The RCX output(s) to set global direction. See \ref RCXOutputConstants. * \param _dir The RCX output direction. See \ref RCXOutputDirection. */ #define MSRCXSetGlobalDirection(_outputs, _dir) __MSRCXSetGlobalDirection(_outputs, _dir) /** * MSRCXSetGlobalOutput function. * Send the SetGlobalOutput command to an RCX. * * \param _outputs The RCX output(s) to set global mode. See \ref RCXOutputConstants. * \param _mode The RCX output mode. See \ref RCXOutputMode. */ #define MSRCXSetGlobalOutput(_outputs, _mode) __MSRCXSetGlobalOutput(_outputs, _mode) /** * MSRCXSetMaxPower function. * Send the SetMaxPower command to an RCX. * * \param _outputs The RCX output(s) to set max power. See \ref RCXOutputConstants. * \param _pwrsrc The RCX source. See \ref RCXSourceConstants. * \param _pwrval The RCX value. */ #define MSRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) __MSRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) /** * MSRCXSetMessage function. * Send the SetMessage command to an RCX. * * \param _msg The numeric message to send. */ #define MSRCXSetMessage(_msg) __MSRCXSetMessage(_msg) /** * MSRCXSetOutput function. * Send the SetOutput command to an RCX to configure the mode of the specified outputs * * \param _outputs The RCX output(s) to set mode. See \ref RCXOutputConstants. * \param _mode The RCX output mode. See \ref RCXOutputMode. */ #define MSRCXSetOutput(_outputs, _mode) __MSRCXSetOutput(_outputs, _mode) /** * MSRCXSetPower function. * Send the SetPower command to an RCX to configure the power level of the specified outputs. * * \param _outputs The RCX output(s) to set power. See \ref RCXOutputConstants. * \param _pwrsrc The RCX source. See \ref RCXSourceConstants. * \param _pwrval The RCX value. */ #define MSRCXSetPower(_outputs, _pwrsrc, _pwrval) __MSRCXSetPower(_outputs, _pwrsrc, _pwrval) /** * MSRCXSetPriority function. * Send the SetPriority command to an RCX. * * \param _p The new task priority. */ #define MSRCXSetPriority(_p) __MSRCXSetPriority(_p) /** * MSRCXSetSensorMode function. * Send the SetSensorMode command to an RCX. * * \param _port The RCX sensor port. * \param _mode The RCX sensor mode. */ #define MSRCXSetSensorMode(_port, _mode) __MSRCXSetSensorMode(_port, _mode) /** * MSRCXSetSensorType function. * Send the SetSensorType command to an RCX. * * \param _port The RCX sensor port. * \param _type The RCX sensor type. */ #define MSRCXSetSensorType(_port, _type) __MSRCXSetSensorType(_port, _type) /** * MSRCXSetSleepTime function. * Send the SetSleepTime command to an RCX. * * \param _t The new sleep time value. */ #define MSRCXSetSleepTime(_t) __MSRCXSetSleepTime(_t) /** * MSRCXSetTxPower function. * Send the SetTxPower command to an RCX. * * \param _pwr The IR transmit power level. */ #define MSRCXSetTxPower(_pwr) __MSRCXSetTxPower(_pwr) /** * MSRCXSetUserDisplay function. * Send the SetUserDisplay command to an RCX. * * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. * \param _precision The number of digits of precision. */ #define MSRCXSetUserDisplay(_src, _value, _precision) __MSRCXSetUserDisplay(_src, _value, _precision) /** * MSRCXSetVar function. * Send the SetVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSetVar(_varnum, _src, _value) __MSRCXVarOp(RCX_SetVarOp, _varnum, _src, _value) /** * MSRCXSetWatch function. * Send the SetWatch command to an RCX. * * \param _hours The new watch time hours value. * \param _minutes The new watch time minutes value. */ #define MSRCXSetWatch(_hours, _minutes) __MSRCXSetWatch(_hours, _minutes) /** * MSRCXSgnVar function. * Send the SgnVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSgnVar(_varnum, _src, _value) __MSRCXVarOp(RCX_SgnVarOp, _varnum, _src, _value) /** * MSRCXStartTask function. * Send the StartTask command to an RCX. * * \param _t The task number to start. */ #define MSRCXStartTask(_t) __MSRCXStartTask(_t) /** * MSRCXStopAllTasks function. * Send the StopAllTasks command to an RCX. */ #define MSRCXStopAllTasks() __MSRCXOpNoArgs(RCX_StopAllTasksOp) /** * MSRCXStopTask function. * Send the StopTask command to an RCX. * * \param _t The task number to stop. */ #define MSRCXStopTask(_t) __MSRCXStopTask(_t) /** * MSRCXSubVar function. * Send the SubVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSubVar(_varnum, _src, _value) __MSRCXVarOp(RCX_SubVarOp, _varnum, _src, _value) /** * MSRCXSumVar function. * Send the SumVar command to an RCX. * * \param _varnum The variable number to change. * \param _src The RCX source. See \ref RCXSourceConstants. * \param _value The RCX value. */ #define MSRCXSumVar(_varnum, _src, _value) __MSRCXVarOp(RCX_SumVarOp, _varnum, _src, _value) /** * MSRCXToggle function. * Send commands to an RCX to toggle the direction of the specified outputs. * * \param _outputs The RCX output(s) to toggle. See \ref RCXOutputConstants. */ #define MSRCXToggle(_outputs) __MSRCXSetDirection(_outputs, RCX_OUT_TOGGLE) /** * MSRCXUnlock function. * Send the Unlock command to an RCX. */ #define MSRCXUnlock() __MSRCXUnlock() /** * MSRCXUnmuteSound function. * Send the UnmuteSound command to an RCX. */ #define MSRCXUnmuteSound() __MSRCXOpNoArgs(RCX_UnmuteSoundOp) /** * MSScoutCalibrateSensor function. * Send the CalibrateSensor command to a Scout. */ #define MSScoutCalibrateSensor() __MSRCXOpNoArgs(RCX_LSCalibrateOp) /** * MSScoutMuteSound function. * Send the MuteSound command to a Scout. */ #define MSScoutMuteSound() __MSScoutMuteSound() /** * MSScoutSelectSounds function. * Send the SelectSounds command to a Scout. * * \param _grp The Scout sound group to select. */ #define MSScoutSelectSounds(_grp) __MSScoutSelectSounds(_grp) /** * MSScoutSendVLL function. * Send the SendVLL command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSendVLL(_src, _value) __MSScoutSendVLL(_src, _value) /** * MSScoutSetCounterLimit function. * Send the SetCounterLimit command to a Scout. * * \param _ctr The counter for which to set the limit. * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetCounterLimit(_ctr, _src, _value) __MSScoutSetCounterLimit(_ctr, _src, _value) /** * MSScoutSetEventFeedback function. * Send the SetEventFeedback command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetEventFeedback(_src, _value) __MSScoutSetEventFeedback(_src, _value) /** * MSScoutSetLight function. * Send the SetLight command to a Scout. * * \param _x Set the light on or off using this value. See \ref ScoutLightConstants. */ #define MSScoutSetLight(_x) __MSScoutSetLight(_x) /** * MSScoutSetScoutMode function. * Send the SetScoutMode command to a Scout. * * \param _mode Set the scout mode. See \ref ScoutModeConstants. */ #define MSScoutSetScoutMode(_mode) __MSScoutSetScoutMode(_mode) /** * MSScoutSetScoutRules function. * Send the SetScoutRules command to a Scout. * * \param _m Scout motion rule. See \ref ScoutMotionRuleConstants. * \param _t Scout touch rule. See \ref ScoutTouchRuleConstants. * \param _l Scout light rule. See \ref ScoutLightRuleConstants. * \param _tm Scout transmit rule. See \ref ScoutTransmitRuleConstants. * \param _fx Scout special effects rule. See \ref ScoutSpecialEffectConstants. */ #define MSScoutSetScoutRules(_m, _t, _l, _tm, _fx) __MSScoutSetScoutRules(_m, _t, _l, _tm, _fx) /** * MSScoutSetSensorClickTime function. * Send the SetSensorClickTime command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetSensorClickTime(_src, _value) __MSScoutSetSensorClickTime(_src, _value) /** * MSScoutSetSensorHysteresis function. * Send the SetSensorHysteresis command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetSensorHysteresis(_src, _value) __MSScoutSetSensorHysteresis(_src, _value) /** * MSScoutSetSensorLowerLimit function. * Send the SetSensorLowerLimit command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetSensorLowerLimit(_src, _value) __MSScoutSetSensorLowerLimit(_src, _value) /** * MSScoutSetSensorUpperLimit function. * Send the SetSensorUpperLimit command to a Scout. * * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetSensorUpperLimit(_src, _value) __MSScoutSetSensorUpperLimit(_src, _value) /** * MSScoutSetTimerLimit function. * Send the SetTimerLimit command to a Scout. * * \param _tmr The timer for which to set a limit. * \param _src The Scout source. See \ref RCXSourceConstants. * \param _value The Scout value. */ #define MSScoutSetTimerLimit(_tmr, _src, _value) __MSScoutSetTimerLimit(_tmr, _src, _value) /** * MSScoutUnmuteSound function. * Send the UnmuteSound command to a Scout. */ #define MSScoutUnmuteSound() __MSScoutUnmuteSound() /** @} */ // end of MindSensorsAPI group /** @addtogroup CodatexAPI * @{ */ // Codatex RFID functions /** * RFIDInit function. * Initialize the Codatex RFID sensor. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _result The boolean function call result. */ #define RFIDInit(_port, _result) __RFIDInit(_port, _result) /** * RFIDMode function. * Configure the Codatex RFID sensor mode. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _mode The RFID sensor mode. See the \ref CTRFIDModeConstants group. * \param _result The boolean function call result. */ #define RFIDMode(_port, _mode, _result) __RFIDMode(_port, _mode, _result) /** * RFIDStatus function. * Read the Codatex RFID sensor status. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _result The RFID sensor status. */ #define RFIDStatus(_port, _result) __RFIDStatus(_port, _result) /** * RFIDRead function. * Read the Codatex RFID sensor value. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _output The five bytes of RFID data. * \param _result The boolean function call result. */ #define RFIDRead(_port, _output, _result) __RFIDRead(_port, _output, _result) /** * RFIDStop function. * Stop the Codatex RFID sensor. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _result The boolean function call result. */ #define RFIDStop(_port, _result) __RFIDStop(_port, _result) /** * RFIDReadSingle function. * Set the Codatex RFID sensor into single mode and read the RFID data. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _output The five bytes of RFID data. * \param _result The boolean function call result. */ #define RFIDReadSingle(_port, _output, _result) __RFIDReadSingle(_port, _output, _result) /** * RFIDReadContinuous function. * Set the Codatex RFID sensor into continuous mode, if necessary, and read * the RFID data. * * \param _port The port to which the Codatex RFID sensor is attached. See the * \ref NBCInputPortConstants group. You may use a constant or a variable. * \param _output The five bytes of RFID data. * \param _result The boolean function call result. */ #define RFIDReadContinuous(_port, _output, _result) __RFIDReadContinuous(_port, _output, _result) /** @} */ // end of CodatexAPI group /** @} */ // end of ThirdPartyDevices group /** @addtogroup GraphicsLibrary * @{ */ //------------------------------------------------------------------------------ // File : nbcGL.nbc // Description : Data and subroutines for a very simple 3D engine. // Programmed by : Arno van der Vegt, legoasimo@gmail.com //------------------------------------------------------------------------------ /** * Initialize graphics library. * Setup all the necessary data for the graphics library to function. Call this * function before any other graphics library routine. */ #define glInit() __glInit() /** * Set graphics library options. * Adjust graphic library settings for circle size and cull mode. * * \param _glType The setting type. See \ref GLConstantsSettings. * \param _glValue The setting value. For culling modes see \ref GLConstantsCullMode. */ #define glSet(_glType, _glValue) __glSet(_glType, _glValue) /** * Begin defining an object. * Start the process of defining a graphics library object using low level * functions such as \ref glBegin, \ref glAddVertex, and \ref glEnd. * * \param _glObjId The object index of the new object being created. */ #define glBeginObject(_glObjId) __glBeginObject(_glObjId) /** * Stop defining an object. * Finish the process of defining a graphics library object. Call this function * after you have completed the object definition. */ #define glEndObject() __glEndObject() /** * Perform an object action. * Execute the specified action on the specified object. * * \param _glObjectId The object id. * \param _glAction The action to perform on the object. See \ref GLConstantsActions. * \param _glValue The setting value. */ #define glObjectAction(_glObjectId, _glAction, _glValue) __glObjectAction(_glObjectId, _glAction, _glValue) /** * Add a vertex to an object. * Add a vertex to an object currently being defined. This function should * only be used between \ref glBegin and \ref glEnd which are themselves * nested within a \ref glBeginObject and \ref glEndObject pair. * * \param _glX The X axis coordinate. * \param _glY The Y axis coordinate. * \param _glZ The Z axis coordinate. */ #define glAddVertex(_glX, _glY, _glZ) __glAddVertex(_glX, _glY, _glZ) /** * Begin a new polygon for the current object. * Start defining a polygon surface for the current graphics object using * the specified begin mode. * * \param _glBeginMode The desired mode. See \ref GLConstantsBeginModes. */ #define glBegin(_glBeginMode) __glBegin(_glBeginMode) /** * Finish a polygon for the current object. * Stop defining a polgyon surface for the current graphics object. */ #define glEnd() __glEnd() /** * Begin a new render. * Start the process of rendering the existing graphic objects. */ #define glBeginRender() __glBeginRender() /** * Call a graphic object. * Tell the graphics library that you want it to include the specified * object in the render. * * \param _glObjectId The desired object id. */ #define glCallObject(_glObjectId) __glCallObject(_glObjectId) /** * Finish the current render. * Rotate the vertex list, clear the screen, and draw the rendered objects * to the LCD. */ #define glFinishRender() __glFinishRender() /** * Set the X axis angle. * Set the X axis angle to the specified value. * * \param _glValue The new X axis angle. */ #define glSetAngleX(_glValue) __glSetAngleX(_glValue) /** * Add to the X axis angle. * Add the specified value to the existing X axis angle. * * \param _glValue The value to add to the X axis angle. */ #define glAddToAngleX(_glValue) __glAddToAngleX(_glValue) /** * Set the Y axis angle. * Set the Y axis angle to the specified value. * * \param _glValue The new Y axis angle. */ #define glSetAngleY(_glValue) __glSetAngleY(_glValue) /** * Add to the Y axis angle. * Add the specified value to the existing Y axis angle. * * \param _glValue The value to add to the Y axis angle. */ #define glAddToAngleY(_glValue) __glAddToAngleY(_glValue) /** * Set the Z axis angle. * Set the Z axis angle to the specified value. * * \param _glValue The new Z axis angle. */ #define glSetAngleZ(_glValue) __glSetAngleZ(_glValue) /** * Add to the Z axis angle. * Add the specified value to the existing Z axis angle. * * \param _glValue The value to add to the Z axis angle. */ #define glAddToAngleZ(_glValue) __glAddToAngleZ(_glValue) /** * Table-based sine scaled by 32768. * Return the sine of the specified angle in degrees. The result is scaled * by 32768. * * \param _glAngle The angle in degrees. * \param _glResult The sine value scaled by 32768. */ #define glSin32768(_glAngle, _glResult) __glSin32768(_glAngle, _glResult) /** * Table-based cosine scaled by 32768. * Return the cosine of the specified angle in degrees. The result is scaled * by 32768. * * \param _glAngle The angle in degrees. * \param _glResult The cosine value scaled by 32768. */ #define glCos32768(_glAngle, _glResult) __glCos32768(_glAngle, _glResult) /** * Create a 3D box. * Define a 3D box using the specified begin mode for all faces. The center * of the box is at the origin of the XYZ axis with width, height, and depth * specified via the glSizeX, glSizeY, and glSizeZ parameters. * * \param _glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param _glSizeX The X axis size (width). * \param _glSizeY The Y axis size (height). * \param _glSizeZ The Z axis size (depth). * \param _glObjId The object ID of the new object. */ #define glBox(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glObjId) __glBox(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glObjId) /** * Create a 3D cube. * Define a 3D cube using the specified begin mode for all faces. The center * of the box is at the origin of the XYZ axis with equal width, height, and depth * specified via the glSize parameter. * * \param _glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param _glSize The cube's width, height, and depth. * \param _glObjId The object ID of the new object. */ #define glCube(_glMode, _glSize, _glObjId) __glBox(_glMode, _glSize, _glSize, _glSize, _glObjId) /** * Create a 3D pyramid. * Define a 3D pyramid using the specified begin mode for all faces. The center * of the pyramid is at the origin of the XYZ axis with width, height, and depth * specified via the glSizeX, glSizeY, and glSizeZ parameters. * * \param _glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param _glSizeX The X axis size (width). * \param _glSizeY The Y axis size (height). * \param _glSizeZ The Z axis size (depth). * \param _glObjId The object ID of the new object. */ #define glPyramid(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glObjId) __glPyramid(_glMode, _glSizeX, _glSizeY, _glSizeZ, _glObjId) /** @} */ // end of GraphicsLibrary group #endif // NXTDEFS__H NXT/nbcwin32.mak0000644000175000017500000000267111537752673013254 0ustar slavkoslavkoPROGRAMS = nbc.exe VER = 1.2.1.r4 DOBJECTS=uNXTClasses.o uPreprocess.o Parser10.o P10Build.o uNXCComp.o uRPGComp.o uRIC.o uRICComp.o uNBCCommon.o uNXTConstants.o uNBCInterface.o nbc.dpr DEFAULT_INCLUDE_DIR=. all:: $(DOBJECTS) $(PROGRAMS) clean:: rm -f *.o *.ppu *.rst *.compiled ../*.o ../bricktools/*.o nbc_preproc.inc realclean:: clean rm -f $(PROGRAMS) mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas PFLAGS=-S2cdghi -dRELEASE -OG1 -gl -vewnhi -l -Fu../ -Fu. -Fu../bricktools -dCAN_DOWNLOAD # Win32 PTOOLPREFIX=C:/lazarus/fpc/2.2.2/bin/i386-win32/ PPC=$(PTOOLPREFIX)fpc # how to link executable nbc.exe: nbc.dpr nbc_preproc.inc $(PPC) $(PFLAGS) $< -o$@ strip $@ # how to compile pas source %.o: %.pas mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas $(PPC) $(PFLAGS) $< -o$@ # how to create the include file nbc_preproc.inc: echo '// '$@ > $@ echo 'const' >> $@ echo ' DEFAULT_INCLUDE_DIR = '\'$(DEFAULT_INCLUDE_DIR)\'';' >> $@ echo ' COMPILATION_TIMESTAMP = '\'`date`\'';' >> $@ # how to create the mkdata utility mkdata.exe: mkdata.dpr $(PPC) $(PFLAGS) $< -o$@ strip $@ # how to create NBCCommonData.pas NBCCommonData.pas: NBCCommon.h ./mkdata.exe $< $@ nbc_common_data # how to create NXTDefsData.pas NXTDefsData.pas: NXTDefs.h ./mkdata.exe $< $@ nxt_defs_data # how to create NXCDefsData.pas NXCDefsData.pas: NXCDefs.h ./mkdata.exe $< $@ nxc_defs_data NXT/mkdata.cfg0000644000175000017500000000065211537752673013054 0ustar slavkoslavko-$A8 -$B- -$C+ -$D+ -$E- -$F- -$G+ -$H+ -$I+ -$J- -$K- -$L+ -$M- -$N+ -$O+ -$P+ -$Q- -$R- -$S- -$T- -$U- -$V+ -$W- -$X+ -$YD -$Z1 -cg -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -H+ -W+ -M -$M16384,1048576 -K$00400000 -LE"c:\win32apps\borland\delphi7\Projects\Bpl" -LN"c:\win32apps\borland\delphi7\Projects\Bpl" -w-UNSAFE_TYPE -w-UNSAFE_CODE -w-UNSAFE_CAST NXT/mkdata.dof0000644000175000017500000000610011537752673013057 0ustar slavkoslavko[FileVersion] Version=7.0 [Compiler] A=8 B=0 C=1 D=1 E=0 F=0 G=1 H=1 I=1 J=0 K=0 L=1 M=0 N=1 O=1 P=1 Q=0 R=0 S=0 T=0 U=0 V=1 W=0 X=1 Y=1 Z=1 ShowHints=1 ShowWarnings=1 UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; NamespacePrefix= SymbolDeprecated=1 SymbolLibrary=1 SymbolPlatform=1 UnitLibrary=1 UnitPlatform=1 UnitDeprecated=1 HResultCompat=1 HidingMember=1 HiddenVirtual=1 Garbage=1 BoundsError=1 ZeroNilCompat=1 StringConstTruncated=1 ForLoopVarVarPar=1 TypedConstVarPar=1 AsgToTypedConst=1 CaseLabelRange=1 ForVariable=1 ConstructingAbstract=1 ComparisonFalse=1 ComparisonTrue=1 ComparingSignedUnsigned=1 CombiningSignedUnsigned=1 UnsupportedConstruct=1 FileOpen=1 FileOpenUnitSrc=1 BadGlobalSymbol=1 DuplicateConstructorDestructor=1 InvalidDirective=1 PackageNoLink=1 PackageThreadVar=1 ImplicitImport=1 HPPEMITIgnored=1 NoRetVal=1 UseBeforeDef=1 ForLoopVarUndef=1 UnitNameMismatch=1 NoCFGFileFound=1 MessageDirective=1 ImplicitVariants=1 UnicodeToLocale=1 LocaleToUnicode=1 ImagebaseMultiple=1 SuspiciousTypecast=1 PrivatePropAccessor=1 UnsafeType=0 UnsafeCode=0 UnsafeCast=0 [Linker] MapFile=0 OutputObjs=0 ConsoleApp=1 DebugInfo=0 RemoteSymbols=0 MinStackSize=16384 MaxStackSize=1048576 ImageBase=4194304 ExeDescription= [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath= Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;vcldb;soaprtl;VclSmp;inetdb;bdertl;vcldbx;adortl;teeui;teedb;tee;dss;vclactnband;vclshlctrls;O217_R70;O217BR70;SynEdit_D7;ComDrv32;cxLibraryVCLD7;dxThemeD7;cxEditorsVCLD7;cxDataD7;cxExtEditorsVCLD7;cxPageControlVCLD7;cxGridVCLD7;M103_r70;S201DR70;BricxCCSyn_D7;dxmdsD7;dxNavBarD7;cxExportVCLD7;vcl7cr10;TCSComp_65 Conditionals= DebugSourceDirs= UsePackages=0 [Parameters] RunParams=NBCCommon.h NBCCommonData.pas nbc_common_data HostApplication= Launcher= UseLauncher=0 DebugCWD= [Language] ActiveLang= ProjectLang= RootDir=C:\winapps\Borland\Delphi7\Bin\ [Version Info] IncludeVerInfo=0 AutoIncBuild=0 MajorVer=1 MinorVer=0 Release=0 Build=0 Debug=0 PreRelease=0 Special=0 Private=0 DLL=0 Locale=1033 CodePage=1252 [Version Info Keys] CompanyName= FileDescription= FileVersion=1.0.0.0 InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion=1.0.0.0 Comments= [Excluded Packages] c:\winapps\borland\delphi7\Projects\Bpl\TCSComp_65.bpl=TCS Components 6.5 [HistoryLists\hlDebugSourcePath] Count=2 Item0=E:\nxt\BricxCC\source\bricktools\;E:\nxt\BricxCC\source\ Item1=E:\nxt\BricxCC\source\bricktools\ [HistoryLists\hlConditionals] Count=3 Item0=FAST_MM, CAN_DOWNLOAD Item1=FAST_MM Item2=FAST_MM, WITHTINY [HistoryLists\hlUnitAliases] Count=1 Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; [HistoryLists\hlSearchPath] Count=3 Item0=.. Item1=..;..\bricktools Item2=..;..\bricktool [HistoryLists\hlBPLOutput] Count=1 Item0=.. [HistoryLists\hlDCPOutput] Count=1 Item0=.. NXT/mkdata.dpr0000644000175000017500000000554611537752673013111 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) program mkdata; {$APPTYPE CONSOLE} uses Classes, SysUtils, uCmdLineUtils in '..\uCmdLineUtils.pas'; procedure PrintUsage; begin WriteLn('Usage: ' + progName + ' sourceFile destFile arrayName'); end; var srcFile, destFile, arrayName : string; MS : TMemoryStream; destMS : TMemoryStream; tmp : string; const ENDING = #13#10; HEADER = 'unit %s;'+ ENDING + ENDING + 'interface' + ENDING + ENDING + 'const' + ENDING + ' %s : array[0..%d] of byte = (' + ENDING; FOOTER = ' );' + ENDING + ENDING + 'implementation' + ENDING + ENDING + 'end.' + ENDING; SPACES = ' '; procedure WriteBytes(src, dest : TStream); var val : string; i : integer; b : byte; begin // write the contents of src to dest as a stream of // comma-separated hexadecimal byte values. { $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f, $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e,$1f, etc } src.Position := 0; i := 0; b := 0; val := SPACES; dest.Write(PChar(val)^, Length(val)); while src.Read(b, 1) = 1 do begin val := Format('$%2.2x', [b]); if src.Position < src.Size then val := val + ','; inc(i); dest.Write(PChar(val)^, Length(val)); if i mod 16 = 0 then begin val := ENDING; dest.Write(PChar(val)^, Length(val)); val := SPACES; dest.Write(PChar(val)^, Length(val)); end; end; val := ENDING; dest.Write(PChar(val)^, Length(val)); end; begin if ParamCount <> 3 then begin PrintUsage; Exit; end; srcFile := ParamStr(1); destFile := ParamStr(2); arrayName := ParamStr(3); MS := TMemoryStream.Create; try MS.LoadFromFile(srcFile); destMS := TMemoryStream.Create; try tmp := Format(HEADER, [ChangeFileExt(destFile, ''), arrayName, MS.Size-1]); destMS.Write(PChar(tmp)^, Length(tmp)); WriteBytes(MS, destMS); tmp := FOOTER; destMS.Write(PChar(tmp)^, Length(tmp)); destMS.SaveToFile(destFile); finally destMS.Free; end; finally MS.Free; end; end. NXT/nbcunix.mak0000644000175000017500000000266111537752673013274 0ustar slavkoslavkoPROGRAMS = nbc VER = 1.2.1.r4 DOBJECTS=uNXTClasses.o uPreprocess.o Parser10.o P10Build.o uNXCComp.o uRPGComp.o uRIC.o uRICComp.o uNBCCommon.o uNXTConstants.o uNBCInterface.o nbc.dpr DEFAULT_INCLUDE_DIR=/usr/local/include/nbc all:: $(DOBJECTS) $(PROGRAMS) clean:: rm -f *.o *.ppu *.rst *.compiled *.dcu nbc_preproc.inc realclean:: clean rm -f $(PROGRAMS) mkdata NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas install:: all PFLAGS=-S2cdghi -dRELEASE -vewnhi -l -Fu../ -Fu. -Fu../bricktools -dCAN_DOWNLOAD # PTOOLPREFIX may differ on different platforms (e.g. /usr/local/bin/) PTOOLPREFIX=/usr/bin/ PPC=$(PTOOLPREFIX)fpc # how to link executable nbc: nbc.dpr nbc_preproc.inc $(PPC) $(PFLAGS) $< -o$@ # how to compile pas source %.o: %.pas mkdata NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas $(PPC) $(PFLAGS) $< -o$@ # how to create the include file nbc_preproc.inc: echo '// '$@ > $@ echo 'const' >> $@ echo ' DEFAULT_INCLUDE_DIR = '\'$(DEFAULT_INCLUDE_DIR)\'';' >> $@ echo ' COMPILATION_TIMESTAMP = '\'`date`\'';' >> $@ # how to create the mkdata utility mkdata: mkdata.dpr $(PPC) $(PFLAGS) $< -o$@ # how to create NBCCommonData.pas NBCCommonData.pas: NBCCommon.h ./mkdata $< $@ nbc_common_data # how to create NXTDefsData.pas NXTDefsData.pas: NXTDefs.h ./mkdata $< $@ nxt_defs_data # how to create NXCDefsData.pas NXCDefsData.pas: NXCDefs.h ./mkdata $< $@ nxc_defs_data NXT/Parser10.pas0000644000175000017500000007257711537752673013253 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit Parser10; {$H+,S-} { long strings, no stack-checking} {.$DEFINE DEBUG} { by default make it lean and efficient } {$IFNDEF DEBUG} {$D-} {$L-} {$Q-} {$R-} {$S-} {$ENDIF} {$I+} { I/O checking ON } interface uses SysUtils, Classes; type { a couple of unfortunately necessary global declarations } ParserFloat = Extended; { please do NOT use "real", only single, double, extended} PParserFloat = ^ParserFloat; TToken=( variab, constant, minus, bitnot, lognot, sum, diff, prod, divis, modulo, IntDiv, bitand, bitor, bitxor, sleft, sright, logand, logor, lessthan,lessoreq, greaterthan,greateroreq, equalto,notequalto, integerpower, realpower, square, third, fourth, FuncOneVar, FuncTwoVar); PExpOperation = ^TExpOperation; { functions that are added to the engine MUST have this declaration } { make sure that the procedure is declared far !!! } TMathProcedure = procedure(AnOperation: PExpOperation); TExpOperation = record { MUST use pointers (!), because argument and destination are linked... } Arg1, Arg2 : PParserFloat; Dest : PParserFloat; NextOperation : PExpOperation; Operation: TMathProcedure; Token : TToken; end; EMathParserError = class(Exception); { create a new exception class and... } { ... some descendants } ESyntaxError = class(EMathParserError); EExpressionHasBlanks = class(EMathParserError); EExpressionTooComplex = class(EMathParserError); ETooManyNestings = class(EMathParserError); EMissMatchingBracket = class(EMathParserError); EBadName = class(EMathParserError); EParserInternalError = class(EMathParserError); { hopefully we will never see this one } { we COULD use Forms and the TExceptionEvent therein, but that would give us all the VCL overhead. Consequentially we just redeclare an appropriate event } TParserExceptionEvent = procedure (Sender: TObject; E: Exception) of object; TCustomExpressionEvent = procedure (Sender: TObject; const expr : string; var value : extended; var bDone : boolean) of object; TCustomParser = class(TComponent) private fCaseSensitive: boolean; fSilent: boolean; fOnCustomExpression: TCustomExpressionEvent; procedure SetCaseSensitive(const Value: boolean); procedure SetSilentExpression(const Value: string); function GetSilentExpression: string; private FExpression : string; FPascalNumberformat: boolean; FParserError : boolean; FErrorMessage : string; FVariables: TStringList; FStartOperationList: PExpOperation; FOnParserError : TParserExceptionEvent; function CalcValue: extended; procedure SetExpression(const AnExpression: string); procedure SetVar(const VarName: string; const Value: extended); protected { lists of available functions, see .Create for example use } FunctionOne : TStringList; { functions with ONE argument, e.g. exp() } FunctionTwo : TStringList; { functions with TWO arguments, e.g. max(,) } public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function ParseExpression(const AnExpression: string): boolean; procedure FreeExpression; { The PParserFloat returned points to the place in memory where the variable actually sits; to speed up assignment you can DIRECTLY assign data to the memory area. } function SetVariable(VarName: string; const Value: extended): PParserFloat; function GetVariable(const VarName: string): extended; procedure AddFunctionOneParam(const AFunctionName: string; const Func: TMathProcedure); procedure AddFunctionTwoParam(const AFunctionName: string; const Func: TMathProcedure); procedure ClearVariables; procedure ClearVariable(const AVarName: string); function VariableExists(const AVarName: string): boolean; procedure ClearFunctions; procedure ClearFunction(const AFunctionName: string); property ParserError: boolean read FParserError; property ErrorMessage : string read FErrorMessage; property LinkedOperationList: PExpOperation read FStartOperationList; property Variable[const VarName: string]: extended read GetVariable write SetVar; property CaseSensitive : boolean read fCaseSensitive write SetCaseSensitive; property Silent : boolean read fSilent write fSilent; published property Value: extended read CalcValue stored false; { setting Expression automatically parses it Warning: exceptions MAY be raised, if OnParserError is NOT assigned, otherwise the event will be triggered in case of an error } property Expression: string read FExpression write SetExpression; property SilentExpression: string read GetSilentExpression write SetSilentExpression; property PascalNumberformat: boolean read FPascalNumberformat write FPascalNumberformat default true; property OnParserError: TParserExceptionEvent read FOnParserError write FOnParserError; property OnCustomExpression : TCustomExpressionEvent read fOnCustomExpression write fOnCustomExpression; end; TExpParser = class(TCustomParser) public { overrides to add the properties below as variables and adds all the functions } constructor Create(AOwner: TComponent); override; { returns the string with the blanks inside removed } class function RemoveBlanks(const s: string): string; end; implementation {$DEFINE UseMath} { Note: if you do not have the MATH unit simply remove the conditional define the component will continue to work, just a bit slower } uses {$IFDEF UseMath} Math, {$ENDIF} P10Build; {****************************************************************} { } { Following are "built-in" calculation procedures } { } {****************************************************************} { Naming convention for functions: Name of built-in function, prepended with an underscore. Example: ln --> _ln Passed arguments / results: If the function takes any arguments - i.e. if it has been added to either the FunctionOne or the FunctionTwo list: - First argument --> Arg1^ - Second argument --> Arg2^ The result of the operation must ALWAYS be put into Dest^ Note: These are POINTERS to floats. } {****************************************************************} { } { These are mandatory procedures - never remove them } { } {****************************************************************} { do nothing - this only happens if the "term" is just a number or a variable; otherwise this procedure will never be called } procedure _nothing(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Dest^; end; procedure _Add(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Arg1^ + Arg2^; end; procedure _Subtract(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Arg1^ - Arg2^; end; procedure _Multiply(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Arg1^ * Arg2^; end; procedure _RealDivide(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Arg1^ / Arg2^; end; procedure _Modulo(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) mod trunc(Arg2^); end; procedure _IntDiv(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) div trunc(Arg2^); end; procedure _BitAnd(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) and trunc(Arg2^); end; procedure _BitOr(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) or trunc(Arg2^); end; procedure _BitXor(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) xor trunc(Arg2^); end; procedure _ShiftLeft(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) shl trunc(Arg2^); end; procedure _ShiftRight(AnOp: PExpOperation); begin with AnOp^ do Dest^ := trunc(Arg1^) shr trunc(Arg2^); end; procedure _Negate(AnOp: PExpOperation); begin with AnOp^ do Dest^ := -Arg1^; end; procedure _BitNot(AnOp: PExpOperation); begin with AnOp^ do Dest^ := not Trunc(Arg1^); end; const bVals : array[boolean] of integer = (0, 1); procedure _LogicalNot(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Trunc(Arg1^) = 0]; // not is implied end; procedure _LogicalAnd(AnOp: PExpOperation); var b1, b2 : boolean; begin with AnOp^ do begin b1 := Trunc(Arg1^) <> 0; b2 := Trunc(Arg2^) <> 0; Dest^ := bVals[b1 and b2]; end; end; procedure _LogicalOr(AnOp: PExpOperation); var b1, b2 : boolean; begin with AnOp^ do begin b1 := Trunc(Arg1^) <> 0; b2 := Trunc(Arg2^) <> 0; Dest^ := bVals[b1 or b2]; end; end; procedure _LessThan(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ < Arg2^]; end; procedure _LessOrEqual(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ <= Arg2^]; end; procedure _GreaterThan(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ > Arg2^]; end; procedure _GreaterOrEqual(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ >= Arg2^]; end; procedure _EqualTo(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ = Arg2^]; end; procedure _NotEqualTo(AnOp: PExpOperation); begin with AnOp^ do Dest^ := bVals[Arg1^ <> Arg2^]; end; procedure _IntPower(AnOp: PExpOperation); {$IFNDEF UseMath} var n, i: longint; {$ENDIF} begin {$IFNDEF UseMath} with AnOp^ do begin n := trunc(abs(Arg2^))-1; case n of -1: Dest^ := 1; 0: Dest^ := Arg1^; else Dest^ := Arg1^; for i := 1 to n do Dest^ := Dest^ * Arg1^; end; if Arg2^ < 0 then Dest^ := 1 / Dest^; end; {$ELSE} with AnOp^ do Dest^ := IntPower(Arg1^, Integer(Trunc(Arg2^))); {$ENDIF} end; procedure _square(AnOp: PExpOperation); begin with AnOp^ do Dest^ := sqr(Arg1^); end; procedure _third(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Arg1^ * Arg1^ * Arg1^; end; procedure _forth(AnOp: PExpOperation); begin with AnOp^ do Dest^ := sqr(sqr(Arg1^)); end; procedure _power(AnOp: PExpOperation); begin with AnOp^ do begin {$IFNDEF UseMath} if Arg1^ = 0 then Dest^ := 0 else Dest^ := exp(Arg2^*ln(Arg1^)); {$ELSE} Dest^ := Power(Arg1^, Arg2^); {$ENDIF} end; end; {****************************************************************} { } { These are OPTIONAL procedures - you may remove them, though } { it is preferable to not register them for use } { } {****************************************************************} procedure _sin(AnOp: PExpOperation); begin with AnOp^ do Dest^ := sin(Arg1^); end; procedure _cos(AnOp: PExpOperation); begin with AnOp^ do Dest^ := cos(Arg1^); end; procedure _arctan(AnOp: PExpOperation); begin with AnOp^ do Dest^ := arctan(Arg1^); end; procedure _arg(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ < 0 then Dest^ := arctan(Arg2^/Arg1^)+Pi else if Arg1^>0 then Dest^ := arctan(Arg2^/Arg1^) else if Arg2^ > 0 then Dest^ := 0.5 * Pi else Dest^ := -0.5 * Pi; end; procedure _sinh(AnOp: PExpOperation); begin with AnOp^ do Dest^ := (exp(Arg1^)-exp(-Arg1^))*0.5; end; procedure _cosh(AnOp: PExpOperation); begin with AnOp^ do Dest^ := (exp(Arg1^)+exp(-Arg1^))*0.5; end; procedure _cotan(AnOp: PExpOperation); begin with AnOp^ do {$IFNDEF UseMath} Dest^ := cos(Arg1^) / sin(Arg1^); {$ELSE} Dest^ := cotan(Arg1^); {$ENDIF} end; procedure _tan(AnOp: PExpOperation); begin with AnOp^ do {$IFNDEF UseMath} Dest^ := sin(Arg1^) / cos(Arg1^); {$ELSE} Dest^ := tan(Arg1^); {$ENDIF} end; procedure _exp(AnOp: PExpOperation); begin with AnOp^ do Dest^ := exp(Arg1^); end; procedure _ln(AnOp: PExpOperation); begin with AnOp^ do Dest^ := ln(Arg1^); end; procedure _log10(AnOp: PExpOperation); {$IFNDEF UseMath} const _1_ln10 = 0.4342944819033; {$ENDIF} begin with AnOp^ do {$IFDEF UseMath} Dest^ := log10(Arg1^); {$ELSE} Dest^ := ln(Arg1^) * _1_ln10; {$ENDIF} end; procedure _log2(AnOp: PExpOperation); {$IFNDEF UseMath} const _1_ln2 = 1.4426950409; {$ENDIF} begin with AnOp^ do {$IFDEF UseMath} Dest^ := log2(Arg1^); {$ELSE} Dest^ := ln(Arg1^) * _1_ln2; {$ENDIF} end; procedure _logN(AnOp: PExpOperation); begin with AnOp^ do {$IFDEF UseMath} Dest^ := logN(Arg1^, Arg2^); {$ELSE} Dest^ := ln(Arg1^) / ln(Arg2^); {$ENDIF} end; procedure _sqrt(AnOp: PExpOperation); begin with AnOp^ do Dest^ := sqrt(Arg1^); end; procedure _abs(AnOp: PExpOperation); begin with AnOp^ do Dest^ := abs(Arg1^); end; procedure _min(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ < Arg2^ then Dest^ := Arg1^ else Dest^ := Arg2^; end; procedure _max(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ < Arg2^ then Dest^ := Arg2^ else Dest^ := Arg1^; end; procedure _heaviside(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ < 0 then Dest^ := 0 else Dest^ := 1; end; procedure _sign(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ < 0 then Dest^ := -1 else if Arg1^ > 0 then Dest^ := 1.0 else Dest^ := 0.0; end; procedure _zero(AnOp: PExpOperation); begin with AnOp^ do if Arg1^ = 0.0 then Dest^ := 0.0 else Dest^ := 1.0; end; procedure _trunc(AnOp: PExpOperation); begin with AnOp^ do Dest^ := int(Arg1^) end; procedure _ceil(AnOp: PExpOperation); begin with AnOp^ do if frac(Arg1^) > 0 then Dest^ := int(Arg1^ + 1) else Dest^ := int(Arg1^); end; procedure _floor(AnOp: PExpOperation); begin with AnOp^ do if frac(Arg1^) < 0 then Dest^ := int(Arg1^ - 1) else Dest^ := int(Arg1^); end; procedure _rnd(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Random * int(Arg1^); end; procedure _random(AnOp: PExpOperation); begin with AnOp^ do Dest^ := Random(Trunc(Arg1^)); end; procedure _radius(AnOp: PExpOperation); begin with AnOp^ do Dest^ := sqrt(sqr(Arg1^)+sqr(Arg2^)); end; procedure _phase(AnOp: PExpOperation); var a: ParserFloat; begin with AnOp^ do begin a := Arg1^ / (2/pi); Dest^ := (2*pi) * (a-round(a)); end; end; {****************************************************************} { } { TCustomParser } { } { A base class which does not publish the variable properties } { and adds no functions by default } { } {****************************************************************} function TCustomParser.ParseExpression(const AnExpression: string):boolean; var OperationLoop: PExpOperation; begin FreeExpression; FExpression := AnExpression; if AnExpression <> '' then begin Result := false; try ParseFunction( AnExpression, FVariables, FunctionOne, FunctionTwo, FPascalNumberformat, CaseSensitive, FStartOperationList, Result); FParserError := Result; except on E: Exception do begin FParserError := true; FErrorMessage := E.Message; if not Silent then begin if Assigned(FOnParserError) then begin FOnParserError(Self, E); exit; end else raise; end; end; end; Result := not Result; OperationLoop := FStartOperationList; while OperationLoop <> nil do begin with OperationLoop^ do begin case Token of variab, constant: Operation := @_nothing; minus: Operation := @_negate; bitnot: Operation := @_BitNot; lognot: Operation := @_LogicalNot; logand: Operation := @_LogicalAnd; logor: Operation := @_LogicalOr; lessthan: Operation := @_LessThan; lessoreq: Operation := @_LessOrEqual; greaterthan: Operation := @_GreaterThan; greateroreq: Operation := @_GreaterOrEqual; equalto: Operation := @_EqualTo; notequalto: Operation := @_NotEqualTo; sum: Operation := @_add; diff: Operation := @_subtract; prod: Operation := @_multiply; divis: Operation := @_RealDivide; modulo: Operation := @_Modulo; intdiv: Operation := @_IntDiv; bitand: Operation := @_BitAnd; bitor: Operation := @_BitOr; bitxor: Operation := @_BitXor; sleft: Operation := @_ShiftLeft; sright: Operation := @_ShiftRight; integerpower: Operation := @_IntPower; realpower: Operation := @_Power; square: Operation := @_square; third: Operation := @_third; fourth: Operation := @_forth; FuncOneVar, FuncTwoVar: { job has been done in build already !}; end; {case} OperationLoop := NextOperation; end; {with OperationLoop^} end; {while OperationLoop<>nil} end; // reset Silent to False (it is always a one-shot use) Silent := False; end; constructor TCustomParser.Create(AOwner: TComponent); begin inherited Create(AOwner); fCaseSensitive := true; FPascalNumberformat := true; FVariables := TStringList.Create; FVariables.CaseSensitive := fCaseSensitive; with FVariables do begin Sorted := true; Duplicates := dupIgnore; end; FunctionOne := TStringList.Create; FunctionOne.CaseSensitive := fCaseSensitive; with FunctionOne do begin Sorted := true; Duplicates := dupError; end; FunctionTwo := TStringList.Create; FunctionTwo.CaseSensitive := fCaseSensitive; with FunctionTwo do begin Sorted := true; Duplicates := dupError; end; end; destructor TCustomParser.Destroy; begin FreeExpression; ClearVariables; FVariables.Free; FunctionOne.Free; FunctionTwo.Free; inherited Destroy; end; procedure TCustomParser.SetVar(const VarName: string; const Value: extended); begin SetVariable(VarName, Value); end; function TCustomParser.SetVariable(VarName: string; const Value: extended): PParserFloat; var i: integer; begin if not CaseSensitive then VarName := UpperCase(VarName); i := 0; with FVariables do if Find(VarName, i) then begin Result := PParserFloat(Objects[i]); Result^ := Value; end else begin if Length(Varname) = 1 then begin { is the variable name a valid identifier? } if not IsValidIdent(VarName) then raise EBadName.Create(VarName); { unravelled loop for improved (string!) performance! } { check whether the variable contains any of the operators (DIV and MOD) this would confuse the parser... } if pos('+', VarName) <> 0 then raise EBadName.Create(VarName); if pos('-', VarName) <> 0 then raise EBadName.Create(VarName); if pos('*', VarName) <> 0 then raise EBadName.Create(VarName); if pos('/', VarName) <> 0 then raise EBadName.Create(VarName); if pos('^', VarName) <> 0 then raise EBadName.Create(VarName); if pos('div', VarName) <> 0 then raise EBadName.Create(VarName); if pos('mod', VarName) <> 0 then raise EBadName.Create(VarName); new(Result); end else begin { is the variable name a valid identifier? } if not IsValidIdent(VarName) then raise EBadName.Create(VarName); new(Result); end; Result^ := Value; AddObject(VarName, TObject(Result)); end end; function TCustomParser.GetVariable(const VarName: string): extended; var i: integer; tmpVarName : string; begin with FVariables do begin if CaseSensitive then tmpVarName := VarName else tmpVarName := UpperCase(VarName); i := 0; if Find(tmpVarName, i) then Result := PParserFloat(Objects[i])^ else Result := 0.0; end; end; procedure TCustomParser.AddFunctionOneParam(const AFunctionName: string; const Func: TMathProcedure); var tmpFuncName : string; begin if CaseSensitive then tmpFuncName := AFunctionName else tmpFuncName := UpperCase(AFunctionName); if IsValidIdent(AFunctionName) then FunctionOne.AddObject(tmpFuncName, TObject(@Func)) else raise EBadName.Create(AFunctionName); end; procedure TCustomParser.AddFunctionTwoParam(const AFunctionName: string; const Func: TMathProcedure); var tmpFuncName : string; begin if CaseSensitive then tmpFuncName := AFunctionName else tmpFuncName := UpperCase(AFunctionName); if IsValidIdent(AFunctionName) then FunctionTwo.AddObject(tmpFuncName, TObject(@Func)) else raise EBadName.Create(AFunctionName); end; procedure TCustomParser.ClearVariables; var i: integer; APPFloat: PParserFloat; // AString: string; { disregard stack consumption } begin with FVariables do begin i := Count; while i > 0 do begin dec(i); // AString := Strings[i]; APPFloat := PParserFloat(Objects[i]); if APPFloat <> nil then dispose( APPFloat ); { dispose only user-defined variables } end; Clear; end; SetExpression(''); { invalidate expression } end; procedure TCustomParser.ClearVariable(const AVarName: string); var index: integer; begin index := 0; with FVariables do begin if Find(AVarName, index) then begin dispose( PParserFloat(Objects[index]) ); Delete(index); end; end; SetExpression(''); { invalidate expression } end; function TCustomParser.VariableExists(const AVarName: string): boolean; var index: integer; tmpVarName : string; begin index := 0; if CaseSensitive then tmpVarName := AVarName else tmpVarName := UpperCase(AVarName); Result := FVariables.Find(tmpVarName, index); end; procedure TCustomParser.ClearFunctions; begin FunctionOne.Clear; FunctionTwo.Clear; SetExpression(''); { invalidate expression } end; procedure TCustomParser.ClearFunction(const AFunctionName: string); var index: integer; begin index := 0; with FunctionOne do begin if Find(AFunctionName, index) then begin Delete(index); SetExpression(''); { invalidate expression } exit; end; end; with FunctionTwo do begin if Find(AFunctionName, index) then begin Delete(index); SetExpression(''); { invalidate expression } end; end; end; procedure TCustomParser.FreeExpression; var LastOP, NextOP: PExpOperation; begin LastOP := FStartOperationList; while LastOP <> nil do begin NextOP := LastOP^.NextOperation; while NextOP <> nil do with NextOP^ do begin if (Arg1 = lastop^.Arg1) or (Arg1 = lastop^.Arg2) or (Arg1 = lastop^.Dest) then Arg1 := nil; if (Arg2 = lastop^.Arg1) or (Arg2 = lastop^.Arg2) or (Arg2 = lastop^.Dest) then Arg2 := nil; if (Dest = lastop^.Arg1) or (Dest = lastop^.Arg2) or (Dest = lastop^.Dest) then Dest := nil; NextOP := NextOperation; end; with LastOP^, FVariables do begin if IndexOfObject( TObject(Arg1)) >= 0 then Arg1 := nil; if IndexOfObject( TObject(Arg2)) >= 0 then Arg2 := nil; if IndexOfObject( TObject(Dest)) >= 0 then Dest := nil; if (Dest <> nil) and (Dest <> Arg2) and (Dest <> Arg1) then dispose(Dest); if (Arg2 <> nil) and (Arg2 <> Arg1) then dispose(Arg2); if (Arg1 <> nil) then dispose(Arg1); end; NextOP := LastOP^.NextOperation; dispose(LastOP); LastOP := NextOP; end; FStartOperationList := nil; end; procedure TCustomParser.SetExpression(const AnExpression: string); begin ParseExpression(AnExpression); { this implies FExpression := AnExpression } end; function TCustomParser.CalcValue: extended; var LastOP: PExpOperation; begin if FStartOperationList <> nil then begin LastOP := FStartOperationList; while LastOP^.NextOperation <> nil do begin with LastOP^ do begin Operation(LastOP); LastOP := NextOperation; end; end; LastOP^.Operation(LastOP); Result := LastOP^.Dest^; end else Result := 0; end; {****************************************************************} { } { TExpParser } { } {****************************************************************} constructor TExpParser.Create(AOwner: TComponent); begin inherited Create(AOwner); with FunctionOne do begin {.$DEFINE SpeedCompare} { compare speed against older versions with less functions } AddObject('tan', TObject(@_tan)); AddObject('sin', TObject(@_sin)); AddObject('cos', TObject(@_cos)); AddObject('sinh', TObject(@_sinh)); AddObject('cosh', TObject(@_cosh)); AddObject('arctan', TObject(@_arctan)); {$IFNDEF SpeedCompare} AddObject('cotan', TObject(@_cotan)); AddObject('arg', TObject(@_arg)); {$ENDIF} AddObject('exp', TObject(@_exp)); AddObject('ln', TObject(@_ln)); {$IFNDEF SpeedCompare} AddObject('log10', TObject(@_log10)); AddObject('log2', TObject(@_log2)); AddObject('sqr', TObject(@_square)); {$ENDIF} AddObject('sqrt', TObject(@_sqrt)); AddObject('abs', TObject(@_abs)); {$IFNDEF SpeedCompare} AddObject('trunc', TObject(@_trunc)); AddObject('int', TObject(@_trunc)); { NOTE: INT = TRUNC ! } AddObject('ceil', TObject(@_ceil)); AddObject('floor', TObject(@_floor)); {$ENDIF} AddObject('heav', TObject(@_heaviside)); AddObject('sign', TObject(@_sign)); AddObject('zero', TObject(@_zero)); AddObject('ph', TObject(@_phase)); AddObject('rnd', TObject(@_rnd)); {$IFNDEF SpeedCompare} AddObject('random', TObject(@_random)); {$ENDIF} end; with FunctionTwo do begin AddObject('max', TObject(@_max)); AddObject('min', TObject(@_min)); {$IFNDEF SpeedCompare} AddObject('power', TObject(@_Power)); AddObject('intpower', TObject(@_IntPower)); AddObject('logn', TObject(@_logN)); {$ENDIF} end; end; class function TExpParser.RemoveBlanks(const s: string): string; {deletes all blanks in s} var i : integer; begin Result := s; i := pos(' ', Result); while i > 0 do begin delete(Result, i, 1); i := pos(' ', Result); end; end; procedure TCustomParser.SetCaseSensitive(const Value: boolean); begin fCaseSensitive := Value; FVariables.CaseSensitive := fCaseSensitive; FunctionOne.CaseSensitive := fCaseSensitive; FunctionTwo.CaseSensitive := fCaseSensitive; end; procedure TCustomParser.SetSilentExpression(const Value: string); begin Silent := True; try Expression := Value; finally Silent := False; // make sure it is turned off again end; end; function TCustomParser.GetSilentExpression: string; begin Result := Expression; end; initialization Randomize; end. NXT/nbcwincearm.mak0000644000175000017500000000350411537752673014113 0ustar slavkoslavkoPROGRAMS = nbc.exe VER = 1.2.1.r4 DOBJECTS=uNXTClasses.o uPreprocess.o Parser10.o P10Build.o uNXCComp.o uRPGComp.o uRIC.o uRICComp.o uNBCCommon.o uNXTConstants.o uNBCInterface.o nbc.dpr DEFAULT_INCLUDE_DIR=. all:: $(DOBJECTS) $(PROGRAMS) clean:: rm -f *.o *.ppu *.rst *.compiled *.dcu nbc_preproc.inc realclean:: clean rm -f $(PROGRAMS) mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas #PFLAGS=-S2cdghi -dRELEASE -OG1 -gl -vewnhi -l -Fu../ -Fu. # wince arm PFLAGS=-S2cdghi -dRELEASE -OG1 -TWinCE -Parm -gl -Xs -WG -va -vewnhi -l -Fu..\..\..\..\lazarus\lcl\units\arm-wince\ -Fu..\..\..\..\lazarus\lcl\units\arm-wince\wince\ -Fu..\..\..\..\lazarus\packager\units\arm-wince\ -Fu../ -Fu. PTOOLPREFIX=c:/lazarus/fpc/2.1.3/bin/i386-win32/ PPC=$(PTOOLPREFIX)fpc.exe # Win32 #PTOOLPREFIX=C:/lazarus/fpc/2.1.3/bin/i386-win32/ #PPC=$(PTOOLPREFIX)ppc386.exe # Linux #PTOOLPREFIX=/usr/bin/ #PPC=$(PTOOLPREFIX)ppc386 # Mac OSX #PTOOLPREFIX=/usr/local/bin/ #PPC=$(PTOOLPREFIX)ppcppc # how to link executable %.exe: %.dpr nbc_preproc.inc $(PPC) $(PFLAGS) $< -o$@ strip $@ # how to compile pas source %.o: %.pas mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas $(PPC) $(PFLAGS) $< -o$@ # how to create the include file nbc_preproc.inc: echo '// '$@ > $@ echo 'const' >> $@ echo ' DEFAULT_INCLUDE_DIR = '\'$(DEFAULT_INCLUDE_DIR)\'';' >> $@ echo ' COMPILATION_TIMESTAMP = '\'`date`\'';' >> $@ # how to create the mkdata utility mkdata.exe: mkdata.dpr $(PPC) $(PFLAGS) $< -o$@ strip $@ # how to create NBCCommonData.pas NBCCommonData.pas: NBCCommon.h ./mkdata $< $@ nbc_common_data # how to create NXTDefsData.pas NXTDefsData.pas: NXTDefs.h ./mkdata $< $@ nxt_defs_data # how to create NXCDefsData.pas NXCDefsData.pas: NXCDefs.h ./mkdata $< $@ nxc_defs_data NXT/uNXTConstants.pas0000644000175000017500000016674311537752673014410 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNXTConstants; interface type TDSType = (dsVoid, dsUByte, dsSByte, dsUWord, dsSWord, dsULong, dsSLong, dsArray, dsCluster, dsMutex, dsFloat); const MIN_FW_VER1X = 101; // 1.01 MAX_FW_VER1X = 107; // 1.07 MIN_FW_VER2X = 120; // 1.20 const OPCC1_LT = $00; OPCC1_GT = $01; OPCC1_LTEQ = $02; OPCC1_GTEQ = $03; OPCC1_EQ = $04; OPCC1_NEQ = $05; const OPARR_SUM = $00; OPARR_MEAN = $01; OPARR_SUMSQR = $02; OPARR_STD = $03; OPARR_MIN = $04; OPARR_MAX = $05; OPARR_SORT = $06; const OPCODE_COUNT = $51; HEX_FMT = '0x%x'; type TOpCode = Byte; const OP_ADD = $00; OP_SUB = $01; OP_NEG = $02; OP_MUL = $03; OP_DIV = $04; OP_MOD = $05; OP_AND = $06; OP_OR = $07; OP_XOR = $08; OP_NOT = $09; OP_CMNT = $0a; OP_LSL = $0b; OP_LSR = $0c; OP_ASL = $0d; OP_ASR = $0e; OP_ROTL = $0f; OP_ROTR = $10; OP_CMP = $11; OP_TST = $12; OP_CMPSET = $13; OP_TSTSET = $14; OP_INDEX = $15; OP_REPLACE = $16; OP_ARRSIZE = $17; OP_ARRBUILD = $18; OP_ARRSUBSET = $19; OP_ARRINIT = $1a; OP_MOV = $1b; OP_SET = $1c; OP_FLATTEN = $1d; OP_UNFLATTEN = $1e; OP_NUMTOSTRING = $1f; OP_STRINGTONUM = $20; OP_STRCAT = $21; OP_STRSUBSET = $22; OP_STRTOBYTEARR = $23; OP_BYTEARRTOSTR = $24; OP_JMP = $25; OP_BRCMP = $26; OP_BRTST = $27; OP_SYSCALL = $28; OP_STOP = $29; OP_FINCLUMP = $2a; OP_FINCLUMPIMMED = $2b; OP_ACQUIRE = $2c; OP_RELEASE = $2d; OP_SUBCALL = $2e; OP_SUBRET = $2f; OP_SETIN = $30; OP_SETOUT = $31; OP_GETIN = $32; OP_GETOUT = $33; OP_WAIT = $34; // standard 1.26+ or enhanced 1.07+ OP_GETTICK = $35; // enhanced firmware opcodes (1.07) OPS_WAITV = $36; OPS_ABS = $37; OPS_SIGN = $38; OPS_STOPCLUMP = $39; OPS_START = $3a; OPS_PRIORITY = $3b; OPS_FMTNUM = $3c; OPS_ARROP = $3d; OPS_ACOS = $3e; OPS_ASIN = $3f; OPS_ATAN = $40; OPS_CEIL = $41; OPS_EXP = $42; OPS_FABS = $43; OPS_FLOOR = $44; OPS_SQRT = $45; OPS_TAN = $46; OPS_TANH = $47; OPS_COS = $48; OPS_COSH = $49; OPS_LOG = $4a; OPS_LOG10 = $4b; OPS_SIN = $4c; OPS_SINH = $4d; OPS_ATAN2 = $4e; OPS_FMOD = $4f; OPS_POW = $50; // standard firmware opcodes (1.26+) OP_SQRT_2 = $36; OP_ABS_2 = $37; // enhanced firmware opcodes (1.28) OPS_WAITI_2 = $64; OPS_WAITV_2 = $65; OPS_SIGN_2 = $66; OPS_STOPCLUMP_2 = $67; OPS_START_2 = $68; OPS_PRIORITY_2 = $69; OPS_FMTNUM_2 = $6a; OPS_ARROP_2 = $6b; OPS_ACOS_2 = $6c; OPS_ASIN_2 = $6d; OPS_ATAN_2 = $6e; OPS_CEIL_2 = $6f; OPS_EXP_2 = $70; OPS_FLOOR_2 = $71; OPS_TAN_2 = $72; OPS_TANH_2 = $73; OPS_COS_2 = $74; OPS_COSH_2 = $75; OPS_LOG_2 = $76; OPS_LOG10_2 = $77; OPS_SIN_2 = $78; OPS_SINH_2 = $79; OPS_TRUNC_2 = $7a; OPS_FRAC_2 = $7b; OPS_ATAN2_2 = $7c; OPS_POW_2 = $7d; OPS_MULDIV_2 = $7e; // transcendental opcodes that use degrees instead of radians OPS_ACOSD_2 = $7f; OPS_ASIND_2 = $80; OPS_ATAND_2 = $81; OPS_TAND_2 = $82; OPS_TANHD_2 = $83; OPS_COSD_2 = $84; OPS_COSHD_2 = $85; OPS_SIND_2 = $86; OPS_SINHD_2 = $87; OPS_ATAN2D_2 = $88; // misc other enhanced opcodes OPS_ADDROF = $89; // pseudo opcodes OPS_THREAD = $90; OPS_ENDT = $91; OPS_SUBROUTINE = $92; OPS_REQUIRES = $93; OPS_USES = $94; OPS_SEGMENT = $95; OPS_ENDS = $96; OPS_TYPEDEF = $97; OPS_STRUCT = $98; // var declarations OPS_DB = $99; OPS_BYTE = $9a; OPS_SBYTE = $9b; OPS_UBYTE = $9c; OPS_DW = $9d; OPS_WORD = $9e; OPS_SWORD = $9f; OPS_UWORD = $a0; OPS_DD = $a1; OPS_DWORD = $a2; OPS_SDWORD = $a3; OPS_UDWORD = $a4; OPS_LONG = $a5; OPS_SLONG = $a6; OPS_ULONG = $a7; OPS_VOID = $a8; OPS_MUTEX = $a9; OPS_FLOAT = $aa; // pseudo opcodes OPS_CALL = $ab; OPS_RETURN = $ac; OPS_STRINDEX = $ad; OPS_STRREPLACE = $ae; OPS_SHL = $af; OPS_SHR = $b0; OPS_STRLEN = $b1; OPS_COMPCHK = $b2; OPS_COMPIF = $b3; OPS_COMPELSE = $b4; OPS_COMPEND = $b5; OPS_COMPCHKTYPE = $b6; OPS_COMMENT = $b7; // invalid opcode OPS_INVALID = $f0; (* type TOpCode = ( OP_ADD, OP_SUB, OP_NEG, OP_MUL, OP_DIV, OP_MOD, OP_AND, OP_OR, OP_XOR, OP_NOT, OP_CMNT, OP_LSL, OP_LSR, OP_ASL, OP_ASR, OP_ROTL, OP_ROTR, OP_CMP, OP_TST, OP_CMPSET, OP_TSTSET, OP_INDEX, OP_REPLACE, OP_ARRSIZE, OP_ARRBUILD, OP_ARRSUBSET, OP_ARRINIT, OP_MOV, OP_SET, OP_FLATTEN, OP_UNFLATTEN, OP_NUMTOSTRING, OP_STRINGTONUM, OP_STRCAT, OP_STRSUBSET, OP_STRTOBYTEARR, OP_BYTEARRTOSTR, OP_JMP, OP_BRCMP, OP_BRTST, OP_SYSCALL, OP_STOP, OP_FINCLUMP, OP_FINCLUMPIMMED, OP_ACQUIRE, OP_RELEASE, OP_SUBCALL, OP_SUBRET, OP_SETIN, OP_SETOUT, OP_GETIN, OP_GETOUT, OP_WAIT, // 0x34 OP_GETTICK, // 0x35 OPS_WAITV, OPS_ABS, OPS_SIGN, OPS_STOPCLUMP, OPS_START, OPS_PRIORITY, OPS_FMTNUM, OPS_ARROP, OPS_ACOS, OPS_ASIN, OPS_ATAN, OPS_CEIL, OPS_EXP, OPS_FABS, OPS_FLOOR, OPS_SQRT, OPS_TAN, OPS_TANH, OPS_COS, OPS_COSH, OPS_LOG, OPS_LOG10, OPS_SIN, OPS_SINH, OPS_ATAN2, OPS_FMOD, OPS_POW, OPS_THREAD, OPS_ENDT, OPS_SUBROUTINE, OPS_REQUIRES, OPS_USES, OPS_SEGMENT, OPS_ENDS, OPS_TYPEDEF, OPS_STRUCT, OPS_DB, OPS_BYTE, OPS_SBYTE, OPS_UBYTE, OPS_DW, OPS_WORD, OPS_SWORD, OPS_UWORD, OPS_DD, OPS_DWORD, OPS_SDWORD, OPS_UDWORD, OPS_LONG, OPS_SLONG, OPS_ULONG, OPS_VOID, OPS_MUTEX, OPS_FLOAT, OPS_CALL, OPS_RETURN, OPS_STRINDEX, OPS_STRREPLACE, OPS_SHL, OPS_SHR, OPS_STRLEN, OPS_COMPCHK, OPS_COMPIF, OPS_COMPELSE, OPS_COMPEND, OPS_COMPCHKTYPE, OPS_COMMENT, OPS_INVALID ); *) const FILENAME_LENGTH = 19; // zero termination not included FILEHEADER_LENGTH = 8; // all simple file headers DISPLAYLINE_LENGTH = 16; // zero termination not included ON_BRICK_PROGRAMSTEPS = 5; // no of on brick program steps STATUSTEXT_SIZE = 8; // zero termination not included function INC_ID(X : Word) : Word; const DATA_ARG_ADDR_MASK = $3FFF; DATA_ARG_IMM_MASK = $7FFF; MOD_INPUT = 0; MOD_OUTPUT = 1; NO_OF_INPUTS = 4; IO_IN_FPP = 6; IO_IN_FIELD_COUNT = IO_IN_FPP * NO_OF_INPUTS; NO_OF_OUTPUTS = 3; IO_OUT_FPP = 15; IO_OUT_FIELD_COUNT = IO_OUT_FPP * NO_OF_OUTPUTS; NO_OF_BTNS = 4; // flags passed into the UpdateFlags field of RCXOutput/RCXOutputMulti const UF_UPDATE_MODE = $01; UF_UPDATE_SPEED = $02; UF_UPDATE_TACHO_LIMIT = $04; UF_UPDATE_RESET_COUNT = $08; UF_UPDATE_PID_VALUES = $10; UF_UPDATE_RESET_BLOCK_COUNT = $20; UF_UPDATE_RESET_ROTATION_COUNT = $40; UF_PENDING_UPDATES = $80; // flags passed into the Mode field of RCXOutput/RCXOutputMulti const OUT_MODE_COAST = $00; OUT_MODE_MOTORON = $01; OUT_MODE_BRAKE = $02; OUT_MODE_REGULATED = $04; OUT_MODE_REGMETHOD = $f0; // may be more ??? const OUT_RUNSTATE_IDLE = $00; OUT_RUNSTATE_RAMPUP = $10; OUT_RUNSTATE_RUNNING = $20; OUT_RUNSTATE_RAMPDOWN = $40; const OUT_REGMODE_IDLE = 0; OUT_REGMODE_SPEED = 1; OUT_REGMODE_SYNC = 2; // values passed into the Type field of the RCXInput const IN_TYPE_NO_SENSOR = $0; IN_TYPE_SWITCH = $1; IN_TYPE_TEMPERATURE = $2; IN_TYPE_REFLECTION = $3; IN_TYPE_ANGLE = $4; IN_TYPE_LIGHT_ACTIVE = $5; IN_TYPE_LIGHT_INACTIVE = $6; IN_TYPE_SOUND_DB = $7; IN_TYPE_SOUND_DBA = $8; IN_TYPE_CUSTOM = $9; IN_TYPE_LOWSPEED = $A; IN_TYPE_LOWSPEED_9V = $B; IN_TYPE_HISPEED = $C; IN_TYPE_COLORFULL = $D; IN_TYPE_COLORRED = $E; IN_TYPE_COLORGREEN = $F; IN_TYPE_COLORBLUE = $10; IN_TYPE_COLORNONE = $11; // flags passed into the Mode field of the RCXInput const IN_MODE_RAW = $00; IN_MODE_BOOLEAN = $20; IN_MODE_TRANSITIONCNT = $40; IN_MODE_PERIODCOUNTER = $60; IN_MODE_PCTFULLSCALE = $80; IN_MODE_CELSIUS = $A0; IN_MODE_FAHRENHEIT = $C0; IN_MODE_ANGLESTEP = $E0; IN_MODE_SLOPEMASK = $1F; IN_MODE_MODEMASK = $E0; const UpdateFlags = 0; OutputMode = 1; Power = 2; ActualSpeed = 3; TachoCount = 4; TachoLimit = 5; RunState = 6; TurnRatio = 7; RegMode = 8; Overloaded = 9; RegPValue = 10; RegIValue = 11; RegDValue = 12; BlockTachoCount = 13; RotationCount = 14; OutputOptions = 15; MaxSpeed = 16; MaxAcceleration = 17; const InputType = 0; InputMode = 1; RawValue = 2; NormalizedValue = 3; ScaledValue = 4; InvalidData = 5; // IOMap Constants const STAT_MSG_EMPTY_MAILBOX = 64; //Specified mailbox contains no new messages STAT_COMM_PENDING = 32; //Pending setup operation in progress const STOP_REQ = 5; BREAKOUT_REQ = 4; PC_OVERRIDE = 3; CLUMP_SUSPEND = 2; CLUMP_DONE = 1; NO_ERR = 0; const //Fatal errors ERR_ARG = ShortInt($FF); //0xFF Bad arguments; ERR_INSTR = ShortInt($FE); //0xFE Illegal bytecode instruction; ERR_FILE = ShortInt($FD); //0xFD Mal-formed file contents; ERR_VER = ShortInt($FC); //0xFC Version mismatch between firmware and compiler; ERR_MEM = ShortInt($FB); //0xFB Insufficient memory available; ERR_BAD_PTR = ShortInt($FA); //0xFA Someone passed us a bad pointer!; ERR_CLUMP_COUNT = ShortInt($F9); // //(FileClumpCount == 0 || FileClumpCount >= NOT_A_CLUMP) ERR_NO_CODE = ShortInt($F8); // VarsCmd.CodespaceCount == 0 */ ERR_INSANE_OFFSET = ShortInt($F7); // CurrOffset != (DataSize - VarsCmd.CodespaceCount * 2) */ ERR_BAD_POOL_SIZE = ShortInt($F6); // VarsCmd.PoolSize > POOL_MAX_SIZE */ ERR_LOADER_ERR = ShortInt($F5); // LOADER_ERR(LStatus) != SUCCESS || pData == NULL || DataSize == 0 */ ERR_SPOTCHECK_FAIL = ShortInt($F4); // ((UBYTE*)(VarsCmd.pCodespace) < pData) (c_cmd.c 1893) */ ERR_NO_ACTIVE_CLUMP = ShortInt($F3); // VarsCmd.RunQ.Head == NOT_A_CLUMP */ ERR_DEFAULT_OFFSETS = ShortInt($F2); // (DefaultsOffset != FileOffsets.DynamicDefaults) || (DefaultsOffset + FileOffsets.DynamicDefaultsSize != FileOffsets.DSDefaultsSize) */ ERR_MEMMGR_FAIL = ShortInt($F1); // (UBYTE *)VarsCmd.MemMgr.pDopeVectorArray != VarsCmd.pDataspace + DV_ARRAY[0].Offset */ //General errors ERR_INVALID_PORT = ShortInt($F0); // Bad input or output port specified ERR_INVALID_FIELD = ShortInt($EF); // Attempted to access invalid field of a structure ERR_INVALID_QUEUE = ShortInt($EE); // Illegal queue ID specified ERR_INVALID_SIZE = ShortInt($ED); // Illegal size specified ERR_NO_PROG = ShortInt($EC); // No active program //Communications specific errors ERR_COMM_CHAN_NOT_READY = ShortInt($E0); // Specified channel/connection not configured or busy ERR_COMM_CHAN_INVALID = ShortInt($DF); // Specified channel/connection is not valid ERR_COMM_BUFFER_FULL = ShortInt($DE); // No room in comm buffer ERR_COMM_BUS_ERR = ShortInt($DD); // Something went wrong on the communications bus //Remote control ("direct commands") errors ERR_RC_ILLEGAL_VAL = ShortInt($C0); // Data contains out-of-range values ERR_RC_BAD_PACKET = ShortInt($BF); // Clearly insane packet ERR_RC_UNKNOWN_CMD = ShortInt($BE); // Unknown command opcode ERR_RC_FAILED = ShortInt($BD); // Request failed (i.e. specified file not found) function IS_ERR(Status : Integer) : boolean; function IS_FATAL(Status : Integer) : boolean; const RC_START_PROGRAM = 0; RC_STOP_PROGRAM = 1; RC_PLAY_SOUND_FILE = 2; RC_PLAY_TONE = 3; RC_SET_OUT_STATE = 4; RC_SET_IN_MODE = 5; RC_GET_OUT_STATE = 6; RC_GET_IN_VALS = 7; RC_RESET_IN_VAL = 8; RC_MESSAGE_WRITE = 9; RC_RESET_POSITION = 10; RC_GET_BATT_LVL = 11; RC_STOP_SOUND = 12; RC_KEEP_ALIVE = 13; RC_LS_GET_STATUS = 14; RC_LS_WRITE = 15; RC_LS_READ = 16; RC_GET_CURR_PROGRAM = 17; RC_GET_BUTTON_STATE = 18; RC_MESSAGE_READ = 19; NUM_RC_OPCODES = 20; const // ProgStatus PROG_IDLE = 0; PROG_OK = 1; //PROG_OK: Last program finished normally. PROG_RUNNING = 2; //PROG_RUNNING: Program currently running PROG_ERROR = 3; //PROG_ERROR: Last program ended because of an error PROG_ABORT = 4; //PROG_ABORT: Last program ended because of (user) abort PROG_RESET = 5; const POOL_MAX_SIZE = 32768; //Maximum size of memory pool, in bytes const VM_FORMAT_STRING = 'MindstormsNXT'; VM_FORMAT_STRING_SIZE = 16; VM_OLDEST_COMPATIBLE_VERSION = $0004; FIRMWARE_VERSION = $0; const NOT_A_HANDLE = $FF; NOT_A_CLUMP = $FF; NOT_AN_ELEMENT = $FFFF; NOT_A_DS_ID = $FFFF; NOT_AN_OFFSET = $FFFF; MAX_CLUMPS = 255; const DV_ARRAY_GROWTH_COUNT = 5; DS_DEFAULT_DEFAULT = 1; const // VM_STATE VM_IDLE = 0; //VM_IDLE: Just sitting around. Request to run program will lead to ONE of the VM_RUN* states. VM_RUN_FREE = 1; //VM_RUN_FREE: Attempt to run as many instructions as possible within our timeslice VM_RUN_SINGLE = 2; //VM_RUN_SINGLE: Run exactly one instruction per timeslice VM_RUN_PAUSE = 3; //VM_RUN_PAUSE: Program still "active", but someone has asked us to pause VM_RESET1 = 4; //VM_RESET2: Final clean up and return to IDLE VM_RESET2 = 5; //VM_RESET1: Initialize state variables and some I/O devices -- executed when programs end const SUCCESS = $0000; INPROGRESS = $0001; REQPIN = $0002; NOMOREHANDLES = $8100; NOSPACE = $8200; NOMOREFILES = $8300; EOFEXSPECTED = $8400; ENDOFFILE = $8500; NOTLINEARFILE = $8600; FILENOTFOUND = $8700; HANDLEALREADYCLOSED = $8800; NOLINEARSPACE = $8900; UNDEFINEDERROR = $8A00; FILEISBUSY = $8B00; NOWRITEBUFFERS = $8C00; APPENDNOTPOSSIBLE = $8D00; FILEISFULL = $8E00; FILE_EXISTS = $8F00; MODULENOTFOUND = $9000; OUTOFBOUNDERY = $9100; ILLEGALFILENAME = $9200; ILLEGALHANDLE = $9300; BTBUSY = $9400; BTCONNECTFAIL = $9500; BTTIMEOUT = $9600; FILETX_TIMEOUT = $9700; FILETX_DSTEXISTS = $9800; FILETX_SRCMISSING = $9900; FILETX_STREAMERROR = $9A00; FILETX_CLOSEERROR = $9B00; const MESSAGES_PER_QUEUE = 5; MESSAGE_QUEUE_COUNT = 20; INCOMING_QUEUE_COUNT = MESSAGE_QUEUE_COUNT div 2; NOT_A_QUEUE = $FF; MAX_MESSAGE_SIZE = 59; // IOMAP Offsets const CommandOffsetFormatString = 0; CommandOffsetPRCHandler = $10; CommandOffsetTick = $14; CommandOffsetOffsetDS = $18; CommandOffsetOffsetDVA = $1A; CommandOffsetProgStatus = $1C; CommandOffsetAwake = $1D; CommandOffsetActivateFlag = $1E; CommandOffsetDeactivateFlag = $1F; CommandOffsetFileName = $20; CommandOffsetMemoryPool = $34; // 32768 bytes (* varsCmd information pCodespace: pointer for flat codespace (stored in flash, includes all clumps) CodespaceCount: count of code words pAllClumps: Pointer to list of CLUMP_RECs AllClumpsCount: Count of CLUMP_RECs in list RunQ: Head and tail of run queue (elements in-place in AllClumps list) ScratchPC: Temp PC value for control flow instructions pDataspaceTOC: Pointer to DSTOC entries (stored in flash) DataspaceCount: Count of entries in DSTOC pDataspace: Base pointer of actual dataspace DataspaceSize: Size, in bytes, of dataspace DSStaticSize: Size, in bytes, of static portion of the dataspace (used as an offset to the dynamic dataspace) VMState: Internal state of VM's loader/scheduler (cCmdCtrl()) MemMgr: Contains data to manage dynamic arrays PoolSize: Current size of main memory pool, in bytes. Pool: Static pool of bytes for stashing all program run-time data ActiveProgHandle: Handle of the program that is currently running NOTES ON THE ABOVE STRUCTURES The main memory pool is used for all clump records, dataspace tracking data, and the dataspace itself. In other words, pAllClumps and pDataspace must all point to memory within the pool. Watch for RCX_ASSERTs to enforce safe indexing into the pool. *) const ClumpRecOffsetCodeStart = $00; // 2 bytes ClumpRecOffsetCodeEnd = $02; // 2 bytes ClumpRecOffsetPC = $04; // 2 bytes ClumpRecOffsetInitFireCount = $06; // 1 byte ClumpRecOffsetCurrFireCount = $07; // 1 byte ClumpRecOffsetLink = $08; // 1 byte ClumpRecOffsetPriority = $09; // 1 byte ClumpRecOffsetPadBytes = $0A; // 2 bytes ClumpRecOffsetPDependents = $0C; // 4 bytes (UBYTE*) ClumpRecOffsetDependentCount = $10; // 1 byte ClumpRecOffsetPadBytes2 = $11; // 3 bytes ClumpRecSize = 20; // total size = 20 bytes ($14) const DSTOCEntryOffsetTypeCode = 0; // 1 byte DSTOCEntryOffsetFlags = 1; // 1 byte DSTOCEntryOffsetDSOffset = 2; // 2 bytes DSTOCEntrySize = 4; const DopeVectorOffsetOffset = 0; // 2 bytes DopeVectorOffsetElemSize = 2; // 2 bytes DopeVectorOffsetCount = 4; // 2 bytes DopeVectorOffsetBackPtr = 6; // 2 bytes DopeVectorOffsetLink = 8; // 2 bytes DopeVectorSize = 10; const MemMgrOffsetHead = 0; // 2 bytes MemMgrOffsetTail = 2; // 2 bytes MemMgrOffsetFreeHead = 4; // 2 bytes MemMgrOffsetPDopeVectorArray = 6; // 4 bytes (DOPE_VECTOR*) MemMgrSize = 10; const ClumpQueueOffsetHead = 0; // 1 byte ClumpQueueOffsetTail = 1; // 1 byte ClumpQueueSize = 2; const MessageQueueOffsetReadIndex = 0; // 2 bytes MessageQueueOffsetWriteIndex = 2; // 2 bytes MessageQueueOffsetMessages = 4; // 10 bytes (UWORD[5]) MessageQueueSize = 14; const VarsCmdOffsetBase = $8034; // varsCmd record lives just past the end of the IOMapCmd record (above) VarsCmdOffsetPCodespace = $8034; // 4 bytes (SWORD*) VarsCmdOffsetPAllClumps = $8038; // 4 bytes (CLUMP_REC*) (see above for ClumpRec offsets) VarsCmdOffsetPDataspaceTOC = $803C; // 4 bytes (DS_TOC_ENTRY*) (see above for DSTOCEntry offsets) VarsCmdOffsetPDataspace = $8040; // 4 bytes (UBYTE *) VarsCmdOffsetPool = $8044; // 4 bytes (UBYTE *) VarsCmdOffsetPoolSize = $8048; // 4 bytes (ULONG) VarsCmdOffsetCodespaceCount = $804C; // 2 bytes (UWORD) VarsCmdOffsetAllClumpsCount = $804E; // 1 byte (UBYTE) VarsCmdOffsetDataspaceCount = $804F; // 2 byte (UWORD) VarsCmdOffsetDataspaceSize = $8051; // 2 byte (UWORD) VarsCmdOffsetDSStaticSize = $8053; // 2 byte (UWORD) VarsCmdOffsetVMState = $8055; // 1 byte ????? (VM_STATE enum) VarsCmdOffsetMemMgr = $8056; // 10 bytes (MEM_MGR struct) VarsCmdOffsetMemMgrHead = VarsCmdOffsetMemMgr + 0; // 2 bytes VarsCmdOffsetMemMgrTail = VarsCmdOffsetMemMgr + 2; // 2 bytes VarsCmdOffsetMemMgrFreeHead = VarsCmdOffsetMemMgr + 4; // 2 bytes VarsCmdOffsetMemMgrPDopeVectorArray = VarsCmdOffsetMemMgr + 6; // 4 bytes (DOPE_VECTOR*) VarsCmdOffsetRunQ = $8060; // 2 bytes (CLUMP_Q) VarsCmdOffsetRunQHead = VarsCmdOffsetRunQ + 0; // 1 byte (CLUMP_Q.Head) VarsCmdOffsetRunQTail = VarsCmdOffsetRunQ + 1; // 1 byte (CLUMP_Q.Tail) VarsCmdOffsetScratchPC = $8062; // 2 bytes (UWORD) VarsCmdOffsetCallerClump = $8064; // 1 byte (UBYTE) VarsCmdOffsetActiveProgHandle = $8065; // 1 byte (UBYTE) VarsCmdOffsetActiveProgName = $8066; // 20 bytes (filename) VarsCmdOffsetFileHandleTable = $807A; // 336 bytes VarsCmdOffsetMessageQueues = $81CA; // 280 bytes VarsCmdOffsetCommStat = $82E2; // 2 bytes VarsCmdOffsetCommStatReset = $82E4; // 2 bytes VarsCmdOffsetCommCurrConn = $82E6; // 1 byte VarsCmdOffsetDirtyComm = $82E7; // 1 byte VarsCmdOffsetDirtyDisplay = $82E8; // 1 byte VarsCmdOffsetStartTick = $82E9; // 4 bytes // ifdef VM_BENCHMARK VarsCmdOffsetInstrCount = $82ED; // 4 bytes VarsCmdOffsetAverage = $82F1; // 4 bytes VarsCmdOffsetOverTimeCount = $82F5; // 4 bytes VarsCmdOffsetMaxOverTimeLength = $82F9; // 4 bytes VarsCmdOffsetCmdCtrlCount = $82FD; // 4 bytes VarsCmdOffsetCompactionCount = $8301; // 4 bytes VarsCmdOffsetLastCompactionTick = $8305; // 4 bytes VarsCmdOffsetMaxCompactionTime = $8309; // 4 bytes VarsCmdOffsetOpcodeBenchmarks = $830D; // 864 bytes VarCmdOffsetSyscallBenchmarks = $866D; // 544 bytes VarCmdOffsetBuffer = $888D; // 256 bytes; // ifdef ARM_DEBUG VarCmdOffsetAssertFlag = $898D; // 1 byte VarCmdOffsetAssertLine = $898E; // 4 bytes function VarCmdOffsetFHT(const i : byte) : word; function VarCmdOffsetFHTHandle(const i : byte) : word; function VarCmdOffsetFHTFilename(const i : byte) : word; function VarCmdOffsetMessageQueue(const queue : byte) : word; function VarCmdOffsetMessageQueueReadIndex(const queue : byte) : word; function VarCmdOffsetMessageQueueWriteIndex(const queue : byte) : word; function VarCmdOffsetMessageQueueMessage(const queue, msg : byte) : word; // VarsCmdOffsetOpcodeBenchmarks[54][4]; // VarsCmdOffsetSyscallBenchmarks[34][4]; const IOCtrlOffsetPowerOn = 0; const LoaderOffsetPFunc = 0; LoaderOffsetFreeUserFlash = 4; const // error codes LDR_SUCCESS = $0000; LDR_INPROGRESS = $0001; LDR_REQPIN = $0002; LDR_NOMOREHANDLES = $8100; LDR_NOSPACE = $8200; LDR_NOMOREFILES = $8300; LDR_EOFEXSPECTED = $8400; LDR_ENDOFFILE = $8500; LDR_NOTLINEARFILE = $8600; LDR_FILENOTFOUND = $8700; LDR_HANDLEALREADYCLOSED = $8800; LDR_NOLINEARSPACE = $8900; LDR_UNDEFINEDERROR = $8A00; LDR_FILEISBUSY = $8B00; LDR_NOWRITEBUFFERS = $8C00; LDR_APPENDNOTPOSSIBLE = $8D00; LDR_FILEISFULL = $8E00; LDR_FILEEXISTS = $8F00; LDR_MODULENOTFOUND = $9000; LDR_OUTOFBOUNDERY = $9100; LDR_ILLEGALFILENAME = $9200; LDR_ILLEGALHANDLE = $9300; LDR_BTBUSY = $9400; LDR_BTCONNECTFAIL = $9500; LDR_BTTIMEOUT = $9600; LDR_FILETX_TIMEOUT = $9700; LDR_FILETX_DSTEXISTS = $9800; LDR_FILETX_SRCMISSING = $9900; LDR_FILETX_STREAMERROR = $9A00; LDR_FILETX_CLOSEERROR = $9B00; const SoundOffsetFreq = 0; SoundOffsetDuration = 2; SoundOffsetSampleRate = 4; SoundOffsetSoundFilename = 6; SoundOffsetFlags = 26; SoundOffsetState = 27; SoundOffsetMode = 28; SoundOffsetVolume = 29; const ButtonOffsetPressedCnt0 = 0; ButtonOffsetLongPressCnt0 = 1; ButtonOffsetShortRelCnt0 = 2; ButtonOffsetLongRelCnt0 = 3; ButtonOffsetRelCnt0 = 4; ButtonOffsetPressedCnt1 = 8; ButtonOffsetLongPressCnt1 = 9; ButtonOffsetShortRelCnt1 = 10; ButtonOffsetLongRelCnt1 = 11; ButtonOffsetRelCnt1 = 12; ButtonOffsetPressedCnt2 = 16; ButtonOffsetLongPressCnt2 = 17; ButtonOffsetShortRelCnt2 = 18; ButtonOffsetLongRelCnt2 = 19; ButtonOffsetRelCnt2 = 20; ButtonOffsetPressedCnt3 = 24; ButtonOffsetLongPressCnt3 = 25; ButtonOffsetShortRelCnt3 = 26; ButtonOffsetLongRelCnt3 = 27; ButtonOffsetRelCnt3 = 28; ButtonOffsetState0 = 32; ButtonOffsetState1 = 33; ButtonOffsetState2 = 34; ButtonOffsetState3 = 35; const PRESSED_EV = $01; SHORT_RELEASED_EV = $02; LONG_PRESSED_EV = $04; LONG_RELEASED_EV = $08; PRESSED_STATE = $80; const UIOffsetPMenu = 0; UIOffsetBatteryVoltage = 4; UIOffsetLMSfilename = 6; UIOffsetFlags = 26; UIOffsetState = 27; UIOffsetButton = 28; UIOffsetRunState = 29; UIOffsetBatteryState = 30; UIOffsetBluetoothState = 31; UIOffsetUsbState = 32; UIOffsetSleepTimeout = 33; UIOffsetSleepTimer = 34; UIOffsetRechargeable = 35; UIOffsetVolume = 36; UIOffsetError = 37; UIOffsetOBPPointer = 38; UIOffsetForceOff = 39; const InputOffsetCustomZeroOffset0 = 0; InputOffsetADRaw0 = 2; InputOffsetSensorRaw0 = 4; InputOffsetSensorValue0 = 6; InputOffsetSensorType0 = 8; InputOffsetSensorMode0 = 9; InputOffsetSensorBoolean0 = 10; InputOffsetDigiPinsDir0 = 11; InputOffsetDigiPinsIn0 = 12; InputOffsetDigiPinsOut0 = 13; InputOffsetCustomPctFullScale0 = 14; InputOffsetCustomActiveStatus0 = 15; InputOffsetInvalidData0 = 16; InputOffsetSpare10 = 17; InputOffsetSpare20 = 18; InputOffsetSpare30 = 19; InputOffsetCustomZeroOffset1 = 20; InputOffsetADRaw1 = 22; InputOffsetSensorRaw1 = 24; InputOffsetSensorValue1 = 26; InputOffsetSensorType1 = 28; InputOffsetSensorMode1 = 29; InputOffsetSensorBoolean1 = 30; InputOffsetDigiPinsDir1 = 31; InputOffsetDigiPinsIn1 = 32; InputOffsetDigiPinsOut1 = 33; InputOffsetCustomPctFullScale1 = 34; InputOffsetCustomActiveStatus1 = 35; InputOffsetInvalidData1 = 36; InputOffsetSpare11 = 37; InputOffsetSpare21 = 38; InputOffsetSpare31 = 39; InputOffsetCustomZeroOffset2 = 40; InputOffsetADRaw2 = 42; InputOffsetSensorRaw2 = 44; InputOffsetSensorValue2 = 46; InputOffsetSensorType2 = 48; InputOffsetSensorMode2 = 49; InputOffsetSensorBoolean2 = 50; InputOffsetDigiPinsDir2 = 51; InputOffsetDigiPinsIn2 = 52; InputOffsetDigiPinsOut2 = 53; InputOffsetCustomPctFullScale2 = 54; InputOffsetCustomActiveStatus2 = 55; InputOffsetInvalidData2 = 56; InputOffsetSpare12 = 57; InputOffsetSpare22 = 58; InputOffsetSpare32 = 59; InputOffsetCustomZeroOffset3 = 60; InputOffsetADRaw3 = 63; InputOffsetSensorRaw3 = 64; InputOffsetSensorValue3 = 66; InputOffsetSensorType3 = 68; InputOffsetSensorMode3 = 69; InputOffsetSensorBoolean3 = 70; InputOffsetDigiPinsDir3 = 71; InputOffsetDigiPinsIn3 = 72; InputOffsetDigiPinsOut3 = 73; InputOffsetCustomPctFullScale3 = 74; InputOffsetCustomActiveStatus3 = 75; InputOffsetInvalidData3 = 76; InputOffsetSpare13 = 77; InputOffsetSpare23 = 78; InputOffsetSpare33 = 79; const OutputOffsetTachoCnt0 = 0; OutputOffsetBlockTachoCount0 = 4; OutputOffsetRotationCount0 = 8; OutputOffsetTachoLimit0 = 12; OutputOffsetMotorRPM0 = 16; OutputOffsetFlags0 = 18; OutputOffsetMode0 = 19; OutputOffsetSpeed0 = 20; OutputOffsetActualSpeed0 = 21; OutputOffsetRegPParameter0 = 22; OutputOffsetRegIParameter0 = 23; OutputOffsetRegDParameter0 = 24; OutputOffsetRunState0 = 25; OutputOffsetRegMode0 = 26; OutputOffsetOverloaded0 = 27; OutputOffsetSyncTurnParameter0 = 28; OutputOffsetOptions0 = 29; OutputOffsetMaxSpeed0 = 30; OutputOffsetMaxAcceleration0 = 31; OutputOffsetTachoCnt1 = 32; OutputOffsetBlockTachoCount1 = 36; OutputOffsetRotationCount1 = 40; OutputOffsetTachoLimit1 = 44; OutputOffsetMotorRPM1 = 48; OutputOffsetFlags1 = 50; OutputOffsetMode1 = 51; OutputOffsetSpeed1 = 52; OutputOffsetActualSpeed1 = 53; OutputOffsetRegPParameter1 = 54; OutputOffsetRegIParameter1 = 55; OutputOffsetRegDParameter1 = 56; OutputOffsetRunState1 = 57; OutputOffsetRegMode1 = 58; OutputOffsetOverloaded1 = 59; OutputOffsetSyncTurnParameter1 = 60; OutputOffsetOptions1 = 61; OutputOffsetMaxSpeed1 = 62; OutputOffsetMaxAcceleration1 = 63; OutputOffsetTachoCnt2 = 64; OutputOffsetBlockTachoCount2 = 68; OutputOffsetRotationCount2 = 72; OutputOffsetTachoLimit2 = 76; OutputOffsetMotorRPM2 = 80; OutputOffsetFlags2 = 82; OutputOffsetMode2 = 83; OutputOffsetSpeed2 = 84; OutputOffsetActualSpeed2 = 85; OutputOffsetRegPParameter2 = 86; OutputOffsetRegIParameter2 = 87; OutputOffsetRegDParameter2 = 88; OutputOffsetRunState2 = 89; OutputOffsetRegMode2 = 90; OutputOffsetOverloaded2 = 91; OutputOffsetSyncTurnParameter2 = 92; OutputOffsetOptions2 = 93; OutputOffsetMaxSpeed2 = 94; OutputOffsetMaxAcceleration2 = 95; OutputOffsetRegulationTime = 96; OutputOffsetRegulationOptions = 97; const LowSpeedOffsetInBufBuf0 = 0; LowSpeedOffsetInBufInPtr0 = 16; LowSpeedOffsetInBufOutPtr0 = 17; LowSpeedOffsetInBufBytesToRx0 = 18; LowSpeedOffsetInBufBuf1 = 19; LowSpeedOffsetInBufInPtr1 = 35; LowSpeedOffsetInBufOutPtr1 = 36; LowSpeedOffsetInBufBytesToRx1 = 37; LowSpeedOffsetInBufBuf2 = 38; LowSpeedOffsetInBufInPtr2 = 54; LowSpeedOffsetInBufOutPtr2 = 55; LowSpeedOffsetInBufBytesToRx2 = 56; LowSpeedOffsetInBufBuf3 = 57; LowSpeedOffsetInBufInPtr3 = 73; LowSpeedOffsetInBufOutPtr3 = 74; LowSpeedOffsetInBufBytesToRx3 = 75; LowSpeedOffsetOutBufBuf0 = 76; LowSpeedOffsetOutBufInPtr0 = 92; LowSpeedOffsetOutBufOutPtr0 = 93; LowSpeedOffsetOutBufBytesToRx0 = 94; LowSpeedOffsetOutBufBuf1 = 95; LowSpeedOffsetOutBufInPtr1 = 111; LowSpeedOffsetOutBufOutPtr1 = 112; LowSpeedOffsetOutBufBytesToRx1 = 113; LowSpeedOffsetOutBufBuf2 = 114; LowSpeedOffsetOutBufInPtr2 = 130; LowSpeedOffsetOutBufOutPtr2 = 131; LowSpeedOffsetOutBufBytesToRx2 = 132; LowSpeedOffsetOutBufBuf3 = 133; LowSpeedOffsetOutBufInPtr3 = 149; LowSpeedOffsetOutBufOutPtr3 = 150; LowSpeedOffsetOutBufBytesToRx3 = 151; LowSpeedOffsetMode0 = 152; LowSpeedOffsetMode1 = 153; LowSpeedOffsetMode2 = 154; LowSpeedOffsetMode3 = 155; LowSpeedOffsetChannelState0 = 156; LowSpeedOffsetChannelState1 = 157; LowSpeedOffsetChannelState2 = 158; LowSpeedOffsetChannelState3 = 159; LowSpeedOffsetErrorType0 = 160; LowSpeedOffsetErrorType1 = 161; LowSpeedOffsetErrorType2 = 162; LowSpeedOffsetErrorType3 = 163; LowSpeedOffsetState = 164; LowSpeedOffsetSpeed = 165; LowSpeedOffsetSpare = 166; const // Constants related to simple draw entry (x = dont care) DISPLAY_ERASE_ALL = $00; // W - erase entire screen (CMD,x,x,x,x,x) DISPLAY_PIXEL = $01; // W - set pixel (on/off) (CMD,TRUE/FALSE,X,Y,x,x) DISPLAY_HORIZONTAL_LINE = $02; // W - draw horisontal line (CMD,TRUE,X1,Y1,X2,x) DISPLAY_VERTICAL_LINE = $03; // W - draw vertical line (CMD,TRUE,X1,Y1,x,Y2) DISPLAY_CHAR = $04; // W - draw char (actual font) (CMD,TRUE,X1,Y1,Char,x) // Constants related to Flags DISPLAY_ON = $01; // W - Display on DISPLAY_REFRESH = $02; // W - Enable refresh DISPLAY_POPUP = $08; // W - Use popup display memory DISPLAY_REFRESH_DISABLED = $40; // R - Refresh disabled DISPLAY_BUSY = $80; // R - Refresh in progress DISPLAY_HEIGHT = 64; // Y pixels DISPLAY_WIDTH = 100; // X pixels DISPLAY_MENUICONS_Y = 40; DISPLAY_MENUICONS_X_OFFS = 7; DISPLAY_MENUICONS_X_DIFF = 31; // Used in macro "TEXTLINE_BIT" TEXTLINE_1 = 0; // Upper most line TEXTLINE_2 = 1; // TEXTLINE_3 = 2; // TEXTLINE_4 = 3; // TEXTLINE_5 = 4; // TEXTLINE_6 = 5; // TEXTLINE_7 = 6; // TEXTLINE_8 = 7; // Bottom line TEXTLINES = 8; // Used in macro "MENUICON_BIT" MENUICON_LEFT = 0; // Left icon MENUICON_CENTER = 1; // Center icon MENUICON_RIGHT = 2; // Right icon MENUICONS = 3; // Used in macro "SPECIAL_BIT" FRAME_SELECT = 0; // Center icon select frame STATUSTEXT = 1; // Status text (BT name) MENUTEXT = 2; // Center icon text STEPLINE = 3; // Step collection lines TOPLINE = 4; // Top status underline SPECIALS = 5; // Used in macro "STATUSICON_BIT" STATUSICON_BLUETOOTH = 0; // BlueTooth status icon collection STATUSICON_USB = 1; // USB status icon collection STATUSICON_VM = 2; // VM status icon collection STATUSICON_BATTERY = 3; // Battery status icon collection STATUSICONS = 4; SCREENBIT = $20000000; // Used in macro "SCREEN_BIT" SCREEN_BACKGROUND = 0; // Entire screen SCREEN_LARGE = 1; // Entire screen except status line SCREEN_SMALL = 2; // Screen between menu icons and status line SCREENS = 3; // Used in macro "BITMAP_BIT" BITMAP_1 = 0; // Bitmap 1 BITMAP_2 = 1; // Bitmap 2 BITMAP_3 = 2; // Bitmap 3 BITMAP_4 = 3; // Bitmap 4 BITMAPS = 4; // Used in macro "STEPICON_BIT" STEPICON_1 = 0; // Left most step icon STEPICON_2 = 1; // STEPICON_3 = 2; // STEPICON_4 = 3; // STEPICON_5 = 4; // Right most step icon STEPICONS = 5; SCREEN_BITS = ($E0000000); // Executed as 1. STEPICON_BITS = ($1F000000); // Executed as 2. BITMAP_BITS = ($00F00000); // Executed as 3. MENUICON_BITS = ($000E0000); // Executed as 4. STATUSICON_BITS = ($0001E000); // Executed as 5. SPECIAL_BITS = ($00001F00); // Executed as 6. TEXTLINE_BITS = ($000000FF); // Executed as 7. function SCREEN_BIT(const No : byte) : Cardinal; function STEPICON_BIT(const No : byte) : Cardinal; function BITMAP_BIT(const No : byte) : Cardinal; function MENUICON_BIT(const No : byte) : Cardinal; function STATUSICON_BIT(const No : byte) : Cardinal; function SPECIAL_BIT(const No : byte) : Cardinal; function TEXTLINE_BIT(const No : byte) : Cardinal; const DisplayOffsetPFunc = 0; // Simple draw entry DisplayOffsetEraseMask = 4; // Section erase mask (executed first) DisplayOffsetUpdateMask = 8; // Section update mask (executed next) DisplayOffsetPFont = 12; // Pointer to font file DisplayOffsetPStatusText = 48; // Pointer to status text string DisplayOffsetPStatusIcons = 52; // Pointer to status icon collection file DisplayOffsetPMenuText = 84; // Pointer to menu icon text (NULL == none) DisplayOffsetPStepIcons = 100; // Pointer to step icon collection file DisplayOffsetDisplay = 104; // Display content copied to physical display every 17 mS DisplayOffsetFlags = 117; // Update flags enumerated above DisplayOffsetTextLinesCenterFlags = 118; // Mask to center TextLines function DisplayOffsetPTextLines(const p : byte) : word; // Pointer to text strings function DisplayOffsetPScreens(const p : byte) : word; // Pointer to screen bitmap file function DisplayOffsetPBitmaps(const p : byte) : word; // Pointer to free bitmap files function DisplayOffsetPMenuIcons(const p : byte) : word; // Pointer to menu icon images (NULL == none) function DisplayOffsetStatusIcons(const p : byte) : word; // Index in status icon collection file (index = 0 -> none) function DisplayOffsetStepIcons(const p : byte) : word; // Index in step icon collection file (index = 0 -> none) function DisplayOffsetNormal(const h, w : byte) : word; // Raw display memory for normal screen function DisplayOffsetPopup(const h, w : byte) : word; // Raw display memory for normal screen const CommOffsetPFunc = 0; CommOffsetPFuncTwo = 4; CommOffsetBrickDataName = 1126; CommOffsetBrickDataBluecoreVersion = 1142; CommOffsetBrickDataBdAddr = 1144; CommOffsetBrickDataBtStateStatus = 1151; CommOffsetBrickDataBtHwStatus = 1152; CommOffsetBrickDataTimeOutValue = 1153; CommOffsetBrickDataSpareOne = 1154; CommOffsetBrickDataSpareTwo = 1155; CommOffsetBrickDataSpareThree = 1156; CommOffsetBtInBufBuf = 1157; CommOffsetBtInBufInPtr = 1285; CommOffsetBtInBufOutPtr = 1286; CommOffsetBtInBufSpareOne = 1287; CommOffsetBtInBufSpareTwo = 1288; CommOffsetBtOutBufBuf = 1289; CommOffsetBtOutBufInPtr = 1417; CommOffsetBtOutBufOutPtr = 1418; CommOffsetBtOutBufSpareOne = 1419; CommOffsetBtOutBufSpareTwo = 1420; CommOffsetHsInBufBuf = 1421; CommOffsetHsInBufInPtr = 1549; CommOffsetHsInBufOutPtr = 1550; CommOffsetHsInBufSpareOne = 1551; CommOffsetHsInBufSpareTwo = 1552; CommOffsetHsOutBufBuf = 1553; CommOffsetHsOutBufInPtr = 1681; CommOffsetHsOutBufOutPtr = 1682; CommOffsetHsOutBufSpareOne = 1683; CommOffsetHsOutBufSpareTwo = 1684; CommOffsetUsbInBufBuf = 1685; CommOffsetUsbInBufInPtr = 1749; CommOffsetUsbInBufOutPtr = 1750; CommOffsetUsbInBufSpareOne = 1751; CommOffsetUsbInBufSpareTwo = 1752; CommOffsetUsbOutBufBuf = 1753; CommOffsetUsbOutBufInPtr = 1817; CommOffsetUsbOutBufOutPtr = 1818; CommOffsetUsbOutBufSpareOne = 1819; CommOffsetUsbOutBufSpareTwo = 1820; CommOffsetUsbPollBufBuf = 1821; CommOffsetUsbPollBufInPtr = 1885; CommOffsetUsbPollBufOutPtr = 1886; CommOffsetUsbPollBufSpareOne = 1887; CommOffsetUsbPollBufSpareTwo = 1888; CommOffsetBtDeviceCnt = 1889; CommOffsetBtDeviceNameCnt = 1890; CommOffsetHsFlags = 1891; CommOffsetHsSpeed = 1892; CommOffsetHsState = 1893; CommOffsetUsbState = 1894; function CommOffsetBtDeviceTableName(const p : byte) : word; function CommOffsetBtDeviceTableClassOfDevice(const p : byte) : word; function CommOffsetBtDeviceTableBdAddr(const p : byte) : word; function CommOffsetBtDeviceTableDeviceStatus(const p : byte) : word; function CommOffsetBtDeviceTableSpareOne(const p : byte) : word; function CommOffsetBtDeviceTableSpareTwo(const p : byte) : word; function CommOffsetBtDeviceTableSpareThree(const p : byte) : word; function CommOffsetBtConnectTableName(const p : byte) : word; function CommOffsetBtConnectTableClassOfDevice(const p : byte) : word; function CommOffsetBtConnectTablePinCode(const p : byte) : word; function CommOffsetBtConnectTableBdAddr(const p : byte) : word; function CommOffsetBtConnectTableHandleNr(const p : byte) : word; function CommOffsetBtConnectTableStreamStatus(const p : byte) : word; function CommOffsetBtConnectTableLinkQuality(const p : byte) : word; function CommOffsetBtConnectTableSpare(const p : byte) : word; function CCToStr(const cc : integer) : string; function NXTInputTypeToStr(const stype : integer) : string; function NXTInputModeToStr(const smode : integer) : string; function NXTOutputModeToStr(const mode : integer) : string; function NXTOutputRunStateToStr(const runstate : integer) : string; function NXTOutputRegModeToStr(const regmode : integer) : string; const TONES : array[3..9,0..11] of Word = ( // C C# D D# E F F# G G# A A# B ( 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247), ( 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494), ( 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988), ( 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976), ( 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951), ( 4186, 4434, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7458, 7902), ( 8372, 8868, 9396, 9956,10548,11176,11840,12544,13288,14080,14916,15804) ); const HTPF_CMD_FWD = $1; HTPF_CMD_REV = $2; HTPF_CMD_BRAKE = $3; HTPF_CHANNEL_1 = $0; HTPF_CHANNEL_2 = $1; HTPF_CHANNEL_3 = $2; HTPF_CHANNEL_4 = $3; PF_MODE_TRAIN = $0; PF_MODE_COMBO_DIRECT = $1; PF_MODE_SINGLE_PIN_CONT = $2; PF_MODE_SINGLE_PIN_TIME = $3; PF_MODE_COMBO_PWM = $4; PF_MODE_SINGLE_OUTPUT_PWM = $4; PF_MODE_SINGLE_OUTPUT_CST = $6; TRAIN_FUNC_STOP = $0; TRAIN_FUNC_INCR_SPEED = $1; TRAIN_FUNC_DECR_SPEED = $2; TRAIN_FUNC_TOGGLE_LIGHT = $4; TRAIN_CHANNEL_1 = $0; TRAIN_CHANNEL_2 = $1; TRAIN_CHANNEL_3 = $2; TRAIN_CHANNEL_ALL = $3; PF_OUT_A = $0; PF_OUT_B = $1; PF_PIN_C1 = $0; PF_PIN_C2 = $1; PF_FUNC_NOCHANGE = $0; PF_FUNC_CLEAR = $1; PF_FUNC_SET = $2; PF_FUNC_TOGGLE = $3; PF_CST_CLEAR1_CLEAR2 = $0; PF_CST_SET1_CLEAR2 = $1; PF_CST_CLEAR1_SET2 = $2; PF_CST_SET1_SET2 = $3; PF_CST_INCREMENT_PWM = $4; PF_CST_DECREMENT_PWM = $5; PF_CST_FULL_FWD = $6; PF_CST_FULL_REV = $7; PF_CST_TOGGLE_DIR = $8; PF_PWM_FLOAT = $0; PF_PWM_FWD1 = $1; PF_PWM_FWD2 = $2; PF_PWM_FWD3 = $3; PF_PWM_FWD4 = $4; PF_PWM_FWD5 = $5; PF_PWM_FWD6 = $6; PF_PWM_FWD7 = $7; PF_PWM_BRAKE = $8; PF_PWM_REV7 = $9; PF_PWM_REV6 = $a; PF_PWM_REV5 = $b; PF_PWM_REV4 = $c; PF_PWM_REV3 = $d; PF_PWM_REV2 = $e; PF_PWM_REV1 = $f; // HiTechnic IRLink RCX constants RCX_OUT_A = $01; RCX_OUT_B = $02; RCX_OUT_C = $04; RCX_OUT_AB = $03; RCX_OUT_AC = $05; RCX_OUT_BC = $06; RCX_OUT_ABC = $07; RCX_OUT_FLOAT = $0; RCX_OUT_OFF = $40; RCX_OUT_ON = $80; RCX_OUT_REV = $0; RCX_OUT_TOGGLE = $40; RCX_OUT_FWD = $80; RCX_OUT_LOW = $0; RCX_OUT_HALF = $3; RCX_OUT_FULL = $7; RCX_RemoteKeysReleased = $0000; RCX_RemotePBMessage1 = $0100; RCX_RemotePBMessage2 = $0200; RCX_RemotePBMessage3 = $0400; RCX_RemoteOutAForward = $0800; RCX_RemoteOutBForward = $1000; RCX_RemoteOutCForward = $2000; RCX_RemoteOutABackward = $4000; RCX_RemoteOutBBackward = $8000; RCX_RemoteOutCBackward = $0001; RCX_RemoteSelProgram1 = $0002; RCX_RemoteSelProgram2 = $0004; RCX_RemoteSelProgram3 = $0008; RCX_RemoteSelProgram4 = $0010; RCX_RemoteSelProgram5 = $0020; RCX_RemoteStopOutOff = $0040; RCX_RemotePlayASound = $0080; RCX_SOUND_CLICK = $0; RCX_SOUND_DOUBLE_BEEP = $1; RCX_SOUND_DOWN = $2; RCX_SOUND_UP = $3; RCX_SOUND_LOW_BEEP = $4; RCX_SOUND_FAST_UP = $5; SCOUT_LIGHT_ON = $80; SCOUT_LIGHT_OFF = $0; SCOUT_SOUND_REMOTE = $6; SCOUT_SOUND_ENTERSA = $7; SCOUT_SOUND_KEYERROR = $8; SCOUT_SOUND_NONE = $9; SCOUT_SOUND_TOUCH1_PRES = $0a; SCOUT_SOUND_TOUCH1_REL = $0b; SCOUT_SOUND_TOUCH2_PRES = $0c; SCOUT_SOUND_TOUCH2_REL = $0d; SCOUT_SOUND_ENTER_BRIGHT = $0e; SCOUT_SOUND_ENTER_NORMAL = $0f; SCOUT_SOUND_ENTER_DARK = $10; SCOUT_SOUND_1_BLINK = $11; SCOUT_SOUND_2_BLINK = $12; SCOUT_SOUND_COUNTER1 = $13; SCOUT_SOUND_COUNTER2 = $14; SCOUT_SOUND_TIMER1 = $15; SCOUT_SOUND_TIMER2 = $16; SCOUT_SOUND_TIMER3 = $17; SCOUT_SOUND_MAIL_RECEIVED = $18; SCOUT_SOUND_SPECIAL1 = $19; SCOUT_SOUND_SPECIAL2 = $1a; SCOUT_SOUND_SPECIAL3 = $1b; SCOUT_SNDSET_NONE = $0; SCOUT_SNDSET_BASIC = $1; SCOUT_SNDSET_BUG = $2; SCOUT_SNDSET_ALARM = $3; SCOUT_SNDSET_RANDOM = $4; SCOUT_SNDSET_SCIENCE = $5; SCOUT_MODE_STANDALONE = $0; SCOUT_MODE_POWER = $1; SCOUT_MR_NO_MOTION = $0; SCOUT_MR_FORWARD = $1; SCOUT_MR_ZIGZAG = $2; SCOUT_MR_CIRCLE_RIGHT = $3; SCOUT_MR_CIRCLE_LEFT = $4; SCOUT_MR_LOOP_A = $5; SCOUT_MR_LOOP_B = $6; SCOUT_MR_LOOP_AB = $7; SCOUT_TR_IGNORE = $0; SCOUT_TR_REVERSE = $1; SCOUT_TR_AVOID = $2; SCOUT_TR_WAIT_FOR = $3; SCOUT_TR_OFF_WHEN = $4; SCOUT_LR_IGNORE = $0; SCOUT_LR_SEEK_LIGHT = $1; SCOUT_LR_SEEK_DARK = $2; SCOUT_LR_AVOID = $3; SCOUT_LR_WAIT_FOR = $4; SCOUT_LR_OFF_WHEN = $5; SCOUT_TGS_SHORT = $0; SCOUT_TGS_MEDIUM = $1; SCOUT_TGS_LONG = $2; SCOUT_FXR_NONE = $0; SCOUT_FXR_BUG = $1; SCOUT_FXR_ALARM = $2; SCOUT_FXR_RANDOM = $3; SCOUT_FXR_SCIENCE = $4; RCX_VariableSrc = 0; RCX_TimerSrc = 1; RCX_ConstantSrc = 2; RCX_OutputStatusSrc = 3; RCX_RandomSrc = 4; RCX_ProgramSlotSrc = 8; RCX_InputValueSrc = 9; RCX_InputTypeSrc = 10; RCX_InputModeSrc = 11; RCX_InputRawSrc = 12; RCX_InputBooleanSrc = 13; RCX_WatchSrc = 14; RCX_MessageSrc = 15; RCX_GlobalMotorStatusSrc = 17; RCX_ScoutRulesSrc = 18; RCX_ScoutLightParamsSrc = 19; RCX_ScoutTimerLimitSrc = 20; RCX_CounterSrc = 21; RCX_ScoutCounterLimitSrc = 22; RCX_TaskEventsSrc = 23; RCX_ScoutEventFBSrc = 24; RCX_EventStateSrc = 25; RCX_TenMSTimerSrc = 26; RCX_ClickCounterSrc = 27; RCX_UpperThresholdSrc = 28; RCX_LowerThresholdSrc = 29; RCX_HysteresisSrc = 30; RCX_DurationSrc = 31; RCX_UARTSetupSrc = 33; RCX_BatteryLevelSrc = 34; RCX_FirmwareVersionSrc = 35; RCX_IndirectVarSrc = 36; RCX_DatalogSrcIndirectSrc = 37; RCX_DatalogSrcDirectSrc = 38; RCX_DatalogValueIndirectSrc = 39; RCX_DatalogValueDirectSrc = 40; RCX_DatalogRawIndirectSrc = 41; RCX_DatalogRawDirectSrc = 42; RCX_PingOp = $10; RCX_BatteryLevelOp = $30; RCX_DeleteTasksOp = $40; RCX_StopAllTasksOp = $50; RCX_PBTurnOffOp = $60; RCX_DeleteSubsOp = $70; RCX_ClearSoundOp = $80; RCX_ClearMsgOp = $90; RCX_LSCalibrateOp = $c0; RCX_MuteSoundOp = $d0; RCX_UnmuteSoundOp = $e0; RCX_ClearAllEventsOp = $06; RCX_OnOffFloatOp = $21; RCX_IRModeOp = $31; RCX_PlaySoundOp = $51; RCX_DeleteTaskOp = $61; RCX_StartTaskOp = $71; RCX_StopTaskOp = $81; RCX_SelectProgramOp = $91; RCX_ClearTimerOp = $a1; RCX_AutoOffOp = $b1; RCX_DeleteSubOp = $c1; RCX_ClearSensorOp = $d1; RCX_OutputDirOp = $e1; RCX_PlayToneVarOp = $02; RCX_PollOp = $12; RCX_SetWatchOp = $22; RCX_InputTypeOp = $32; RCX_InputModeOp = $42; RCX_SetDatalogOp = $52; RCX_DatalogOp = $62; RCX_SendUARTDataOp = $c2; RCX_RemoteOp = $d2; RCX_VLLOp = $e2; RCX_DirectEventOp = $03; RCX_OutputPowerOp = $13; RCX_PlayToneOp = $23; RCX_DisplayOp = $33; RCX_PollMemoryOp = $63; RCX_SetFeedbackOp = $83; RCX_SetEventOp = $93; RCX_GOutputPowerOp = $a3; RCX_LSUpperThreshOp = $b3; RCX_LSLowerThreshOp = $c3; RCX_LSHysteresisOp = $d3; RCX_LSBlinkTimeOp = $e3; RCX_CalibrateEventOp = $04; RCX_SetVarOp = $14; RCX_SumVarOp = $24; RCX_SubVarOp = $34; RCX_DivVarOp = $44; RCX_MulVarOp = $54; RCX_SgnVarOp = $64; RCX_AbsVarOp = $74; RCX_AndVarOp = $84; RCX_OrVarOp = $94; RCX_UploadDatalogOp = $a4; RCX_SetTimerLimitOp = $c4; RCX_SetCounterOp = $d4; RCX_SetSourceValueOp = $05; RCX_UnlockOp = $15; RCX_BootModeOp = $65; RCX_UnlockFirmOp = $a5; RCX_ScoutRulesOp = $d5; RCX_ViewSourceValOp = $e5; RCX_ScoutOp = $47; RCX_SoundOp = $57; RCX_GOutputModeOp = $67; RCX_GOutputDirOp = $77; RCX_LightOp = $87; RCX_IncCounterOp = $97; RCX_DecCounterOp = $a7; RCX_ClearCounterOp = $b7; RCX_SetPriorityOp = $d7; RCX_MessageOp = $f7; implementation uses SysUtils; function INC_ID(X : Word) : Word; begin Result := Word(X + 1); end; function DisplayOffsetPTextLines(const p : byte) : word; begin Result := Word((Word(p)*4)+16); end; function DisplayOffsetPScreens(const p : byte) : word; begin Result := Word((Word(p)*4)+56); end; function DisplayOffsetPBitmaps(const p : byte) : word; begin Result := Word((Word(p)*4)+68); end; function DisplayOffsetPMenuIcons(const p : byte) : word; begin Result := Word((Word(p)*4)+88); end; function DisplayOffsetStatusIcons(const p : byte) : word; begin Result := Word(Word(p)+108); end; function DisplayOffsetStepIcons(const p : byte) : word; begin Result := Word(Word(p)+112); end; function DisplayOffsetNormal(const h, w : byte) : word; begin Result := Word((Word(h)*100)+Word(w)+119); end; function DisplayOffsetPopup(const h, w : byte) : word; begin Result := Word((Word(h)*100)+Word(w)+919); end; function CommOffsetBtDeviceTableName(const p : byte) : word; begin Result := Word((Word(p)*31)+8); end; function CommOffsetBtDeviceTableClassOfDevice(const p : byte) : word; begin Result := Word((Word(p)*31)+24); end; function CommOffsetBtDeviceTableBdAddr(const p : byte) : word; begin Result := Word((Word(p)*31)+28); end; function CommOffsetBtDeviceTableDeviceStatus(const p : byte) : word; begin Result := Word((Word(p)*31)+35); end; function CommOffsetBtDeviceTableSpareOne(const p : byte) : word; begin Result := Word((Word(p)*31)+36); end; function CommOffsetBtDeviceTableSpareTwo(const p : byte) : word; begin Result := Word((Word(p)*31)+37); end; function CommOffsetBtDeviceTableSpareThree(const p : byte) : word; begin Result := Word((Word(p)*31)+38); end; function CommOffsetBtConnectTableName(const p : byte) : word; begin Result := Word((Word(p)*47)+938); end; function CommOffsetBtConnectTableClassOfDevice(const p : byte) : word; begin Result := Word((Word(p)*47)+954); end; function CommOffsetBtConnectTablePinCode(const p : byte) : word; begin Result := Word((Word(p)*47)+958); end; function CommOffsetBtConnectTableBdAddr(const p : byte) : word; begin Result := Word((Word(p)*47)+974); end; function CommOffsetBtConnectTableHandleNr(const p : byte) : word; begin Result := Word((Word(p)*47)+981); end; function CommOffsetBtConnectTableStreamStatus(const p : byte) : word; begin Result := Word((Word(p)*47)+982); end; function CommOffsetBtConnectTableLinkQuality(const p : byte) : word; begin Result := Word((Word(p)*47)+983); end; function CommOffsetBtConnectTableSpare(const p : byte) : word; begin Result := Word((Word(p)*47)+984); end; function IS_ERR(Status : Integer) : boolean; begin Result := ((Status) < NO_ERR); end; function IS_FATAL(Status : Integer) : boolean; begin Result := (Status < NO_ERR) and (Status >= ERR_BAD_PTR); end; function VarCmdOffsetFHT(const i : byte) : word; begin Result := Word(VarsCmdOffsetFileHandleTable + (i*21)); end; function VarCmdOffsetFHTHandle(const i : byte) : word; begin Result := VarCmdOffsetFHT(i); end; function VarCmdOffsetFHTFilename(const i : byte) : word; begin Result := Word(VarCmdOffsetFHT(i) + 1); end; function VarCmdOffsetMessageQueue(const queue : byte) : word; begin Result := Word(VarsCmdOffsetMessageQueues + (queue*14)); end; function VarCmdOffsetMessageQueueReadIndex(const queue : byte) : word; begin Result := VarCmdOffsetMessageQueue(queue) + MessageQueueOffsetReadIndex; end; function VarCmdOffsetMessageQueueWriteIndex(const queue : byte) : word; begin Result := Word(VarCmdOffsetMessageQueue(queue) + MessageQueueOffsetWriteIndex); end; function VarCmdOffsetMessageQueueMessage(const queue, msg : byte) : word; begin Result := Word(VarCmdOffsetMessageQueue(queue) + MessageQueueOffsetMessages + Word(msg*2)); end; function SCREEN_BIT(const No : byte) : Cardinal; begin Result := ($20000000 shl (No)); end; function STEPICON_BIT(const No : byte) : Cardinal; begin Result := ($01000000 shl (No)); end; function BITMAP_BIT(const No : byte) : Cardinal; begin Result := ($00100000 shl (No)); end; function MENUICON_BIT(const No : byte) : Cardinal; begin Result := ($00020000 shl (No)); end; function STATUSICON_BIT(const No : byte) : Cardinal; begin Result := ($00002000 shl (No)); end; function SPECIAL_BIT(const No : byte) : Cardinal; begin Result := ($00000100 shl (No)); end; function TEXTLINE_BIT(const No : byte) : Cardinal; begin Result := ($00000001 shl (No)); end; function CCToStr(const cc : integer) : string; begin case cc of OPCC1_LT : Result := 'less than'; OPCC1_GT : Result := 'greater than'; OPCC1_LTEQ : Result := 'less than or equal to'; OPCC1_GTEQ : Result := 'greater than or equal to'; OPCC1_EQ : Result := 'equal to'; OPCC1_NEQ : Result := 'not equal to'; else Result := 'unknown' end; end; function NXTInputTypeToStr(const stype : integer) : string; begin case stype of IN_TYPE_NO_SENSOR : Result := 'No Sensor'; IN_TYPE_SWITCH : Result := 'Switch'; IN_TYPE_TEMPERATURE : Result := 'Temperature'; IN_TYPE_REFLECTION : Result := 'Reflection'; IN_TYPE_ANGLE : Result := 'Angle'; IN_TYPE_LIGHT_ACTIVE : Result := 'Light Active'; IN_TYPE_LIGHT_INACTIVE : Result := 'Light Inactive'; IN_TYPE_SOUND_DB : Result := 'Sound DB'; IN_TYPE_SOUND_DBA : Result := 'Sound DBA'; IN_TYPE_CUSTOM : Result := 'Custom'; IN_TYPE_LOWSPEED : Result := 'Lowspeed'; IN_TYPE_LOWSPEED_9V : Result := 'Lowspeed 9v'; IN_TYPE_HISPEED : Result := 'Hispeed'; else Result := Format(HEX_FMT, [stype]); end; end; function NXTInputModeToStr(const smode : integer) : string; begin case (smode and IN_MODE_MODEMASK) of IN_MODE_RAW : Result := 'Raw'; IN_MODE_BOOLEAN : Result := 'Boolean'; IN_MODE_TRANSITIONCNT : Result := 'Transition Count'; IN_MODE_PERIODCOUNTER : Result := 'Period Counter'; IN_MODE_PCTFULLSCALE : Result := 'Percent Full Scale'; IN_MODE_CELSIUS : Result := 'Celsius'; IN_MODE_FAHRENHEIT : Result := 'Fahrenheit'; IN_MODE_ANGLESTEP : Result := 'Angle Step'; else Result := Format(HEX_FMT, [smode and IN_MODE_MODEMASK]); end; if (smode and IN_MODE_SLOPEMASK) <> 0 then Result := Result + Format(' (slope = %d)', [smode and IN_MODE_SLOPEMASK]); end; function NXTOutputModeToStr(const mode : integer) : string; begin case (mode and $F) of OUT_MODE_COAST : Result := 'COAST'; OUT_MODE_MOTORON : Result := 'MOTORON'; OUT_MODE_BRAKE : Result := 'BRAKE'; OUT_MODE_MOTORON + OUT_MODE_BRAKE : Result := 'MOTORON|BRAKE'; OUT_MODE_REGULATED : Result := 'REGULATED'; OUT_MODE_MOTORON + OUT_MODE_REGULATED : Result := 'MOTORON|REGULATED'; OUT_MODE_BRAKE + OUT_MODE_REGULATED : Result := 'BRAKE|REGULATED'; OUT_MODE_BRAKE + OUT_MODE_MOTORON + OUT_MODE_REGULATED : Result := 'MOTORON|BRAKE|REGULATED'; else Result := Format(HEX_FMT, [mode and $F]); end; end; function NXTOutputRunStateToStr(const runstate : integer) : string; begin case (runstate and $F0) of OUT_RUNSTATE_IDLE : Result := 'IDLE'; OUT_RUNSTATE_RAMPUP : Result := 'RAMPUP'; OUT_RUNSTATE_RUNNING : Result := 'RUNNING'; OUT_RUNSTATE_RAMPUP + OUT_RUNSTATE_RUNNING : Result := 'RAMPUP|RUNNING'; OUT_RUNSTATE_RAMPDOWN : Result := 'RAMPDOWN'; OUT_RUNSTATE_RAMPUP + OUT_RUNSTATE_RAMPDOWN : Result := 'RAMPUP|RAMPDOWN'; OUT_RUNSTATE_RUNNING + OUT_RUNSTATE_RAMPDOWN : Result := 'RUNNING|RAMPDOWN'; OUT_RUNSTATE_RAMPUP + OUT_RUNSTATE_RUNNING + OUT_RUNSTATE_RAMPDOWN : Result := 'RAMPUP|RUNNING|RAMPDOWN'; else Result := Format(HEX_FMT, [runstate and $F0]); end; end; function NXTOutputRegModeToStr(const regmode : integer) : string; begin case regmode of OUT_REGMODE_IDLE : Result := 'IDLE'; OUT_REGMODE_SPEED : Result := 'SPEED'; OUT_REGMODE_SYNC : Result := 'SYNC'; else Result := Format(HEX_FMT, [regmode]); end; end; end. NXT/uRICComp.pas0000644000175000017500000026232111537752673013263 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uRICComp; interface uses Classes, Contnrs, uNBCCommon, uRIC, Parser10; type TImgPoint = IMG_PT; TImgRect = IMG_RECT; TImgCanvas = TObject; TRICOps = class(TObjectList) public constructor Create; destructor Destroy; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); end; TRICOpBase = class protected fOwner : TRICOps; fOpSize : Word; fOpCode : Word; function GetOpSize : Word; virtual; public constructor Create(aOwner : TRICOps); virtual; destructor Destroy; override; procedure SaveToStream(aStream : TStream); virtual; procedure LoadFromStream(aStream : TStream); virtual; function SaveAsDataArray(const aLangName: TLangName): string; virtual; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); virtual; abstract; property OpSize : Word read GetOpSize write fOpSize; property OpCode : Word read fOpCode write fOpCode; end; TRICDescription = class(TRICOpBase) protected fOptions : Word; fWidth : Word; fHeight : Word; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property Options : Word read fOptions write fOptions; property Width : Word read fWidth write fWidth; property Height : Word read fHeight write fHeight; end; TByteObject = class private fValue: Byte; public property Value : Byte read fValue write fValue; end; TRICSprite = class(TRICOpBase) protected fDataAddr: Word; fRowBytes: Word; fRows: Word; fBytes : TObjectList; function GetByteCount: Integer; function GetByte(Index: Integer): Byte; procedure SetByte(Index: Integer; const Value: Byte); function GetOpSize : Word; override; function BytesToWrite : Integer; function GetByteValue(const idx : integer) : Byte; public constructor Create(aOwner : TRICOps); override; destructor Destroy; override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; procedure Add(aValue : Byte); property DataAddr : Word read fDataAddr write fDataAddr; property Rows : Word read fRows write fRows; property RowBytes : Word read fRowBytes write fRowBytes; property ByteCount : Integer read GetByteCount; property Bytes[Index : Integer] : Byte read GetByte write SetByte; procedure AddBytes(val : string); class function CountBytes(val : string) : Word; end; TMapElement = class private fRange: Word; fDomain: Word; public property Domain : Word read fDomain write fDomain; property Range : Word read fRange write fRange; end; TRICVarMap = class(TRICOpBase) private protected fDataAddr: Word; fMapElements : TObjectList; function GetMapCount: Word; function GetMapElement(Index: Integer): TMapElement; procedure SetMapElement(Index: Integer; const Value: TMapElement); public constructor Create(aOwner : TRICOps); override; destructor Destroy; override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; procedure AddMap(aMapElement : PIOV_MAPELT); function Add : TMapElement; property DataAddr : Word read fDataAddr write fDataAddr; property MapCount : Word read GetMapCount; property MapElements[Index : Integer] : TMapElement read GetMapElement write SetMapElement; end; TRICCopyBits = class(TRICOpBase) protected fCopyOptions : Word; fDataAddr : Word; fDestPoint: TImgPoint; fSrcRect: TImgRect; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property DataAddr : Word read fDataAddr write fDataAddr; property SrcRect : TImgRect read fSrcRect write fSrcRect; property DestPoint : TImgPoint read fDestPoint write fDestPoint; end; TRICPixel = class(TRICOpBase) protected fCopyOptions : Word; fPoint: TImgPoint; fValue: Word; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point : TImgPoint read fPoint write fPoint; property Value : Word read fValue write fValue; end; TRICLine = class(TRICOpBase) protected fCopyOptions : Word; fPoint1: TImgPoint; fPoint2: TImgPoint; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point1 : TImgPoint read fPoint1 write fPoint1; property Point2 : TImgPoint read fPoint2 write fPoint2; end; TRICRect = class(TRICOpBase) protected fCopyOptions : Word; fPoint: TImgPoint; fHeight: SmallInt; fWidth: SmallInt; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point : TImgPoint read fPoint write fPoint; property Width : SmallInt read fWidth write fWidth; property Height : SmallInt read fHeight write fHeight; end; TRICCircle = class(TRICOpBase) protected fCopyOptions : Word; fPoint: TImgPoint; fRadius: Word; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point : TImgPoint read fPoint write fPoint; property Radius : Word read fRadius write fRadius; end; TRICNumBox = class(TRICOpBase) protected fCopyOptions : Word; fPoint: TImgPoint; fValue: Word; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point : TImgPoint read fPoint write fPoint; property Value : Word read fValue write fValue; end; TRICEllipse = class(TRICOpBase) protected fCopyOptions : Word; fPoint: TImgPoint; fRadius1: Word; fRadius2: Word; public constructor Create(aOwner : TRICOps); override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; property CopyOptions : Word read fCopyOptions write fCopyOptions; property Point : TImgPoint read fPoint write fPoint; property Radius1 : Word read fRadius1 write fRadius1; property Radius2 : Word read fRadius2 write fRadius2; end; TPolyPoint = class private fX: SmallInt; fY: SmallInt; public property X : SmallInt read fX write fX; property Y : SmallInt read fY write fY; end; TRICPolygon = class(TRICOpBase) private protected fCopyOptions : Word; fPolyPoints : TObjectList; function GetCount: Word; function GetPolyPoint(Index: Integer): TPolyPoint; procedure SetPolyPoint(Index: Integer; const Value: TPolyPoint); public constructor Create(aOwner : TRICOps); override; destructor Destroy; override; procedure SaveToStream(aStream : TStream); override; procedure LoadFromStream(aStream : TStream); override; function SaveAsDataArray(const aLangName: TLangName): string; override; // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); override; procedure AddPoint(aPolyPoint : PIMG_PT); function Add : TPolyPoint; property Count : Word read GetCount; property PolyPoints[Index : Integer] : TPolyPoint read GetPolyPoint write SetPolyPoint; property CopyOptions : Word read fCopyOptions write fCopyOptions; end; TRICComp = class private endofallsource : boolean; fBadProgram : boolean; fBytesRead : integer; fProgErrorCount : integer; fOptimize: boolean; fCurFile: string; fEnhancedFirmware: boolean; fMessages: TStrings; fOnCompMSg: TOnCompilerMessage; fCalc : TExpParser; fMaxErrors: word; fFirmwareVersion: word; procedure InternalParseStream; procedure ReportProblem(const lineNo: integer; const fName, msg: string; err: boolean); procedure Init; procedure GetChar; procedure GetCharX; procedure IncLineNumber; procedure Next; procedure SkipWhite; procedure SkipLine; procedure SkipCommentBlock; procedure GetHexNum; procedure GetName; procedure GetNum; procedure Expected(s: string); procedure AbortMsg(s: string); function IsAlpha(c: char): boolean; function IsWhite(c: char): boolean; function IsAlNum(c: char): boolean; function IsDigit(c: char): boolean; function IsHex(c: char): boolean; procedure GetOp; procedure ScriptCommands; procedure Scan; procedure CheckBytesRead(const oldBytesRead: integer); procedure MatchString(x: string); procedure Semi; procedure Statement; procedure DoDesc; procedure DoSprite; procedure DoCircle; procedure DoCopyBits; procedure DoLine; procedure DoNumBox; procedure DoPixel; procedure DoRect; procedure DoVarMap; procedure DoEllipse; procedure DoPolygon; procedure DoFontOut; procedure CloseParen; procedure CheckNumeric; function ProcessArg: SmallInt; function ProcessWordArg: Word; function ValueToInt: integer; function ValueToSmallInt: SmallInt; function ValueToWord: Word; function StringToInt(const val: string): integer; procedure OpenParen; procedure GetString; procedure CheckStringConst; procedure CheckFirmwareVersion(const MinVer : word; const msg : string); protected fMS : TMemoryStream; fOperations : TRICOps; fCurrentLine : string; fTempChar : Char; fParenDepth : integer; fIncludeDirs: TStrings; function GetOpCount: Integer; procedure SyncObjectListToStream; procedure SyncStreamToObjectList; function GetAsText: string; procedure SetAsText(const Value: string); function GetOperation(Index: integer): TRICOpBase; procedure Clear; public constructor Create; virtual; destructor Destroy; override; property CompilerMessages : TStrings read fMessages; procedure LoadFromStream(aStream : TStream); procedure LoadFromFile(const aFilename : string); procedure SaveToStream(aStream : TStream); procedure SaveToFile(const aFilename : string); // procedure Draw(aPoint : TImgPoint; Vars : TRICVariables; Options : Cardinal; aCanvas : TImgCanvas); procedure Parse(const aFilename : string); overload; procedure Parse(aStream : TStream); overload; procedure Parse(aStrings : TStrings); overload; function SaveAsDataArray(const aLangName : TLangName; varname : string) : string; property RICOps : TRICOps read fOperations; property Operations[Index : integer] : TRICOpBase read GetOperation; property OperationCount : Integer read GetOpCount; property AsText : string read GetAsText write SetAsText; property CurrentFile : string read fCurFile write fCurFile; property Optimize : boolean read fOptimize write fOptimize; property EnhancedFirmware : boolean read fEnhancedFirmware write fEnhancedFirmware; property FirmwareVersion : word read fFirmwareVersion write fFirmwareVersion; property MaxErrors : word read fMaxErrors write fMaxErrors; property OnCompilerMessage : TOnCompilerMessage read fOnCompMSg write fOnCompMsg; property IncludeDirs : TStrings read fIncludeDirs; class function RICToText(aStream : TStream; const aFilename : string = '') : string; overload; class function RICToText(const aFilename : string) : string; overload; class function RICToDataArray(const aFilename, aVarName : string; const aLangName : TLangName) : string; end; implementation uses SysUtils, Math, uCommonUtils, uLocalizedStrings, {$IFNDEF FPC} Graphics, JPEG, pngimage, GIFImage {$ELSE} FPImage, FPCanvas, FPReadBMP, {FPReadGIF, }FPReadJpeg, FPReadPCX, FPReadPNG, FPReadPNM, FPReadTGA, {FPReadTiff, }FPReadXPM {$ENDIF}; type TRGBColor = record red : Byte; green : Byte; blue : Byte; end; THSBColor = record Hue : Double; Saturation : Double; Brightness : Double; end; function RGB2HSB( rgb:TRGBColor ) : THSBColor; var minRGB : Double; maxRGB : Double; delta : Double; h : Double; s : Double; b : Double; begin h := 0.0; minRGB := Min( Min( rgb.Red,rgb.Green ),rgb.Blue ); maxRGB := Max( Max( rgb.Red,rgb.Green ),rgb.Blue ); delta := maxRGB - minRGB; b := maxRGB ; if maxRGB <> 0.0 then s := 255.0 * delta / maxRGB else s := 0.0; if s <> 0.0 then begin if rgb.Red = maxRGB then h := (rgb.Green - rgb.Blue) / delta else if rgb.Green = minRGB then h := 2.0 + (rgb.Blue - rgb.Red) / delta else if rgb.Blue = maxRGB then h := 4.0 + (rgb.Red - rgb.Green) / delta end else h := -1.0; h := h * 60; if h < 0.0 then h := h + 360.0; with result do begin Hue := h; Saturation := s * 100 / 255; Brightness := b * 100 / 255; end; end; {$IFNDEF FPC} procedure ImportImage(op : TRICSprite; const fname : string; threshold, width, height : integer); var pic : TPicture; img : TBitmap; w, h, nw, nh, x, y, c : Integer; rgb : TRGBColor; hsb : THSBColor; row : string; begin img := TBitmap.Create; try pic := TPicture.Create; try pic.LoadFromFile(fname); w := pic.Graphic.Width; h := pic.Graphic.Height; img.Width := w; img.Height := h; img.Canvas.Draw( 0,0, pic.Graphic ); finally pic.Free; end; // now generate the pixel bytes for the NXT sprite nw := Min(width, w); nh := Min(height, h); op.Rows := nh; x := nw div 8; if (nw mod 8) <> 0 then inc(x); op.RowBytes := x; for y := 0 to nh-1 do begin row := ''; for x := 0 to nw-1 do begin c := img.Canvas.Pixels[ x,y ]; rgb.red := Byte( ( c and $00FF0000 ) shr 16 ); rgb.green := Byte( ( c and $0000FF00 ) shr 8 ); rgb.blue := Byte( c and $000000FF ); hsb := RGB2HSB( rgb ); if ( hsb.Brightness > threshold ) then row := row + '0' else row := row + '1'; end; op.AddBytes(row); end; finally img.Free; end; end; {$ELSE} procedure ImportImage(op : TRICSprite; const fname : string; threshold, width, height : integer); var img : TFPMemoryImage; w, h, nw, nh, x, y : Integer; c : TFPColor; rgb : TRGBColor; hsb : THSBColor; row : string; begin img := TFPMemoryImage.Create(0, 0); try img.LoadFromFile(fname); w := img.Width; h := img.Height; // now generate the pixel bytes for the NXT sprite nw := Min(width, w); nh := Min(height, h); op.Rows := nh; x := nw div 8; if (nw mod 8) <> 0 then inc(x); op.RowBytes := x; for y := 0 to nh-1 do begin row := ''; for x := 0 to nw-1 do begin c := img.Colors[ x,y ]; rgb.red := c.red; rgb.green := c.green; rgb.blue := c.blue; hsb := RGB2HSB( rgb ); if ( hsb.Brightness > threshold ) then row := row + '0' else row := row + '1'; end; op.AddBytes(row); end; finally img.Free; end; end; {$ENDIF} const TAB = ^I; CR = ^M; LF = ^J; TOK_NUM = 'N'; TOK_HEX = 'H'; TOK_STRINGLIT = 'G'; TOK_OPENPAREN = '('; TOK_CLOSEPAREN = ')'; TOK_COMMA = ','; TOK_IDENTIFIER = 'x'; TOK_DESC = 'd'; TOK_SPRITE = 's'; TOK_COPYBITS = 'c'; TOK_VARMAP = 'v'; TOK_IMPORT = 'i'; TOK_LINE = 'l'; TOK_RECT = 'r'; TOK_PIXEL = 'p'; TOK_CIRCLE = 'C'; TOK_NUMBOX = 'n'; TOK_ARG = 'a'; TOK_MAPARG = 'm'; TOK_F = 'f'; TOK_ELLIPSE = 'e'; TOK_POLYGON = 'P'; TOK_FONTOUT = 'F'; TOK_BLOCK_COMMENT = #01; TOK_LINE_COMMENT = #02; var Look: char = LF; { Lookahead Character } Token: char; { Encoded Token } Value: string; { Unencoded Token } var slevel : integer = 1; linenumber : integer; // current source line number totallines : integer = 0; const NKW = 16; NKW1 = 17; const KWlist: array[1..NKW] of string = ('desc', 'sprite', 'varmap', 'import', 'copybits', 'line', 'rect', 'pixel', 'circle', 'numbox', 'maparg', 'arg', 'f', 'ellipse', 'polygon', 'fontout'); const KWcode: array[1..NKW1+1] of Char = (TOK_IDENTIFIER, TOK_DESC, TOK_SPRITE, TOK_VARMAP, TOK_IMPORT, TOK_COPYBITS, TOK_LINE, TOK_RECT, TOK_PIXEL, TOK_CIRCLE, TOK_NUMBOX, TOK_MAPARG, TOK_ARG, TOK_F, TOK_ELLIPSE, TOK_POLYGON, TOK_FONTOUT, #0); type SymTab = array[1..NKW] of string; TabPtr = ^SymTab; function PixelsToBytes(p : word) : word; begin Result := Word(p div 8); if (p mod 8) <> 0 then Inc(Result); end; procedure WriteImgPointToStream(aStream : TStream; pt : TImgPoint; bLittleEndian : Boolean = True); begin WriteSmallIntToStream(aStream, pt.X, bLittleEndian); WriteSmallIntToStream(aStream, pt.Y, bLittleEndian); end; procedure WriteImgRectToStream(aStream : TStream; R : TImgRect; bLittleEndian : Boolean = True); begin WriteImgPointToStream(aStream, R.Pt, bLittleEndian); WriteSmallIntToStream(aStream, R.Width, bLittleEndian); WriteSmallIntToStream(aStream, R.Height, bLittleEndian); end; procedure ReadImgPointFromStream(aStream : TStream; var pt : TImgPoint; bLittleEndian : Boolean = True); begin ReadSmallIntFromStream(aStream, pt.X, bLittleEndian); ReadSmallIntFromStream(aStream, pt.Y, bLittleEndian); end; procedure ReadImgRectFromStream(aStream : TStream; var R : TImgRect; bLittleEndian : Boolean = True); begin ReadImgPointFromStream(aStream, R.Pt, bLittleEndian); ReadSmallIntFromStream(aStream, R.Width, bLittleEndian); ReadSmallIntFromStream(aStream, R.Height, bLittleEndian); end; function RICOpCodeToStr(const Op : Word; const Options : Word = 0) : string; begin case Op of IMG_DESCRIPTION_ID : begin if Options = $8001 then Result := 'fontout' else Result := 'desc'; end; IMG_SPRITE_ID : Result := 'sprite'; IMG_VARMAP_ID : Result := 'varmap'; IMG_COPYBITS_ID : Result := 'copybits'; IMG_PIXEL_ID : Result := 'pixel'; IMG_LINE_ID : Result := 'line'; IMG_RECTANGLE_ID : Result := 'rect'; IMG_CIRCLE_ID : Result := 'circle'; IMG_NUMBOX_ID : Result := 'numbox'; IMG_ELLIPSE_ID : Result := 'ellipse'; IMG_POLYGON_ID : Result := 'polygon'; else Result := 'unknown'; end; end; function SpriteByteToHexString(const B : Byte) : string; begin Result := IntToHex(B, 2); end; function SpriteByteToBinaryString(const B : Byte) : string; begin Result := ''; if (B and $80) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $40) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $20) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $10) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $08) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $04) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $02) <> 0 then Result := Result + '1' else Result := Result + '0'; if (B and $01) <> 0 then Result := Result + '1' else Result := Result + '0'; end; function RICValueToStr(const val : integer; const aLangName : TLangName = lnRICScript) : string; var fmtStr : string; begin if aLangName in [lnNBC, lnNXC] then begin Result := Format('0x%2.2x, 0x%2.2x', [Lo(val), Hi(val)]); end else begin if IMG_SYMB_USEARGS(val) = 0 then begin Result := Format('%d', [val]); end else begin if IMG_SYMB_MAP(val) = 0 then begin if aLangName = lnRICSCript then fmtStr := 'arg(%d)' else fmtStr := 'RICArg(%d)'; Result := Format(fmtStr, [IMG_SYMB_ARG(val)]); end else begin if aLangName = lnRICSCript then fmtStr := 'maparg(%d, %d)' else fmtStr := 'RICMapArg(%d, %d)'; Result := Format(fmtStr, [IMG_SYMB_MAP(val), IMG_SYMB_ARG(val)]); end; end; end; end; function RICPointToStr(const val : TImgPoint; const aLangName : TLangName) : string; var fmtStr : string; begin if aLangName in [lnNBC, lnNXC, lnNXCHeader] then begin if aLangName in [lnNBC, lnNXC] then fmtStr := '%s, %s' else fmtStr := 'RICImgPoint(%s, %s)'; Result := Format(fmtStr, [RICValueToStr(val.X, aLangName), RICValueToStr(val.Y, aLangName)]); end else Result := ''; end; function RICRectToStr(const val : TImgRect; const aLangName : TLangName) : string; var fmtStr : string; begin if aLangName in [lnNBC, lnNXC, lnNXCHeader] then begin if aLangName in [lnNBC, lnNXC] then fmtStr := '%s, %s, %s' else fmtStr := 'RICImgRect(%s, %s, %s)'; Result := Format(fmtStr, [RICPointToStr(val.Pt, aLangName), RICValueToStr(val.Width, aLangName), RICValueToStr(val.Height, aLangName)]); end else Result := ''; end; function ImgRect(X, Y, Width, Height: SmallInt): TImgRect; begin Result.Pt.X := X; Result.Pt.Y := Y; Result.Width := Width; Result.Height := Height; end; function ImgPoint(X, Y: SmallInt): TImgPoint; begin Result.X := X; Result.Y := Y; end; function RICToText(aMS : TMemoryStream; ops : TRICOps; const Filename : string) : string; var OpSize, i, j : integer; tmpCmd, tmpRow : string; DataSize : Cardinal; pImage : PIMG_OP_UNION; pCB : PIMG_OP_COPYBITS; pL : PIMG_OP_LINE; pR : PIMG_OP_RECT; pC : PIMG_OP_CIRCLE; pNB : PIMG_OP_NUMBOX; pSP : PIMG_OP_SPRITE; pVM : PIMG_OP_VARMAP; pD : PIMG_OP_DESCRIPTION; pPX : PIMG_OP_PIXEL; pE : PIMG_OP_ELLIPSE; pP : PIMG_OP_POLYGON; pB : PByte; pMAP : PIOV_MAPELT; pImgPt : PIMG_PT; theText : TStringList; opDescr : TRICDescription; opSprite : TRICSprite; opVM : TRICVarMap; opCB : TRICCopyBits; opPixel : TRICPixel; opLine : TRICLine; opRect : TRICRect; opCircle : TRICCircle; opNumBox : TRICNumBox; opEllipse : TRICEllipse; opPolygon : TRICPolygon; begin ops.Clear; Result := ''; theText := TStringList.Create; try DataSize := Cardinal(aMS.Size); aMS.Position := 0; pImage := aMS.Memory; if Filename <> '' then theText.Add(Format('// %s', [ExtractFileName(Filename)])); // Run through the op codes. while DataSize >= SizeOf(IMG_OP_CORE) do begin // Setup to look at an opcode, make sure it looks reasonable. OpSize := pImage^.Core.OpSize + SizeOf(Word); if (OpSize and $01) <> 0 then Break; // Odd sizes not allowed. case pImage^.Core.OpCode of IMG_DESCRIPTION_ID : begin if OpSize >= SizeOf(IMG_OP_DESCRIPTION) then begin // write out the Description opcode pD := @(pImage^.Desc); if pD^.Options = $8001 then begin theText.Add(Format('%s(%d, %d);', [RICOpCodeToStr(pD^.OpCode, pD^.Options), pD^.Width, pD^.Height])); end else begin theText.Add(Format('%s(%d, %d, %d);', [RICOpCodeToStr(pD^.OpCode), pD^.Options, pD^.Width, pD^.Height])); end; // add to the operations list opDescr := TRICDescription.Create(ops); with opDescr do begin OpCode := pD^.OpCode; OpSize := pD^.OpSize; Options := pD^.Options; Width := pD^.Width; Height := pD^.Height; end; end; end; IMG_SPRITE_ID : begin if OpSize >= SizeOf(IMG_OP_SPRITE) then begin // write the sprite to the file. pSP := @(pImage^.Sprite); // add to the operations list opSprite := TRICSprite.Create(ops); with opSprite do begin OpCode := pSP^.OpCode; OpSize := pSP^.OpSize; DataAddr := pSP^.DataAddr; Rows := pSP^.Rows; RowBytes := pSP^.RowBytes; end; tmpCmd := Format('%s(%d', [RICOpCodeToStr(pSP^.OpCode), pSP^.DataAddr]); pB := @(pSP^.Bytes[0]); for j := 0 to pSP^.Rows - 1 do begin tmpRow := '0x'; for i := 0 to pSP^.RowBytes - 1 do begin // pB points at the current byte tmpRow := tmpRow + SpriteByteToHexString(pB^); opSprite.Add(pb^); inc(pB); end; tmpCmd := tmpCmd + ', ' + tmpRow; end; tmpCmd := tmpCmd + ');'; theText.Add(tmpCmd); // set the OpSize value last since adding bytes tries to change the OpSize value opSprite.OpSize := pSP^.OpSize; end; end; IMG_VARMAP_ID : begin if OpSize >= SizeOf(IMG_OP_VARMAP) then begin // write the varmap to the file. pVM := @(pImage^.VarMap); // add to the operations list opVM := TRICVarMap.Create(ops); with opVM do begin OpCode := pVM^.OpCode; OpSize := pVM^.OpSize; DataAddr := pVM^.DataAddr; end; tmpCmd := Format('%s(%d', [RICOpCodeToStr(pVM^.OpCode), pVM^.DataAddr]); pMAP := @(pVM^.MapElt[0]); for j := 0 to pVM^.MapCount - 1 do begin tmpCmd := tmpCmd + Format(', f(%d)=%d', [pMAP^.Domain, pMAP^.Range]); opVM.AddMap(pMAP); inc(pMAP); end; tmpCmd := tmpCmd + ');'; theText.Add(tmpCmd); // set the OpSize value last since adding map elements tries to change the OpSize value opVM.OpSize := pVM^.OpSize; end; end; IMG_COPYBITS_ID : begin if OpSize >= SizeOf(IMG_OP_COPYBITS) then begin // write the CopyBits opcode to the file pCB := @(pImage^.CopyBits); // add to the operations list opCB := TRICCopyBits.Create(ops); with opCB do begin OpCode := pCB^.OpCode; OpSize := pCB^.OpSize; CopyOptions := pCB^.CopyOptions; DataAddr := pCB^.DataAddr; SrcRect := ImgRect(pCB^.Src.Pt.X, pCB^.Src.Pt.Y, pCB^.Src.Width, pCB^.Src.Height); DestPoint := ImgPoint(pCB^.Dst.X, pCB^.Dst.Y); end; theText.Add(Format('%s(%s, %s, %s, %s, %s, %s, %s, %s);', [RICOpCodeToStr(pCB^.OpCode), RICValueToStr(pCB^.CopyOptions), RICValueToStr(pCB^.DataAddr), RICValueToStr(pCB^.Src.Pt.X), RICValueToStr(pCB^.Src.Pt.Y), RICValueToStr(pCB^.Src.Width), RICValueToStr(pCB^.Src.Height), RICValueToStr(pCB^.Dst.X), RICValueToStr(pCB^.Dst.Y)])); end; end; IMG_PIXEL_ID : begin if OpSize >= SizeOf(IMG_OP_PIXEL) then begin pPX := @(pImage^.Pixel); // add to the operations list opPixel := TRICPixel.Create(ops); with opPixel do begin OpCode := pPX^.OpCode; OpSize := pPX^.OpSize; CopyOptions := pPX^.CopyOptions; Point := ImgPoint(pPX^.Pt.X, pPX^.Pt.Y); Value := pPX^.Value; end; theText.Add(Format('%s(%s, %s, %s, %s);', [RICOpCodeToStr(pPX^.OpCode), RICValueToStr(pPX^.CopyOptions), RICValueToStr(pPX^.Pt.X), RICValueToStr(pPX^.Pt.Y), RICValueToStr(pPX^.Value)])); end; end; IMG_LINE_ID : begin if OpSize >= SizeOf(IMG_OP_LINE) then begin pL := @(pImage^.Line); // add to the operations list opLine := TRICLine.Create(ops); with opLine do begin OpCode := pL^.OpCode; OpSize := pL^.OpSize; CopyOptions := pL^.CopyOptions; Point1 := ImgPoint(pL^.Pt1.X, pL^.Pt1.Y); Point2 := ImgPoint(pL^.Pt2.X, pL^.Pt2.Y); end; theText.Add(Format('%s(%s, %s, %s, %s, %s);', [RICOpCodeToStr(pL^.OpCode), RICValueToStr(pL^.CopyOptions), RICValueToStr(pL^.Pt1.X), RICValueToStr(pL^.Pt1.Y), RICValueToStr(pL^.Pt2.X), RICValueToStr(pL^.Pt2.Y)])); end; end; IMG_RECTANGLE_ID : begin if OpSize >= SizeOf(IMG_OP_RECT) then begin pR := @(pImage^.Rect); // add to the operations list opRect := TRICRect.Create(ops); with opRect do begin OpCode := pR^.OpCode; OpSize := pR^.OpSize; CopyOptions := pR^.CopyOptions; Point := ImgPoint(pR^.Pt.X, pR^.Pt.Y); Width := pR^.Width; Height := pR^.Height; end; theText.Add(Format('%s(%s, %s, %s, %s, %s);', [RICOpCodeToStr(pR^.OpCode), RICValueToStr(pR^.CopyOptions), RICValueToStr(pR^.Pt.X), RICValueToStr(pR^.Pt.Y), RICValueToStr(pR^.Width), RICValueToStr(pR^.Height)])); end; end; IMG_CIRCLE_ID : begin if OpSize >= SizeOf(IMG_OP_CIRCLE) then begin pC := @(pImage^.Circle); // add to the operations list opCircle := TRICCircle.Create(ops); with opCircle do begin OpCode := pC^.OpCode; OpSize := pC^.OpSize; CopyOptions := pC^.CopyOptions; Point := ImgPoint(pC^.Pt.X, pC^.Pt.Y); Radius := pC^.Radius; end; theText.Add(Format('%s(%s, %s, %s, %s);', [RICOpCodeToStr(pC^.OpCode), RICValueToStr(pC^.CopyOptions), RICValueToStr(pC^.Pt.X), RICValueToStr(pC^.Pt.Y), RICValueToStr(pC^.Radius)])); end; end; IMG_NUMBOX_ID : begin if OpSize >= SizeOf(IMG_OP_NUMBOX) then begin pNB := @(pImage^.NumBox); // add to the operations list opNumBox := TRICNumBox.Create(ops); with opNumBox do begin OpCode := pNB^.OpCode; OpSize := pNB^.OpSize; CopyOptions := pNB^.CopyOptions; Point := ImgPoint(pNB^.Pt.X, pNB^.Pt.Y); Value := pNB^.Value; end; theText.Add(Format('%s(%s, %s, %s, %s);', [RICOpCodeToStr(pNB^.OpCode), RICValueToStr(pNB^.CopyOptions), RICValueToStr(pNB^.Pt.X), RICValueToStr(pNB^.Pt.Y), RICValueToStr(pNB^.Value)])); end; end; IMG_ELLIPSE_ID : begin if OpSize >= SizeOf(IMG_OP_ELLIPSE) then begin pE := @(pImage^.Ellipse); // add to the operations list opEllipse := TRICEllipse.Create(ops); with opEllipse do begin OpCode := pE^.OpCode; OpSize := pE^.OpSize; CopyOptions := pE^.CopyOptions; Point := ImgPoint(pE^.Pt.X, pE^.Pt.Y); Radius1 := pE^.Radius1; Radius2 := pE^.Radius2; end; theText.Add(Format('%s(%s, %s, %s, %s, %s);', [RICOpCodeToStr(pE^.OpCode), RICValueToStr(pE^.CopyOptions), RICValueToStr(pE^.Pt.X), RICValueToStr(pE^.Pt.Y), RICValueToStr(pE^.Radius1), RICValueToStr(pE^.Radius2)])); end; end; IMG_POLYGON_ID : begin if OpSize >= SizeOf(IMG_OP_POLYGON) then begin pP := @(pImage^.Polygon); // add to the operations list opPolygon := TRICPolygon.Create(ops); with opPolygon do begin OpCode := pP^.OpCode; OpSize := pP^.OpSize; CopyOptions := pP^.CopyOptions; end; tmpCmd := Format('%s(%s', [RICOpCodeToStr(pP^.OpCode), RICValueToStr(pP^.CopyOptions)]); pImgPt := @(pP^.Points[0]); for j := 0 to pP^.Count - 1 do begin tmpCmd := tmpCmd + Format(', (%d, %d)', [pImgPt^.X, pImgPt^.Y]); opPolygon.AddPoint(pImgPt); inc(pImgPt); end; tmpCmd := tmpCmd + ');'; theText.Add(tmpCmd); // set the OpSize value last since adding polygon points tries to change the OpSize value opPolygon.OpSize := pP^.OpSize; end; end; else //Unrecognized opcode so quit Break; end; dec(DataSize, OpSize); pImage := PIMG_OP_UNION(PChar(pImage) + OpSize); end; Result := theText.Text; finally theText.Free; end; end; { TRICComp } constructor TRICComp.Create; begin inherited; fIncludeDirs := TStringList.Create; fMessages := TStringList.Create; fMS := TMemoryStream.Create; fOperations := TRICOps.Create; fCurFile := ''; fOptimize := False; fMaxErrors := 0; fCalc := TExpParser.Create(nil); fCalc.CaseSensitive := True; fFirmwareVersion := 128; // 1.28 NXT 2.0 firmware end; destructor TRICComp.Destroy; begin FreeAndNil(fIncludeDirs); FreeAndNil(fMessages); FreeAndNil(fMS); FreeAndNil(fOperations); FreeAndNil(fCalc); inherited; end; { procedure TRICComp.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin fOperations.Draw(aPoint, Vars, Options, aCanvas); end; } function TRICComp.GetAsText: string; begin // make sure the stream matches the contents of fOperations SyncStreamToObjectList; Result := uRICComp.RICToText(fMS, fOperations, fCurFile); end; function TRICComp.GetOperation(Index: integer): TRICOpBase; begin Result := TRICOpBase(fOperations[Index]); end; function TRICComp.GetOpCount: Integer; begin Result := fOperations.Count; end; procedure TRICComp.LoadFromFile(const aFilename: string); var Stream: TStream; begin fCurFile := aFilename; Stream := TFileStream.Create(aFilename, fmOpenRead or fmShareDenyWrite); try LoadFromStream(Stream); finally Stream.Free; end; end; procedure TRICComp.LoadFromStream(aStream: TStream); begin fMS.LoadFromStream(aStream); SyncObjectListToStream; end; class function TRICComp.RICToText(aStream: TStream; const aFilename : string): string; begin with TRICComp.Create do try fCurFile := aFilename; LoadFromStream(aStream); Result := AsText; finally Free; end; end; class function TRICComp.RICToText(const aFilename: string): string; begin with TRICComp.Create do try LoadFromFile(aFilename); Result := AsText; finally Free; end; end; procedure TRICComp.SaveToFile(const aFilename: string); var Stream: TStream; begin Stream := TFileStream.Create(aFilename, fmCreate); try SaveToStream(Stream); finally Stream.Free; end; end; procedure TRICComp.SaveToStream(aStream: TStream); begin SyncStreamToObjectlist; aStream.CopyFrom(fMS, 0); end; procedure TRICComp.SetAsText(const Value: string); var SL : TStringList; begin Clear; // compile text to RIC SL := TStringList.Create; try SL.Text := Value; SL.SaveToStream(fMS); InternalParseStream; finally SL.Free; end; end; procedure TRICComp.ReportProblem(const lineNo: integer; const fName, msg: string; err : boolean); var tmp, tmp1, tmp2, tmp3, tmp4 : string; stop : boolean; begin if lineNo = -1 then begin tmp := msg; fMessages.Add(tmp); end else begin if err then tmp1 := Format('# Error: %s', [msg]) else tmp1 := Format('# Warning: %s', [msg]); fMessages.Add(tmp1); tmp2 := Format('File "%s" ; line %d', [fName, lineNo]); fMessages.Add(tmp2); tmp3 := Format('# %s', [fCurrentLine]); fMessages.Add(tmp3); tmp4 := '#----------------------------------------------------------'; fMessages.Add(tmp4); tmp := tmp1+#13#10+tmp2+#13#10+tmp3+#13#10+tmp4; end; fBadProgram := err; if err then inc(fProgErrorCount); stop := (MaxErrors > 0) and (fProgErrorCount >= MaxErrors); // stop := false; if assigned(fOnCompMsg) then fOnCompMsg(tmp, stop); if stop then Abort; end; procedure TRICComp.IncLineNumber; begin linenumber := linenumber + 1; inc(totallines); end; procedure TRICComp.GetCharX; var bytesread : integer; begin bytesread := fMS.Read(Look, 1); inc(fBytesRead, bytesread); fCurrentLine := fCurrentLine + Look; if Look = LF then begin IncLineNumber; fCurrentLine := ''; end; if bytesread < 1 then endofallsource := True; if endofallsource and (slevel > 1) then begin // close file pointer linenumber := 0; dec(slevel); Look := LF; endofallsource := False; end; end; procedure TRICComp.GetChar; begin if fTempChar <> ' ' then begin Look := fTempChar; fCurrentLine := fCurrentLine + Look; fTempChar := ' '; end else begin GetCharX; if Look = '/' then begin fMS.Read(fTempChar, 1); if fTempChar = '*' then begin Look := TOK_BLOCK_COMMENT; fTempChar := ' '; end else if fTempChar = '/' then begin Look := TOK_LINE_COMMENT; fTempChar := ' '; end; end; end; end; function TRICComp.IsWhite(c: char): boolean; begin Result := c in [' ', TAB, CR, LF, TOK_BLOCK_COMMENT, TOK_LINE_COMMENT]; end; function TRICComp.IsAlpha(c: char): boolean; begin Result := c in ['A'..'Z', 'a'..'z', '_']; end; function TRICComp.IsDigit(c: char): boolean; begin Result := c in ['0'..'9']; end; function TRICComp.IsHex(c: char): boolean; begin Result := IsDigit(c) or (c in ['a'..'f', 'A'..'F']); end; function TRICComp.IsAlNum(c: char): boolean; begin Result := IsAlpha(c) or IsDigit(c) or (c = '.'); end; procedure TRICComp.SkipCommentBlock; begin repeat repeat GetCharX; until (Look = '*') or endofallsource; GetCharX; until (Look = '/') or endofallsource; GetChar; end; procedure TRICComp.SkipLine; begin repeat GetCharX; until (Look = LF) or endofallsource; GetChar; end; procedure TRICComp.SkipWhite; begin while IsWhite(Look) and not endofallsource do begin case Look of TOK_LINE_COMMENT : SkipLine; TOK_BLOCK_COMMENT : SkipCommentBlock; else GetChar; end; end; end; procedure TRICComp.AbortMsg(s: string); begin ReportProblem(linenumber, CurrentFile, s, True); end; procedure TRICComp.Expected(s: string); begin AbortMsg(Format(sExpectedString, [s])); end; procedure TRICComp.GetName; begin SkipWhite; if not IsAlpha(Look) then Expected(sIdentifier); Token := TOK_IDENTIFIER; Value := ''; repeat Value := Value + Look; GetChar; until not IsAlNum(Look); end; procedure TRICComp.GetNum; var savedLook : char; begin SkipWhite; if not IsDigit(Look) then Expected(sNumber); savedLook := Look; GetChar; if Look in ['x', 'X'] then begin GetHexNum; end else begin Token := TOK_NUM; Value := savedLook; if not IsDigit(Look) then Exit; repeat Value := Value + Look; GetChar; until not IsDigit(Look); end; end; procedure TRICComp.GetHexNum; begin SkipWhite; GetChar(); // skip the $ (or 'x') if not IsHex(Look) then Expected(sHexNumber); Token := TOK_HEX; Value := '0x'; repeat Value := Value + Look; GetChar; until not IsHex(Look); end; procedure TRICComp.GetOp; begin SkipWhite; Token := Look; Value := Look; GetChar; end; procedure TRICComp.GetString; begin SkipWhite; GetChar; // skip the " Token := TOK_STRINGLIT; if Look = '"' then begin // empty string Value := ''''''; GetChar; end else begin Value := '''' + Look; repeat GetCharX; if (Look <> LF) and (Look <> '"') then begin if Look = '''' then Value := Value + '"' else Value := Value + Look; end; until (Look = '"') or (Look = LF) or endofallsource; Value := Value + ''''; if Look <> '"' then Expected(sStringLiteral); GetChar; end; end; procedure TRICComp.Next; begin SkipWhite; if Look = '"' then GetString else if IsAlpha(Look) then GetName else if IsDigit(Look) then GetNum else if Look = '$' then GetHexNum else GetOp; end; procedure TRICComp.Init; begin fCurrentLine := ''; totallines := 1; linenumber := 1; GetChar; Next; while (Token = #0) and not endofallsource do Next; end; function Lookup(T: TabPtr; s: string; n: integer): integer; var i: integer; found: Boolean; begin found := false; i := n; while (i > 0) and not found do if s = T^[i] then found := true else dec(i); Result := i; end; procedure TRICComp.Scan; var idx : integer; begin if Token = TOK_IDENTIFIER then begin idx := Lookup(Addr(KWlist), Value, NKW); if idx <> 0 then Token := KWcode[idx + 1]; end; end; procedure TRICComp.CheckBytesRead(const oldBytesRead: integer); begin if fBytesRead = oldBytesRead then begin AbortMsg(sParserError); SkipLine; Next; end; end; procedure TRICComp.MatchString(x: string); begin if Value <> x then Expected('''' + x + ''''); Next; end; procedure TRICComp.CheckNumeric; begin if not (Token in [TOK_NUM, TOK_HEX]) then Expected(sNumber); end; procedure TRICComp.CheckStringConst; begin if (Token <> TOK_STRINGLIT) then Expected(sStringLiteral); end; procedure TRICComp.Semi; begin MatchString(';'); end; procedure TRICComp.OpenParen; begin MatchString(TOK_OPENPAREN); inc(fParenDepth); end; procedure TRICComp.CloseParen; begin dec(fParenDepth); if fParenDepth < 0 then AbortMsg(sUnmatchedCloseParen); MatchString(TOK_CLOSEPAREN); end; function TRICComp.StringToInt(const val : string) : integer; begin Result := 0; fCalc.SilentExpression := val; if not fCalc.ParserError then Result := Integer(Trunc(fCalc.Value)) else AbortMsg(sInvalidConstExpr); end; function TRICComp.ValueToInt : integer; begin Result := StringToInt(Value); end; function TRICComp.ValueToSmallInt : SmallInt; begin Result := SmallInt(ValueToInt); end; function TRICComp.ValueToWord : Word; begin Result := Word(ValueToInt); end; function TRICComp.ProcessWordArg : Word; begin Result := Word(ProcessArg); end; function TRICComp.ProcessArg : SmallInt; var mapidx : SmallInt; begin Result := 0; { arg can be a simple numeric value: 0x12, 32, or $f or a parameterized argument: arg(0x12), arg(32), arg($f) or a parameterized & mapped argument: maparg(0x1, 0x12), maparg(1, 23), etc... } case Token of TOK_ARG : begin // arg(value) Next; MatchString(TOK_OPENPAREN); CheckNumeric; Result := ValueToSmallInt; if (Result < 0) or (EnhancedFirmware and (Result > $ff)) or (not EnhancedFirmware and (Result > $f))then AbortMsg(Format(sInvalidArgument, [Result])); Result := Result or USEARGS_MASK; Next; // leave it pointing at the close paren end; TOK_MAPARG : begin // maparg(value, value) Next; MatchString(TOK_OPENPAREN); CheckNumeric; mapidx := ValueToSmallInt; if (mapidx < 0) or (mapidx > $a) then AbortMsg(Format(sInvalidVarMapIndex, [mapidx])); Next; MatchString(TOK_COMMA); Result := ValueToSmallInt; if (Result < 0) or (EnhancedFirmware and (Result > $ff)) or (not EnhancedFirmware and (Result > $f))then AbortMsg(Format(sInvalidArgument, [Result])); Result := Result or SmallInt((mapidx and $f) shl 8); Result := Result or USEARGS_MASK; Next; // leave it pointing at the close paren end; TOK_NUM, TOK_HEX : begin Result := ValueToSmallInt; end; else AbortMsg(sInvalidCommandArgument); end; end; procedure TRICComp.DoDesc; var op : TRICDescription; begin // add a description opcode op := TRICDescription.Create(RICOps); // parse and set its values // desc(options, width, height); Next; OpenParen; CheckNumeric; op.Options := ValueToWord; Next; MatchString(TOK_COMMA); CheckNumeric; op.Width := ValueToWord; Next; MatchString(TOK_COMMA); CheckNumeric; op.Height := ValueToWord; Next; CloseParen; end; procedure TRICComp.DoSprite; var op : TRICSprite; sl : TStringList; i : integer; bFileFound : boolean; fname, usePath : string; thresh, width, height : integer; const DEF_SPRITE_IMPORT_THRESHOLD = 50; DEF_SPRITE_IMPORT_WIDTH = 100; DEF_SPRITE_IMPORT_HEIGHT = 64; begin // add a sprite opcode op := TRICSprite.Create(RICOps); // parse and set its values // sprite(addr, row1, row2, ..., rowN); // sprite(addr, import("filename.ext"[, threshold])); // sprite(addr, import("filename.ext"[, threshold, width, height])); Next; OpenParen; CheckNumeric; op.DataAddr := ValueToWord; Next; MatchString(TOK_COMMA); scan; if Token = TOK_IMPORT then begin // support "import" keyword thresh := DEF_SPRITE_IMPORT_THRESHOLD; width := DEF_SPRITE_IMPORT_WIDTH; height := DEF_SPRITE_IMPORT_HEIGHT; Next; OpenParen; CheckStringConst; fname := Value; Next; if Token = TOK_COMMA then begin MatchString(TOK_COMMA); // optional threshold value CheckNumeric; thresh := StrToIntDef(Value, thresh); Next; if Token = TOK_COMMA then begin MatchString(TOK_COMMA); // optional width & height CheckNumeric; width := StrToIntDef(Value, width); Next; MatchString(TOK_COMMA); CheckNumeric; height := StrToIntDef(Value, height); Next; end; end; CloseParen; CloseParen; // build sprite bytes using fname and thresh // find sprite file fName := StripQuotes(fName); usePath := ''; bFileFound := FileExists(fname); if not bFileFound then begin for i := 0 to IncludeDirs.Count - 1 do begin usePath := IncludeTrailingPathDelimiter(IncludeDirs[i]); bFileFound := FileExists(usePath+fname); if bFileFound then Break; end; end; if bFileFound then begin ImportImage(op, usePath+fname, thresh, width, height); end else AbortMsg(Format(sUnableToFindImage, [fname])); end else begin sl := TStringList.Create; try while (Token <> TOK_CLOSEPAREN) and not endofallsource do begin sl.Add(Value + '=' + IntToStr(linenumber)); Next; if Token = TOK_COMMA then MatchString(TOK_COMMA); end; CloseParen; // process strings in sl // calculate rows and rowbytes op.Rows := Word(sl.Count); if sl.count = 0 then begin op.RowBytes := 0; AbortMsg(sSpriteLengthError); end else op.RowBytes := op.CountBytes(sl.Names[0]); for i := 0 to sl.Count - 1 do begin // add bytes to Sprite for each line in sl try op.AddBytes(sl.Names[i]); except on E : Exception do AbortMsg(E.Message); end; end; finally sl.Free; end; end; if ((op.Rows*op.RowBytes) mod 2) = 1 then op.Add(0); // padding byte end; procedure TRICComp.DoVarMap; var op : TRICVarMap; ME : TMapElement; begin // add a varmap opcode op := TRICVarMap.Create(RICOps); // parse and set its values // varmap(addr, func1, func2, ..., funcN); // where funcN is f(xval)=yval Next; OpenParen; CheckNumeric; op.DataAddr := ValueToWord; Next; MatchString(TOK_COMMA); while (Token <> TOK_CLOSEPAREN) and not endofallsource do begin // f(x)=y Scan; if Token <> TOK_F then AbortMsg(sInvalidMapSyntax); Next; // advance to open parenthesis OpenParen; // advance to x value ME := op.Add; CheckNumeric; ME.Domain := ValueToWord; Next; // advance to close parenthesis CloseParen; // advance to equal sign MatchString('='); // Next; // advance to y value CheckNumeric; ME.Range := ValueToWord; Next; // advance to comma or close paren if Token = TOK_COMMA then MatchString(TOK_COMMA); end; CloseParen; if op.MapCount < 2 then AbortMsg(sVarMapCountError); end; procedure TRICComp.DoCopyBits; var op : TRICCopyBits; SR : TImgRect; DP : TImgPoint; begin // add a copybits opcode op := TRICCopyBits.Create(RICOps); // parse and set its values // copybits(options, dataaddr, srcx, srcy, srcw, srch, destx, desty); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; op.DataAddr := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; SR.Pt.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; SR.Pt.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; SR.Width := ProcessArg; Next; MatchString(TOK_COMMA); Scan; SR.Height := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.SrcRect := SR; DP.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; DP.Y := ProcessArg; Next; CloseParen; op.DestPoint := DP; end; procedure TRICComp.DoLine; var op : TRICLine; P1, P2 : TImgPoint; begin // add a line opcode op := TRICLine.Create(RICOps); // parse and set its values // line(options, p1x, p1y, p2x, p2y); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P1.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P1.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P2.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P2.Y := ProcessArg; Next; CloseParen; op.Point1 := P1; op.Point2 := P2; end; procedure TRICComp.DoRect; var op : TRICRect; P : TImgPoint; begin // add a rect opcode op := TRICRect.Create(RICOps); // parse and set its values // rect(options, x, y, w, h); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Point := P; op.Width := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Height := ProcessArg; Next; CloseParen; end; procedure TRICComp.DoPixel; var op : TRICPixel; P : TImgPoint; begin // add a pixel opcode op := TRICPixel.Create(RICOps); // parse and set its values // pixel(options, x, y, value); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Point := P; op.Value := ProcessWordArg; Next; CloseParen; end; procedure TRICComp.DoCircle; var op : TRICCircle; P : TImgPoint; begin // add a circle opcode op := TRICCircle.Create(RICOps); // parse and set its values // circle(options, x, y, radius); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Point := P; op.Radius := ProcessWordArg; Next; CloseParen; end; procedure TRICComp.DoEllipse; var op : TRICEllipse; P : TImgPoint; begin CheckFirmwareVersion(127, sEllipseRequires127); // add an ellipse opcode op := TRICEllipse.Create(RICOps); // parse and set its values // ellipse(options, x, y, radius1, radius2); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Point := P; op.Radius1 := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; op.Radius2 := ProcessWordArg; Next; CloseParen; end; procedure TRICComp.DoPolygon; var op : TRICPolygon; PP : TPolyPoint; begin CheckFirmwareVersion(127, sPolygonRequires127); // add a polygon opcode op := TRICPolygon.Create(RICOps); // parse and set its values // polygon(options, coord1, coord2, ..., coordN); // where coordN is (xval, yval) Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); while (Token <> TOK_CLOSEPAREN) and not endofallsource do begin // (x, y) OpenParen; // advance to x value PP := op.Add; Scan; PP.X := ProcessWordArg; Next; // advance to comma MatchString(','); Scan; PP.Y := ProcessWordArg; Next; CloseParen; // advance to close paren or comma if Token = TOK_COMMA then MatchString(TOK_COMMA); end; CloseParen; if op.Count < 3 then AbortMsg(sPolygonCountError); end; procedure TRICComp.DoNumBox; var op : TRICNumBox; P : TImgPoint; begin // add a numbox opcode op := TRICNumBox.Create(RICOps); // parse and set its values // numbox(options, x, y, value); Next; OpenParen; Scan; op.CopyOptions := ProcessWordArg; Next; MatchString(TOK_COMMA); Scan; P.X := ProcessArg; Next; MatchString(TOK_COMMA); Scan; P.Y := ProcessArg; Next; MatchString(TOK_COMMA); Scan; op.Point := P; op.Value := ProcessWordArg; Next; CloseParen; end; procedure TRICComp.Statement; begin case Token of TOK_DESC: DoDesc; TOK_SPRITE: DoSprite; TOK_VARMAP: DoVarMap; TOK_COPYBITS: DoCopyBits; TOK_LINE: DoLine; TOK_RECT: DoRect; TOK_PIXEL: DoPixel; TOK_CIRCLE: DoCircle; TOK_NUMBOX: DoNumBox; TOK_ELLIPSE: DoEllipse; TOK_POLYGON: DoPolygon; TOK_FONTOUT: DoFontOut; TOK_CLOSEPAREN : CloseParen; ';' : ;// do nothing end; end; procedure TRICComp.ScriptCommands; var oldBytesRead : integer; begin Scan; while not endofallsource do begin oldBytesRead := fBytesRead; Statement; Semi; Scan; CheckBytesRead(oldBytesRead); end; end; procedure TRICComp.InternalParseStream; begin try fBadProgram := False; fBytesRead := 0; fProgErrorCount := 0; fMS.Position := 0; fParenDepth := 0; Init; ScriptCommands; except on E : EAbort do begin fBadProgram := True; // end processing file due to Abort in ReportProblem end; on E : Exception do begin fBadProgram := True; ReportProblem(linenumber, CurrentFile, E.Message, true); end; end; end; procedure TRICComp.SyncObjectListToStream; begin uRICComp.RICToText(fMS, fOperations, fCurFile); end; procedure TRICComp.SyncStreamToObjectList; var i : integer; begin fMS.Clear; for i := 0 to fOperations.Count - 1 do TRICOpBase(fOperations[i]).SaveToStream(fMS); end; procedure TRICComp.Parse(aStream: TStream); begin Clear; fMS.CopyFrom(aStream, 0); InternalParseStream; end; procedure TRICComp.Parse(aStrings: TStrings); begin Clear; aStrings.SaveToStream(fMS); InternalParseStream; end; procedure TRICComp.Parse(const aFilename: string); var Stream : TFileStream; begin Clear; Stream := TFileStream.Create(aFilename, fmOpenRead or fmShareDenyWrite); try fMS.CopyFrom(Stream, 0); finally Stream.Free; end; InternalParseStream; end; procedure TRICComp.Clear; begin fMS.Clear; fMessages.Clear; fTempChar := ' '; end; function TRICComp.SaveAsDataArray(const aLangName: TLangName; varname : string): string; var tmp : string; i : integer; begin if varname = '' then varname := ChangeFileExt(ExtractFileName(CurrentFile),'') else varname := Format(varname, [ChangeFileExt(ExtractFileName(CurrentFile),'')]); if aLangName in [lnNXC, lnNXCHeader] then begin Result := 'byte ' + varname + '[] = {'#13#10; for i := 0 to fOperations.Count - 1 do begin Result := Result + TRICOpBase(fOperations[i]).SaveAsDataArray(aLangName); if i < fOperations.Count - 1 then Result := Result + ', '; Result := Result + #13#10; end; Result := Result + '};'; end else if aLangName = lnNBC then begin tmp := ''; for i := 0 to fOperations.Count - 1 do begin tmp := tmp + TRICOpBase(fOperations[i]).SaveAsDataArray(aLangName); if i < fOperations.Count - 1 then tmp := tmp + ', '; end; Result := 'dseg segment'#13#10 + ' ' + varname + ' byte[] ' + tmp + #13#10 + 'dseg ends'; end else Result := '// unable to import "' + ExtractFileName(CurrentFile) + '"'; end; class function TRICComp.RICToDataArray(const aFilename, aVarName : string; const aLangName: TLangName): string; begin with TRICComp.Create do try LoadFromFile(aFilename); Result := SaveAsDataArray(aLangName, aVarName); finally Free; end; end; procedure TRICComp.CheckFirmwareVersion(const MinVer : word; const msg : string); begin if FirmwareVersion < MinVer then AbortMsg(msg); end; procedure TRICComp.DoFontOut; var op : TRICDescription; begin // add a description opcode op := TRICDescription.Create(RICOps); // parse and set its values // fontout(width, height); op.Options := $8001; Next; OpenParen; CheckNumeric; op.Width := ValueToWord; Next; MatchString(TOK_COMMA); CheckNumeric; op.Height := ValueToWord; Next; CloseParen; end; { TRICDescription } constructor TRICDescription.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_DESCRIPTION_ID; fOpSize := SizeOf(IMG_OP_DESCRIPTION) - 2; end; { procedure TRICDescription.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // The description opcode is a NO-OP when it comes to drawing end; } procedure TRICDescription.LoadFromStream(aStream: TStream); var w : word; begin inherited; w := 0; // read options, width, height from stream ReadWordFromStream(aStream, w); Options := w; ReadWordFromStream(aStream, w); Width := w; ReadWordFromStream(aStream, w); Height := w; end; function TRICDescription.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(Options, aLangName), RICValueToStr(Width, aLangName), RICValueToStr(Height, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpDescription(%d, %d, %d)', [Options, Width, Height]) else Result := ''; end; procedure TRICDescription.SaveToStream(aStream: TStream); begin inherited; // write options, width, height to stream WriteWordToStream(aStream, Options); WriteWordToStream(aStream, Width); WriteWordToStream(aStream, Height); end; { TRICSprite } procedure TRICSprite.Add(aValue: Byte); var O : TByteObject; begin O := TByteObject.Create; fBytes.Add(O); O.Value := aValue; inc(fOpSize, 1); end; function Pow(k: Integer): Integer; var j, Count: Integer; begin if k > 0 then j := 2 else j := 1; for Count := 1 to k - 1 do j := j * 2; Result := j; end; function BinToDec(Str: string): Integer; var Len, Res, i: Integer; begin Len:=Length(Str); Res:=0; for i:=1 to Len do if (Str[i]='0')or(Str[i]='1') then Res:=Res+Pow(Len-i)*StrToInt(Str[i]) else raise Exception.CreateFmt(sStringNotBinary, [Str]); Result := Res; end; function IsHexString(const val : string) : boolean; begin Result := Pos('0x', val) = 1; end; procedure TRICSprite.AddBytes(val: string); var bHex : boolean; b : Byte; tmp : string; begin // parse string and add bytes as needed to sprite // each row must be either a hex string with an even number of hex digits // or a string containing only 1s and 0s where each character is a bit bHex := IsHexString(val); if bHex then System.Delete(val, 1, 2); if bHex and ((Length(val) mod 2) <> 0) then raise Exception.CreateFmt(sInvalidHexLength, [Length(val)]); while Length(val) > 0 do begin if bHex then begin tmp := Copy(val, 1, 2); System.Delete(val, 1, 2); b := Byte(StrToInt('$'+tmp)); end else begin tmp := Copy(val, 1, 8); System.Delete(val, 1, 8); if Length(tmp) < 8 then tmp := tmp + StringOfChar('0', 8-Length(tmp)); b := Byte(BinToDec(tmp)); end; Add(b); end; end; function TRICSprite.BytesToWrite: Integer; begin Result := Rows*RowBytes; if (Result mod 2) = 1 then Inc(Result); end; class function TRICSprite.CountBytes(val: string): Word; var bHex : boolean; len : Word; begin // we count bytes based on the length of the string and // whether it is hex or not. bHex := IsHexString(val); if bHex then System.Delete(val, 1, 2); len := Word(Length(val)); if bHex then Result := Word(len div 2) else begin Result := Word(len div 8); if (len mod 8) <> 0 then inc(Result); end; end; constructor TRICSprite.Create(aOwner : TRICOps); begin inherited Create(aOwner); fBytes := TObjectList.Create; fOpCode := IMG_SPRITE_ID; fOpSize := SizeOf(IMG_OP_SPRITE) - 4; // remove sizeof(fOpCode) + 2 bytes end; destructor TRICSprite.Destroy; begin FreeAndNil(fBytes); inherited; end; { procedure TRICSprite.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // drawing a sprite just copies the sprite into a data address // so that a future CopyBits opcode can access it. end; } function TRICSprite.GetByte(Index: Integer): Byte; begin Result := TByteObject(fBytes[Index]).Value; end; function TRICSprite.GetByteCount: Integer; begin Result := fBytes.Count; end; function TRICSprite.GetByteValue(const idx: integer): Byte; begin if idx < ByteCount then Result := Bytes[idx] else Result := 0; end; function TRICSprite.GetOpSize: Word; begin Result := fOpSize; if (Result mod 2) = 1 then Inc(Result); end; procedure TRICSprite.LoadFromStream(aStream: TStream); var da, r, rb : Word; B : Byte; BytesToRead, i : integer; begin inherited; da := 0; r := 0; rb := 0; B := 0; ReadWordFromStream(aStream, da); ReadWordFromStream(aStream, r); ReadWordFromStream(aStream, rb); DataAddr := da; Rows := r; RowBytes := rb; // read bytes from stream BytesToRead := Rows*RowBytes; if (BytesToRead mod 2) = 1 then Inc(BytesToRead); for i := 0 to BytesToRead - 1 do begin aStream.Read(B, 1); Add(B); end; end; function TRICSprite.SaveAsDataArray(const aLangName: TLangName): string; function OutputBytes(bIsNXCHeader : boolean) : string; var i, cnt : integer; B : Byte; begin if bIsNXCHeader then Result := 'RICSpriteData(' else Result := ''; cnt := BytesToWrite - 1; for i := 0 to cnt do begin B := GetByteValue(i); Result := Result + Format('0x%2.2x', [B]); if i < cnt then begin Result := Result + ', '; if bIsNXCHeader and ((i mod 8) = 0) and (i > 0) then Result := Result + #13#10' '; end; end; if bIsNXCHeader then Result := Result + ')'; end; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s, %s', [RICValueToStr(DataAddr, aLangName), RICValueToStr(Rows, aLangName), RICValueToStr(RowBytes, aLangName), OutputBytes(false)]); end else if aLangName = lnNXCHeader then begin Result := Format('RICOpSprite(%d, %d, %d,'#13#10' %s)', [DataAddr, Rows, RowBytes, OutputBytes(true)]); end else Result := ''; end; procedure TRICSprite.SaveToStream(aStream: TStream); var B : Byte; i : integer; begin inherited; WriteWordToStream(aStream, DataAddr); WriteWordToStream(aStream, Rows); WriteWordToStream(aStream, RowBytes); // now write out all the bytes in the Bytes array for i := 0 to BytesToWrite - 1 do begin B := GetByteValue(i); aStream.Write(B, 1); end; end; procedure TRICSprite.SetByte(Index: Integer; const Value: Byte); begin TByteObject(fBytes[Index]).Value := Value; end; { TRICOpBase } constructor TRICOpBase.Create(aOwner : TRICOps); begin inherited Create; fOwner := aOwner; fOwner.Add(Self); fOpCode := 0; fOpSize := 0; end; destructor TRICOpBase.Destroy; begin inherited; end; function TRICOpBase.GetOpSize: Word; begin Result := fOpSize; end; procedure TRICOpBase.LoadFromStream(aStream: TStream); var w : word; begin // read size and opcode from stream w := 0; ReadWordFromStream(aStream, w); OpSize := w; ReadWordFromStream(aStream, w); OpCode := w; end; function TRICOpBase.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then Result := Format('%s, %s', [RICValueToStr(OpSize, aLangName), RICValueToStr(OpCode, aLangName)]) else Result := ''; end; procedure TRICOpBase.SaveToStream(aStream: TStream); begin // write size and opcode to stream WriteWordToStream(aStream, OpSize); WriteWordToStream(aStream, OpCode); end; { TRICVarMap } function TRICVarMap.Add: TMapElement; begin Result := TMapElement.Create; fMapElements.Add(Result); inc(fOpSize, 4); end; procedure TRICVarMap.AddMap(aMapElement: PIOV_MAPELT); var ME : TMapElement; begin ME := TMapElement.Create; fMapElements.Add(ME); ME.Domain := aMapElement^.Domain; ME.Range := aMapElement^.Range; inc(fOpSize, 4); end; constructor TRICVarMap.Create(aOwner : TRICOps); begin inherited Create(aOwner); fMapElements := TObjectList.Create; fOpCode := IMG_VARMAP_ID; fOpSize := SizeOf(IMG_OP_VARMAP) - 10; end; destructor TRICVarMap.Destroy; begin FreeAndNil(fMapElements); inherited; end; { procedure TRICVarMap.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // copy varmap to specified address end; } function TRICVarMap.GetMapCount: Word; begin Result := Word(fMapElements.Count); end; function TRICVarMap.GetMapElement(Index: Integer): TMapElement; begin Result := TMapElement(fMapElements[Index]); end; procedure TRICVarMap.LoadFromStream(aStream: TStream); var da, mc, d, r : word; i : integer; ME : TMapElement; begin inherited; da := 0; mc := 0; d := 0; r := 0; ReadWordFromStream(aStream, da); ReadWordFromStream(aStream, mc); DataAddr := da; for i := 0 to mc - 1 do begin // read map elements from stream ReadWordFromStream(aStream, d); ReadWordFromStream(aStream, r); ME := Add; ME.Domain := d; ME.Range := r; end; end; function TRICVarMap.SaveAsDataArray(const aLangName: TLangName): string; function OutputBytes(bIsNXCHeader : boolean) : string; var i, cnt : integer; ME : TMapElement; begin if bIsNXCHeader then Result := 'RICMapFunction(' else Result := ''; cnt := MapCount - 1; for i := 0 to cnt do begin ME := Self.MapElements[i]; if bIsNXCHeader then Result := Result + Format('RICMapElement(%d, %d)', [ME.Domain, ME.Range]) else Result := Result + Format('%s, %s', [RICValueToStr(ME.Domain, lnNBC), RICValueToStr(ME.Range, lnNBC)]); if i < cnt then begin Result := Result + ', '; if bIsNXCHeader {and ((i mod 4) = 0) and (i > 0)} then Result := Result + #13#10' '; end; end; if bIsNXCHeader then Result := Result + ')'; end; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(DataAddr, aLangName), RICValueToStr(MapCount, aLangName), OutputBytes(false)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpVarMap(%d, %d,'#13#10' %s)', [DataAddr, MapCount, OutputBytes(true)]) else Result := ''; end; procedure TRICVarMap.SaveToStream(aStream: TStream); var i : integer; ME : TMapElement; begin inherited; WriteWordToStream(aStream, DataAddr); WriteWordToStream(aStream, MapCount); // now write out all the elements in the MapElement array for i := 0 to MapCount - 1 do begin ME := Self.MapElements[i]; WriteWordToStream(aStream, ME.Domain); WriteWordToStream(aStream, ME.Range); end; end; procedure TRICVarMap.SetMapElement(Index: Integer; const Value: TMapElement); begin TMapElement(fMapElements[Index]).Domain := Value.Domain; TMapElement(fMapElements[Index]).Range := Value.Range; end; { TRICCopyBits } constructor TRICCopyBits.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_COPYBITS_ID; fOpSize := SizeOf(IMG_OP_COPYBITS) - 2; end; { procedure TRICCopyBits.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw bits from specified image end; } procedure TRICCopyBits.LoadFromStream(aStream: TStream); var co, da : Word; r : TImgRect; p : TImgPoint; begin inherited; // read CopyOptions, DataAddr, SrcRect, DestPoint from stream co := 0; da := 0; r.Pt.X := 0; r.Pt.Y := 0; r.Width := 0; r.Height := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadWordFromStream(aStream, da); ReadImgRectFromStream(aStream, r); ReadImgPointFromStream(aStream, p); CopyOptions := co; DataAddr := da; SrcRect := r; DestPoint := p; end; function TRICCopyBits.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICValueToStr(DataAddr, aLangName), RICRectToStr(SrcRect, aLangName), RICPointToStr(DestPoint, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpCopyBits(%s, %s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICValueToStr(DataAddr, aLangName), RICRectToStr(SrcRect, aLangName), RICPointToStr(DestPoint, aLangName)]) else Result := ''; end; procedure TRICCopyBits.SaveToStream(aStream: TStream); begin inherited; // write CopyOptions, DataAddr, SrcRect, DestPoint to stream WriteWordToStream(aStream, CopyOptions); WriteWordToStream(aStream, DataAddr); WriteImgRectToStream(aStream, SrcRect); WriteImgPointToStream(aStream, DestPoint); end; { TRICPixel } constructor TRICPixel.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_PIXEL_ID; fOpSize := SizeOf(IMG_OP_PIXEL) - 2; // the standard NXT firmware has a bug in it which needs to be // worked around end; { procedure TRICPixel.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw this pixel to the specified canvas // resolve all the values as required end; } procedure TRICPixel.LoadFromStream(aStream: TStream); var p : TImgPoint; co, v : Word; begin inherited; // read point from stream co := 0; v := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p); ReadWordFromStream(aStream, v); CopyOptions := co; Point := p; Value := v; end; function TRICPixel.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Value, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpPixel(%s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Value, aLangName)]) else Result := ''; end; procedure TRICPixel.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point); WriteWordToStream(aStream, Value); end; { TRICLine } constructor TRICLine.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_LINE_ID; fOpSize := SizeOf(IMG_OP_LINE) - 2; end; { procedure TRICLine.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw line as specified end; } procedure TRICLine.LoadFromStream(aStream: TStream); var p1, p2 : TImgPoint; co : Word; begin inherited; co := 0; p1.X := 0; p1.Y := 0; p2.X := 0; p2.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p1); ReadImgPointFromStream(aStream, p2); CopyOptions := co; Point1 := p1; Point2 := p2; end; function TRICLine.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point1, aLangName), RICPointToStr(Point2, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpLine(%s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point1, aLangName), RICPointToStr(Point2, aLangName)]) else Result := ''; end; procedure TRICLine.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point1); WriteImgPointToStream(aStream, Point2); end; { TRICRect } constructor TRICRect.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_RECTANGLE_ID; fOpSize := SizeOf(IMG_OP_RECT) - 2; end; { procedure TRICRect.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw rectangle as specified end; } procedure TRICRect.LoadFromStream(aStream: TStream); var p : TImgPoint; w, h : SmallInt; co : Word; begin inherited; co := 0; w := 0; h := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p); ReadSmallIntFromStream(aStream, w); ReadSmallIntFromStream(aStream, h); CopyOptions := co; Point := p; Width := w; Height := h; end; function TRICRect.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Width, aLangName), RICValueToStr(Height, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpRect(%s, %s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Width, aLangName), RICValueToStr(Height, aLangName)]) else Result := ''; end; procedure TRICRect.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point); WriteSmallIntToStream(aStream, Width); WriteSmallIntToStream(aStream, Height); end; { TRICCircle } constructor TRICCircle.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_CIRCLE_ID; fOpSize := SizeOf(IMG_OP_CIRCLE) - 2; end; { procedure TRICCircle.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw circle as specified end; } procedure TRICCircle.LoadFromStream(aStream: TStream); var p : TImgPoint; r, co : Word; begin inherited; co := 0; r := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p); ReadWordFromStream(aStream, r); CopyOptions := co; Point := p; Radius := r; end; function TRICCircle.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Radius, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpCircle(%s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Radius, aLangName)]) else Result := ''; end; procedure TRICCircle.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point); WriteWordToStream(aStream, Radius); end; { TRICNumBox } constructor TRICNumBox.Create(aOwner : TRICOps); begin inherited Create(aOwner); fOpCode := IMG_NUMBOX_ID; fOpSize := SizeOf(IMG_OP_NUMBOX) - 2; end; { procedure TRICNumBox.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw numbox as specified end; } procedure TRICNumBox.LoadFromStream(aStream: TStream); var p : TImgPoint; v, co : Word; begin inherited; co := 0; v := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p); ReadWordFromStream(aStream, v); CopyOptions := co; Point := p; Value := v; end; function TRICNumBox.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Value, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpNumBox(%s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Value, aLangName)]) else Result := ''; end; procedure TRICNumBox.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point); WriteWordToStream(aStream, Value); end; { TRICEllipse } constructor TRICEllipse.Create(aOwner: TRICOps); begin inherited Create(aOwner); fOpCode := IMG_ELLIPSE_ID; fOpSize := SizeOf(IMG_OP_ELLIPSE) - 2; end; { procedure TRICEllipse.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); begin // draw ellipse as specified end; } procedure TRICEllipse.LoadFromStream(aStream: TStream); var p : TImgPoint; r1, r2, co : Word; begin inherited; co := 0; r1 := 0; r2 := 0; p.X := 0; p.Y := 0; ReadWordFromStream(aStream, co); ReadImgPointFromStream(aStream, p); ReadWordFromStream(aStream, r1); ReadWordFromStream(aStream, r2); CopyOptions := co; Point := p; Radius1 := r1; Radius2 := r2; end; function TRICEllipse.SaveAsDataArray(const aLangName: TLangName): string; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s, %s, %s', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Radius1, aLangName), RICValueToStr(Radius2, aLangName)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpEllipse(%s, %s, %s, %s)', [RICValueToStr(CopyOptions, aLangName), RICPointToStr(Point, aLangName), RICValueToStr(Radius1, aLangName), RICValueToStr(Radius2, aLangName)]) else Result := ''; end; procedure TRICEllipse.SaveToStream(aStream: TStream); begin inherited; WriteWordToStream(aStream, CopyOptions); WriteImgPointToStream(aStream, Point); WriteWordToStream(aStream, Radius1); WriteWordToStream(aStream, Radius2); end; { TRICPolygon } function TRICPolygon.Add: TPolyPoint; begin Result := TPolyPoint.Create; fPolyPoints.Add(Result); inc(fOpSize, 4); end; procedure TRICPolygon.AddPoint(aPolyPoint: PIMG_PT); var PP : TPolyPoint; begin PP := TPolyPoint.Create; fPolyPoints.Add(PP); PP.X := aPolyPoint^.X; PP.Y := aPolyPoint^.Y; inc(fOpSize, 4); end; constructor TRICPolygon.Create(aOwner: TRICOps); begin inherited Create(aOwner); fPolyPoints := TObjectList.Create; fOpCode := IMG_POLYGON_ID; fOpSize := SizeOf(IMG_OP_POLYGON) - 14; // remove 2 + 3*4 end; destructor TRICPolygon.Destroy; begin FreeAndNil(fPolyPoints); inherited; end; function TRICPolygon.GetCount: Word; begin Result := Word(fPolyPoints.Count); end; function TRICPolygon.GetPolyPoint(Index: Integer): TPolyPoint; begin Result := TPolyPoint(fPolyPoints[Index]); end; procedure TRICPolygon.LoadFromStream(aStream: TStream); var co, mc, x, y : word; i : integer; PP : TPolyPoint; begin inherited; co := 0; mc := 0; x := 0; y := 0; ReadWordFromStream(aStream, co); ReadWordFromStream(aStream, mc); CopyOptions := co; for i := 0 to mc - 1 do begin // read polygon points from stream ReadWordFromStream(aStream, x); ReadWordFromStream(aStream, y); PP := Add; PP.X := x; PP.Y := y; end; end; function TRICPolygon.SaveAsDataArray(const aLangName: TLangName): string; function OutputBytes(bIsNXCHeader : boolean) : string; var i, cnt : integer; PP : TPolyPoint; begin if bIsNXCHeader then Result := 'RICPolygonPoints(' else Result := ''; cnt := Count - 1; for i := 0 to cnt do begin PP := PolyPoints[i]; if bIsNXCHeader then Result := Result + Format('RICImgPoint(%s, %s)', [RICValueToStr(PP.X, aLangName), RICValueToStr(PP.Y, aLangName)]) else Result := Result + Format('%s, %s', [RICValueToStr(PP.X, lnNBC), RICValueToStr(PP.Y, lnNBC)]); if i < cnt then begin Result := Result + ', '; if bIsNXCHeader {and ((i mod 4) = 0) and (i > 0)} then Result := Result + #13#10' '; end; end; if bIsNXCHeader then Result := Result + ')'; end; begin if aLangName in [lnNBC, lnNXC] then begin Result := inherited SaveAsDataArray(aLangName); Result := Result + Format(', %s, %s', [RICValueToStr(Count, aLangName), OutputBytes(false)]); end else if aLangName = lnNXCHeader then Result := Format('RICOpPolygon(%d,'#13#10' %s)', [Count, OutputBytes(true)]) else Result := ''; end; procedure TRICPolygon.SaveToStream(aStream: TStream); var i : integer; PP : TPolyPoint; begin inherited; WriteWordToStream(aStream, CopyOptions); WriteWordToStream(aStream, Count); // now write out all the points in the PolyPoints array for i := 0 to Count - 1 do begin PP := PolyPoints[i]; WriteWordToStream(aStream, PP.X); WriteWordToStream(aStream, PP.Y); end; end; procedure TRICPolygon.SetPolyPoint(Index: Integer; const Value: TPolyPoint); begin TPolyPoint(fPolyPoints[Index]).X := Value.X; TPolyPoint(fPolyPoints[Index]).Y := Value.Y; end; { TRICOps } constructor TRICOps.Create; begin inherited Create; end; destructor TRICOps.Destroy; begin inherited; end; { procedure TRICOps.Draw(aPoint: TImgPoint; Vars: TRICVariables; Options: Cardinal; aCanvas: TImgCanvas); var i : integer; begin for i := 0 to Count - 1 do TRICOpBase(Items[i]).Draw(aPoint, Vars, Options, aCanvas); end; } (* {$IFNDEF FPC} initialization TPicture.RegisterFileFormat('BMP', 'Bitmap', TBitmap); finalization TPicture.UnregisterGraphicClass(TBitmap); {$ENDIF} *) end. NXT/uNXCComp.pas0000644000175000017500000103063511537752673013300 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNXCComp; interface uses Classes, uNBCCommon, uGenLexer, uNXTClasses, uPreprocess, Contnrs; type TNXCComp = class private fStackDepth : integer; fStatementType : TStatementType; fInlineFunctionStack : TObjectStack; fLastErrLine : integer; fLastErrMsg : string; endofallsource : boolean; fEnhancedFirmware: boolean; fIgnoreSystemFile: boolean; fParenDepth : integer; fSafeCalls: boolean; fMaxErrors: word; fFirmwareVersion: word; fStackVarNames : TStringList; fOnCompilerStatusChange: TCompilerStatusChangeEvent; fMaxPreProcDepth: word; function FunctionParameterTypeName(const name: string; idx: integer): string; function LocalDataType(const n: string): char; function LocalTypeName(const n: string): string; function LocalConstantValue(const n: string): string; function GlobalDataType(const n: string): char; function GlobalTypeName(const n: string): string; function ParamDataType(const n: string): char; function ParamTypeName(const n: string): string; function FuncParamDataType(const n: string): char; procedure CheckSemicolon; procedure OpenParen; procedure CloseParen; procedure InitializeGraphicOutVars; procedure LocalEmitLn(SL: TStrings; const line: string); procedure LocalEmitLnNoTab(SL: TStrings; const line: string); procedure pop; procedure push; procedure SetStatementType(const Value: TStatementType); procedure DoCompilerStatusChange(const Status: string; const bDone : boolean = False); procedure DoCommonFuncProcDecl(var bProtoExists: boolean; var Name: string; const tname: string; const tok, dt: char; bInline, bSafeCall: boolean); procedure HandlePreprocStatusChange(Sender : TObject; const StatusMsg : string); procedure SetCurFile(const Value: string); function IsCharLiteral(const aName: string): boolean; function IsStringLiteral(const aName: string): boolean; protected fDD: TDataDefs; fCurrentStruct : TDataspaceEntry; fNamedTypes : TMapList; fEmittedLocals : TStringList; fLocals : TVariableList; fParams : TVariableList; fGlobals : TVariableList; fFuncParams : TFunctionParameters; fCurrentInlineFunction : TInlineFunction; fInlineFunctions : TInlineFunctions; fArrayHelpers : TArrayHelperVars; fNBCSrc : TStrings; fMessages : TStrings; fMS : TMemoryStream; fTempChar : Char; fCCSet : boolean; fIncludeDirs: TStrings; fCurFile: string; fOnCompMSg: TOnCompilerMessage; fDirLine : string; fCurrentLine : string; fExpStr : string; fExpStrHasVars : boolean; fAPIFunctions : TStringList; fAPIStrFunctions : TStringList; fThreadNames : TStringList; fCurrentThreadName : string; fBytesRead : integer; fSwitchFixups : TStringList; fSwitchRegNames : TStringList; fSwitchDepth : integer; fCalc : TNBCExpParser; fOptimizeLevel: integer; fInlineDepth : integer; fInlineStack : TObjectList; // list of TStrings fSafeCalling : boolean; fNestingLevel : integer; fLHSDataType : char; fLHSName : string; fWarningsOff: boolean; fFunctionNameCallStack : TStringList; fSemiColonRequired : boolean; fExpressionIsSigned : boolean; fConstStringMap : TStringList; fArrayIndexStack : TStringList; fStructDecls : TStringList; fUDTOnStack : string; fLastExpressionOptimizedToConst : boolean; fLastLoadedConst : string; fProcessingMathAssignment : boolean; fProcessingAsmBlock : boolean; fNoCommaOperator : boolean; function AmInlining : boolean; procedure IncrementInlineDepth; procedure DecrementInlineDepth; procedure HandleSpecialNames; procedure EmitNXCRequiredStructs; procedure ResetStatementType; procedure DecrementNestingLevel; procedure GetCharX; procedure GetChar; procedure Init; procedure Prog; virtual; procedure SkipCommentBlock; procedure SkipLine; procedure SkipDirectiveLine; procedure SkipWhite; procedure GetDirective; procedure GetName; procedure GetNum; procedure GetHexNum; procedure GetCharLit; procedure GetOp; procedure Next(bProcessDirectives : boolean = True); procedure MatchString(x: string); procedure Semi; procedure NotNumericFactor; procedure NumericFactor; procedure Modulo; procedure Divide; procedure Multiply; procedure Term; procedure Add; procedure EqualString; procedure LessString; procedure EqualArrayOrUDT(const lhs : string); procedure LessArrayOrUDT(const lhs : string); procedure Expression; procedure DoPreIncOrDec(bPutOnStack : boolean); function IncrementOrDecrement : boolean; function OptimizeExpression(const idx : integer) : string; procedure Subtract; procedure CommaExpression; procedure BoolExpression; procedure Relation; procedure StoreZeroFlag; function ValueIsStringType(var dt : char) : boolean; function ValueIsArrayType : boolean; function ValueIsUserDefinedType : boolean; procedure BoolTerm; procedure BitOr; procedure BitXor; procedure BitAnd; function TypesAreCompatible(lhs, rhs : char) : boolean; function GetParamName(procname : string; idx : integer) : string; procedure DoCall(procname: string); function GetValueOf(const name : string) : string; procedure DoCallAPIFunc(procname: string); function APIFuncNameToID(procname : string) : integer; function IsAPIFunc(procname : string) : boolean; procedure DoAssignValue(const aName : string; dt : char; bNoChecks : boolean = False); procedure DoLocalArrayInit(const aName, ival : string; dt : char); procedure DoArrayAssignValue(const aName, idx : string; dt : char); function DoNewArrayIndex(theArrayDT : Char; theArray, aLHSName : string) : boolean; procedure Assignment; procedure CheckNotConstant(const aName : string); function CheckConstant(const aName : string) : string; function Block(const lend : string = ''; const lstart : string = '') : boolean; procedure BlockStatements(const lend : string = ''; const lstart : string = ''); procedure CheckBytesRead(const oldBytesRead : integer); procedure DoFor; procedure DoIf(const lend, lstart : string); procedure DoWhile; procedure DoDoWhile; procedure DoRepeat; procedure DoAsm(var dt : char); function DecorateVariables(const asmStr : string) : string; procedure DoSwitch(const lstart : string); procedure DoSwitchCase; function GetCaseConstant : string; procedure DoSwitchDefault; function SwitchFixupIndex : integer; function SwitchIsString : Boolean; function SwitchRegisterName : string; procedure ClearSwitchFixups; procedure FixupSwitch(idx : integer; lbl : string); procedure DoLabel; procedure DoStart; procedure DoStopTask; procedure DoSetPriority; procedure CommaStatement(const lend, lstart : string); procedure Statement(const lend, lstart : string); procedure ProcessDirectives(bScan : boolean = True); procedure HandlePoundLine; function ArrayOfType(dt : char; dimensions : integer) : char; function GetVariableType(vt: char; bUnsigned: boolean): char; procedure CheckForValidDataType(dt : char); function RemoveArrayDimension(dt : char) : char; function AddArrayDimension(dt : char) : char; procedure IncLineNumber; function AddLocal(name: string; dt: char; const tname : string; bConst : boolean; const lenexp : string) : integer; procedure AllocGlobal(const tname : string; dt: char; bInline, bSafeCall, bConst : boolean); procedure AllocLocal(const sub, tname: string; dt: char; bConst : boolean); function GetInitialValue(dt : char) : string; procedure DoLocals(const sub: string); procedure AddFunctionParameter(pname, varname, tname : string; idx : integer; ptype : char; bIsConst, bIsRef, bIsArray : boolean; aDim : integer; bHasDefault : boolean; defValue : string); function FormalList(protoexists: boolean; var procname: string): integer; procedure ProcedureBlock; procedure InitializeGlobalArrays; procedure EmitGlobalDataInitSubroutine; procedure FunctionBlock(Name, tname : string; dt : char; bInline, bSafeCall : boolean); procedure AbortMsg(s: string); procedure Expected(s: string); procedure Undefined(n: string); procedure CheckIdent; procedure CheckEnhancedFirmware; procedure CheckDataType(dt : char); procedure CheckTypeCompatibility(fp : TFunctionParameter; dt : char; const name : string); procedure Duplicate(n: string); // function SizeOfType(dt: char): integer; function AddEntry(N: string; dt: char; const tname, lenexp : string; bConst : boolean = False; bSafeCall : boolean = False) : integer; procedure CheckDup(N: string); procedure CheckTable(const N: string); procedure CheckGlobal(const N: string); procedure AddParam(N: string; dt: char; const tname : string; bConst : boolean; bHasDefault : boolean; const defValue : string); function DataType(const n: string): char; function DataTypeName(const n: string): string; procedure LoadVar(const Name: string); procedure CheckNotProc(const Name : string); procedure Store(const Name: string; bNoChecks : boolean = False); procedure Allocate(const Name, aVal, Val, tname: string; dt: char); procedure InitializeArray(const Name, aVal, Val, tname: string; dt : char; lenexpr : string); // function InlineDecoration : string; procedure Epilog(bIsSub: boolean); procedure Prolog(const name: string; bIsSub: boolean); procedure EmitRegisters; procedure EmitStackVariables; procedure EmitMutexDeclaration(const name : string); procedure EmitInlineParametersAndLocals(func : TInlineFunction); procedure EmitLn(s: string); procedure EmitLnNoTab(s: string); procedure PostLabel(L: string); procedure LoadConst(n: string); procedure Negate; procedure NotIt; procedure Complement; procedure PopAdd; procedure PopAnd; procedure PopCmpEqual; procedure PopCmpGreater; procedure PopCmpGreaterOrEqual; procedure PopCmpLess; procedure PopCmpLessOrEqual; procedure PopCmpNEqual; procedure PopMod; procedure PopDiv; procedure PopLeftShift; procedure PopMul; procedure PopOr; procedure PopRightShift; procedure PopSub; procedure PopXor; procedure PushPrim; procedure SetZeroCC; procedure Branch(L: string); procedure BranchFalse(L: string); procedure BranchTrue(L: string); procedure ClearReg; procedure ArrayAssignment(const name : string; dt : char; bIndexed : boolean); procedure UDTAssignment(const name : string); procedure GetAndStoreUDT(const name : string); procedure MathAssignment(const name : string); procedure StoreAdd(const name: string); procedure StoreDiv(const name: string); procedure StoreMod(const name: string); procedure StoreAnd(const name: string); procedure StoreOr(const name: string); procedure StoreXor(const name: string); procedure StoreAbs(const name: string); procedure StoreSign(const name: string); procedure StoreShift(bRight : boolean; const name: string); procedure StoreMul(const name: string); procedure StoreSub(const name: string); procedure StoreInc(const name: string; const val: integer = 1); procedure StoreDec(const name: string; const val: integer = 1); procedure DoAPICommands(const lend, lstart : string); procedure DoResetScreen; procedure DoReadButton(idx : integer); procedure DoBreakContinue(idx : integer; const lbl : string); procedure DoOnFwdRev; procedure DoOnFwdRevReg; procedure DoOnFwdRevSync; procedure DoOnFwdRevEx; procedure DoOnFwdRevRegEx; procedure DoOnFwdRevSyncEx; procedure DoOnFwdRevRegPID; procedure DoOnFwdRevSyncPID; procedure DoOnFwdRevRegExPID; procedure DoOnFwdRevSyncExPID; procedure DoResetCounters; procedure DoRotateMotors(idx : integer); procedure DoTextNumOut(idx : integer); procedure DoFontTextNumOut(idx : integer); procedure DoDrawPoint; procedure DoDrawPoly; procedure DoDrawEllipse; procedure DoDrawLineRect(idx : integer); procedure DoDrawCircle; procedure DoDrawGraphic(idx : integer); procedure DoPlayToneEx; procedure DoPlayFileEx; procedure DoAcquireRelease; procedure DoExitTo; procedure DoSetInputOutput(const idx : integer); procedure DoStop; procedure DoGoto; procedure DoPrecedesFollows; procedure DoReturn; procedure DoStopMotors; procedure DoStopMotorsEx; procedure DoStrCat; function StrCatHelper(const oldasmstr : string; recurseToken : Char) : string; procedure DoSubString; procedure DoStrReplace; procedure DoStrToNum; procedure MoveToCorrectRegister(dt : char); procedure ReportProblem(const lineNo: integer; const fName, msg: string; const err: boolean); procedure Scan; function IsWhite(c: char): boolean; function IsRelop(c: char): boolean; function IsOrop(c: char): boolean; function IsDigit(c: char): boolean; function IsHex(c: char): boolean; function IsAlNum(c: char): boolean; function IsAddop(c: char): boolean; function IsMulop(c: char): boolean; procedure GetString; procedure CheckNumeric; function ValueIsNumeric : boolean; procedure CheckString; procedure LoadAPIFunctions; procedure AddAPIFunction(const name : string; id : integer); function WhatIs(const n: string): TSymbolType; function StringExpression(const Name : string; bAdd : boolean = False) : boolean; procedure StringConcatAssignment(const Name : string); procedure StringFunction(const Name : string); function TempSignedByteName: string; function TempSignedWordName: string; function TempSignedLongName : string; function TempUnsignedLongName : string; function TempFloatName : string; function RegisterNameByStatementType(st : TStatementType; name : string = '') : string; function RegisterName(name : string = '') : string; function SignedRegisterName(name : string = '') : string; function UnsignedRegisterName(name : string = '') : string; function FloatRegisterName(name : string = '') : string; function ZeroFlag : string; function tos: string; function StrTmpBufName(name : string = '') : string; function StrBufName(name : string = '') : string; function StrRetValName(name : string = '') : string; procedure StoreString(const Name: string; bNoChecks : boolean = False); procedure AddAPIStringFunction(const name: string; id: integer); function APIStrFuncNameToID(procname: string): integer; function IsAPIStrFunc(procname: string): boolean; procedure DoStrLen; // procedure DoSizeOf; procedure DoStrIndex; procedure DoFormatNum; function ReplaceTokens(const line: string): string; procedure EmitAsmLines(s: string); procedure EmitPoundLine; function IsLocal(n: string): boolean; function LocalIdx(n: string): integer; function IsOldParam(n: string): boolean; function IsFuncParam(n: string; bStripInline : boolean = false): boolean; function IsParam(n: string): boolean; function ParamIdx(n: string): integer; procedure AllocateHelper(const Name, aVal, Val, tname: string; dt: char); function AlreadyDecorated(n : string) : boolean; function GetDecoratedValue: string; function GetDecoratedIdent(const val: string): string; procedure PopCmpHelper(const cc: string); procedure GreaterString; procedure NEqualString; procedure CmpHelper(const cc, lhs, rhs : string); procedure GreaterArrayOrUDT(const lhs : string); procedure NEqualArrayOrUDT(const lhs : string); procedure BoolSubExpression; function NewLabel: string; procedure StoreArray(const name, idx, val: string); procedure CheckTask(const Name: string); procedure StringRelation; procedure ArrayOrUDTRelation; procedure NumericRelation; procedure NumericRelationLTGT; procedure NumericShiftLeftRight; function GetNBCSrc: TStrings; function FunctionReturnType(const name: string): char; function FunctionParameterCount(const name: string): integer; function FunctionRequiredParameterCount(const name: string): integer; function FunctionParameterType(const name : string; idx : integer) : char; procedure ClearLocals; procedure ClearParams; procedure ClearGlobals; function IsGlobal(n: string): boolean; function GlobalIdx(n: string): integer; procedure SetDefines(const Value: TStrings); function GetFunctionParam(const procname: string; idx: integer): TFunctionParameter; procedure CheckStringConst; function AdvanceToNextParam : string; function FunctionParameterIsConstant(const name: string; idx: integer): boolean; function FunctionParameterDefaultValue(const name: string; idx: integer): string; function FunctionParameterHasDefault(const name: string; idx: integer): boolean; function IsParamConst(n: string): boolean; function IsLocalConst(n: string): boolean; function IsGlobalConst(n: string): boolean; function GlobalUsesSafeCall(const n: string): boolean; function GetUDTType(n : string) : string; procedure AddTypeNameAlias(const lbl, args : string); function TranslateTypeName(const name : string) : string; procedure ProcessEnum(bGlobal : boolean); procedure ProcessTypedef; procedure ProcessStruct(bTypeDef : boolean = False); procedure CheckForTypedef(var bUnsigned, bConst, bInline, bSafeCall : boolean); function IsUserDefinedType(const name : string) : boolean; function RootOf(const name : string) : string; function DataTypeOfDataspaceEntry(DE : TDataspaceEntry) : char; procedure LoadSystemFile(S : TStream); procedure CheckForMain; function ProcessArrayDimensions(var lenexpr : string) : string; protected fTmpAsmLines : TStrings; fBadProgram : boolean; fProgErrorCount : integer; fDefines : TStrings; procedure InternalParseStream; procedure Clear; property SwitchFixups : TStringList read fSwitchFixups; property SwitchRegisterNames : TStringList read fSwitchRegNames; protected procedure TopDecls; virtual; procedure Header; virtual; procedure Trailer; virtual; procedure PreProcess; virtual; function GetPreProcLexerClass : TGenLexerClass; virtual; // dataspace definitions property property DataDefinitions : TDataDefs read fDD; property StatementType : TStatementType read fStatementType write SetStatementType; public constructor Create; destructor Destroy; override; procedure Parse(const aFilename : string); overload; procedure Parse(aStream : TStream); overload; procedure Parse(aStrings : TStrings); overload; property Defines : TStrings read fDefines write SetDefines; property NBCSource : TStrings read GetNBCSrc; property CompilerMessages : TStrings read fMessages; property IncludeDirs : TStrings read fIncludeDirs; property CurrentFile : string read fCurFile write SetCurFile; property OptimizeLevel : integer read fOptimizeLevel write fOptimizeLevel; property WarningsOff : boolean read fWarningsOff write fWarningsOff; property EnhancedFirmware : boolean read fEnhancedFirmware write fEnhancedFirmware; property FirmwareVersion : word read fFirmwareVersion write fFirmwareVersion; property IgnoreSystemFile : boolean read fIgnoreSystemFile write fIgnoreSystemFile; property SafeCalls : boolean read fSafeCalls write fSafeCalls; property MaxErrors : word read fMaxErrors write fMaxErrors; property MaxPreprocessorDepth : word read fMaxPreProcDepth write fMaxPreProcDepth; property OnCompilerMessage : TOnCompilerMessage read fOnCompMSg write fOnCompMsg; property ErrorCount : integer read fProgErrorCount; property OnCompilerStatusChange : TCompilerStatusChangeEvent read fOnCompilerStatusChange write fOnCompilerStatusChange; end; implementation uses SysUtils, Math, uNXCLexer, uNBCLexer, mwGenericLex, uLocalizedStrings, NBCCommonData, NXCDefsData, uNXTConstants, Parser10; {--------------------------------------------------------------} { Constant Declarations } const TAB = ^I; CR = ^M; LF = ^J; var LCount : integer = 0; const MAXGLOBALS = 10000; MAXPARAMS = 32; {--------------------------------------------------------------} { Type Declarations } type SymTab = array[1..MAXGLOBALS] of string; TabPtr = ^SymTab; {--------------------------------------------------------------} { Variable Declarations } var Look: char = LF; { Lookahead Character } // PrevLook : char; Token: char; { Encoded Token } Value: string; { Unencoded Token } var slevel : integer = 1; linenumber : integer; // current source line number totallines : integer = 0; var GS_Name : SymTab; GS_Type : array[1..MAXGLOBALS] of char; GS_Size : array[1..MAXGLOBALS] of integer; // size (in 'data type' units) GS_ReturnType : array[1..MAXGLOBALS] of char; // only for procedures NumGlobals : integer = 0; {--------------------------------------------------------------} { Definition of Keywords and Token Types } const NKW = 32; //18; NKW1 = 33; //19; const KWlist: array[1..NKW] of string = ('if', 'else', 'while', 'for', 'sub', 'void', 'task', 'do', 'repeat', 'switch', 'asm', 'const', 'default', 'case', 'typedef', 'inline', 'long', 'enum', 'short', 'int', 'unsigned', 'char', 'bool', 'byte', 'mutex', 'float', 'string', 'struct', 'safecall', 'start', 'stop', 'priority' ); const // 'xileweRWve' KWcode: array[1..NKW1+1] of Char = (TOK_IDENTIFIER, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_PROCEDURE, TOK_PROCEDURE, TOK_TASK, TOK_DO, TOK_REPEAT, TOK_SWITCH, TOK_ASM, TOK_CONST, TOK_DEFAULT, TOK_CASE, TOK_TYPEDEF, TOK_INLINE, TOK_LONGDEF, TOK_ENUM, TOK_SHORTDEF, TOK_SHORTDEF, TOK_UNSIGNED, TOK_CHARDEF, TOK_BYTEDEF, TOK_BYTEDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF, TOK_STRUCT, TOK_SAFECALL, TOK_START, TOK_STOP, TOK_PRIORITY, #0); const API_BREAK = 0; API_CONTINUE = 1; API_RETURN = 2; API_GOTO = 3; API_ONFWD = 4; API_ONREV = 5; API_ONFWDREG = 6; API_ONREVREG = 7; API_ONFWDSYNC = 8; API_ONREVSYNC = 9; API_COAST = 10; API_OFF = 11; API_ROTATEMOTOR = 12; API_ROTATEMOTOREX = 13; API_ACQUIRE = 14; API_RELEASE = 15; API_PRECEDES = 16; API_FOLLOWS = 17; API_EXITTO = 18; API_SETINPUT = 19; API_SETOUTPUT = 20; API_STOP = 21; API_FLOAT = 22; API_ONFWDEX = 23; API_ONREVEX = 24; API_ONFWDREGEX = 25; API_ONREVREGEX = 26; API_ONFWDSYNCEX = 27; API_ONREVSYNCEX = 28; API_COASTEX = 29; API_OFFEX = 30; API_ROTATEMOTORPID = 31; API_ROTATEMOTOREXPID = 32; API_RESETTACHOCOUNT = 33; API_RESETBLOCKTACHOCOUNT = 34; API_RESETROTATIONCOUNT = 35; API_RESETALLTACHOCOUNTS = 36; API_ONFWDREGPID = 37; API_ONREVREGPID = 38; API_ONFWDSYNCPID = 39; API_ONREVSYNCPID = 40; API_ONFWDREGEXPID = 41; API_ONREVREGEXPID = 42; API_ONFWDSYNCEXPID = 43; API_ONREVSYNCEXPID = 44; APICount = 4+41; APIList : array[0..APICount-1] of string = ( 'break', 'continue', 'return', 'goto', 'OnFwd', 'OnRev', 'OnFwdReg', 'OnRevReg', 'OnFwdSync', 'OnRevSync', 'Coast', 'Off', 'RotateMotor', 'RotateMotorEx', 'Acquire', 'Release', 'Precedes', 'Follows', 'ExitTo', 'SetInput', 'SetOutput', 'Stop', 'Float', 'OnFwdEx', 'OnRevEx', 'OnFwdRegEx', 'OnRevRegEx', 'OnFwdSyncEx', 'OnRevSyncEx', 'CoastEx', 'OffEx', 'RotateMotorPID', 'RotateMotorExPID', 'ResetTachoCount', 'ResetBlockTachoCount', 'ResetRotationCount', 'ResetAllTachoCounts', 'OnFwdRegPID', 'OnRevRegPID', 'OnFwdSyncPID', 'OnRevSyncPID', 'OnFwdRegExPID', 'OnRevRegExPID', 'OnFwdSyncExPID', 'OnRevSyncExPID' ); const NonAggregateTypes = [TOK_CHARDEF, TOK_SHORTDEF, TOK_LONGDEF, TOK_BYTEDEF, TOK_USHORTDEF, TOK_ULONGDEF, TOK_FLOATDEF]; IntegerTypes = [TOK_CHARDEF, TOK_SHORTDEF, TOK_LONGDEF, TOK_BYTEDEF, TOK_USHORTDEF, TOK_ULONGDEF]; const UnsignedIntegerTypes = [TOK_BYTEDEF, TOK_USHORTDEF, TOK_ULONGDEF]; SignedIntegerTypes = [TOK_CHARDEF, TOK_SHORTDEF, TOK_LONGDEF]; SignedTypes = SignedIntegerTypes + [TOK_FLOATDEF]; function GetArrayDimension(dt : char) : integer; begin case dt of TOK_ARRAYFLOAT..TOK_ARRAYFLOAT4 : Result := Ord(dt) - Ord(TOK_ARRAYFLOAT) + 1; TOK_ARRAYSTRING..TOK_ARRAYSTRING4 : Result := Ord(dt) - Ord(TOK_ARRAYSTRING) + 1; TOK_ARRAYUDT..TOK_ARRAYUDT4 : Result := Ord(dt) - Ord(TOK_ARRAYUDT) + 1; TOK_ARRAYCHARDEF..TOK_ARRAYCHARDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYCHARDEF) + 1; TOK_ARRAYSHORTDEF..TOK_ARRAYSHORTDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYSHORTDEF) + 1; TOK_ARRAYLONGDEF..TOK_ARRAYLONGDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYLONGDEF) + 1; TOK_ARRAYBYTEDEF..TOK_ARRAYBYTEDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYBYTEDEF) + 1; TOK_ARRAYUSHORTDEF..TOK_ARRAYUSHORTDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYUSHORTDEF) + 1; TOK_ARRAYULONGDEF..TOK_ARRAYULONGDEF4 : Result := Ord(dt) - Ord(TOK_ARRAYULONGDEF) + 1; TOK_STRINGDEF : Result := 1; // a string is an array of byte else Result := 0; end; end; function IsArrayType(dt: char; bAllowStrings : boolean = False): boolean; begin Result := (dt >= TOK_ARRAYFLOAT) and (dt <= TOK_ARRAYULONGDEF4); if not Result and bAllowStrings then Result := dt = TOK_STRINGDEF; end; function IsUDT(dt: char): boolean; begin Result := dt = TOK_USERDEFINEDTYPE; end; function ArrayBaseType(dt: char): char; begin case dt of TOK_ARRAYFLOAT..TOK_ARRAYFLOAT4 : Result := TOK_FLOATDEF; TOK_ARRAYSTRING..TOK_ARRAYSTRING4 : Result := TOK_STRINGDEF; TOK_ARRAYUDT..TOK_ARRAYUDT4 : Result := TOK_USERDEFINEDTYPE; TOK_ARRAYCHARDEF..TOK_ARRAYCHARDEF4 : Result := TOK_CHARDEF; TOK_ARRAYSHORTDEF..TOK_ARRAYSHORTDEF4 : Result := TOK_SHORTDEF; TOK_ARRAYLONGDEF..TOK_ARRAYLONGDEF4 : Result := TOK_LONGDEF; TOK_ARRAYBYTEDEF..TOK_ARRAYBYTEDEF4 : Result := TOK_BYTEDEF; TOK_ARRAYUSHORTDEF..TOK_ARRAYUSHORTDEF4 : Result := TOK_USHORTDEF; TOK_ARRAYULONGDEF..TOK_ARRAYULONGDEF4 : Result := TOK_ULONGDEF; TOK_STRINGDEF : Result := TOK_BYTEDEF; // a string is an array of byte else Result := dt; end; end; function DataTypeToArrayDimensions(dt : char) : string; var d, i : integer; begin Result := ''; d := GetArrayDimension(dt); for i := 0 to d - 1 do Result := Result + '[]'; end; function NXCStrToType(const stype : string; bUseCase : Boolean = false) : TDSType; var tmptype : string; begin tmptype := stype; if not bUseCase then tmptype := LowerCase(tmptype); if (tmptype = 'unsigned char') or (tmptype = 'byte') or (tmptype = 'bool') then Result := dsUByte else if tmptype = 'char' then Result := dsSByte else if (tmptype = 'unsigned int') or (tmptype = 'unsigned short') then Result := dsUWord else if (tmptype = 'int') or (tmptype = 'short') then Result := dsSWord else if tmptype = 'unsigned long' then Result := dsULong else if tmptype = 'long' then Result := dsSLong else if tmptype = 'mutex' then Result := dsMutex else if tmptype = 'float' then Result := dsFloat else if tmptype = 'void' then Result := dsVoid else Result := dsCluster; end; procedure TNXCComp.pop; begin dec(fStackDepth); fStackVarNames.Delete(fStackVarNames.Count - 1); end; procedure TNXCComp.push; var tosName : string; begin inc(fStackDepth); MaxStackDepth := Max(MaxStackDepth, fStackDepth); if fStatementType = stFloat then tosName := Format('__float_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]) else if fStatementType = stUnsigned then tosName := Format('__unsigned_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]) else tosName := Format('__signed_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]); fStackVarNames.Add(tosName); end; procedure TNXCComp.GetCharX; var bytesread : integer; begin bytesread := fMS.Read(Look, 1); inc(fBytesRead, bytesread); fCurrentLine := fCurrentLine + Look; if Look = LF then begin IncLineNumber; fCurrentLine := ''; end; if bytesread < 1 then endofallsource := True; if endofallsource and (slevel > 1) then begin // close file pointer linenumber := 0; dec(slevel); Look := LF; endofallsource := False; end; end; {--------------------------------------------------------------} { Read New Character From Input Stream } procedure TNXCComp.GetChar; begin if fTempChar <> ' ' then begin Look := fTempChar; fCurrentLine := fCurrentLine + Look; fTempChar := ' '; end else begin GetCharX; if Look = '/' then begin fMS.Read(fTempChar, 1); if fTempChar = '*' then begin Look := TOK_BLOCK_COMMENT; fTempChar := ' '; end else if fTempChar = '/' then begin Look := TOK_LINE_COMMENT; fTempChar := ' '; end else begin // we need to put that character we just read back into the buffer fMS.Seek(-1, soFromCurrent); fTempChar := ' '; end; end; end; end; {--------------------------------------------------------------} { Report Error and Halt } procedure TNXCComp.ReportProblem(const lineNo: integer; const fName, msg: string; const err : boolean); var tmp, tmp1, tmp2, tmp3, tmp4 : string; stop : boolean; begin // exit without doing anything if this is not an error and warnings are off if WarningsOff and not err then Exit; if (lineNo <> fLastErrLine) or (msg <> fLastErrMsg) then begin fLastErrLine := lineNo; fLastErrMsg := msg; if lineNo = -1 then begin tmp := msg; fMessages.Add(tmp); end else begin if err then tmp1 := Format('# Error: %s', [msg]) else tmp1 := Format('# Warning: %s', [msg]); fMessages.Add(tmp1); tmp2 := Format('File "%s" ; line %d', [fName, lineNo]); fMessages.Add(tmp2); tmp3 := Format('# %s', [fCurrentLine]); fMessages.Add(tmp3); tmp4 := '#----------------------------------------------------------'; fMessages.Add(tmp4); tmp := tmp1+#13#10+tmp2+#13#10+tmp3+#13#10+tmp4; end; fBadProgram := err; if err then inc(fProgErrorCount); stop := (MaxErrors > 0) and (fProgErrorCount >= MaxErrors); if assigned(fOnCompMsg) then fOnCompMsg(tmp, stop); if stop then Abort; end; end; procedure TNXCComp.AbortMsg(s: string); begin ReportProblem(linenumber, CurrentFile, s, True); end; (* {--------------------------------------------------------------} {Return the size in base units of a standard datatype } function TNXCComp.SizeOfType(dt : char) : integer; begin case dt of TOK_CHARDEF, TOK_BYTEDEF : Result := 1; TOK_SHORTDEF, TOK_USHORTDEF : Result := 2; TOK_LONGDEF, TOK_ULONGDEF : Result := 4; TOK_MUTEXDEF : Result := 4; TOK_FLOATDEF : Result := 4; // ??? else Result := 0; AbortMsg('SizeOfType() - Unknown Data Type'); end; end; *) {--------------------------------------------------------------} { Report What Was Expected } procedure TNXCComp.Expected(s: string); begin AbortMsg(Format(sExpectedString, [s])); end; {--------------------------------------------------------------} { Report an Undefined Identifier } procedure TNXCComp.Undefined(n: string); begin AbortMsg(Format(sUndefinedIdentifier, [n])); end; {--------------------------------------------------------------} { Report a Duplicate Identifier } procedure TNXCComp.Duplicate(n: string); begin AbortMsg(Format(sDuplicateIdentifier, [StripDecoration(n)])); end; {--------------------------------------------------------------} { Check to Make Sure the Current Token is an Identifier } procedure TNXCComp.CheckIdent; begin if Token <> TOK_IDENTIFIER then Expected(sIdentifier); end; {--------------------------------------------------------------} { Check to Make Sure the Current Token is a Number } function TNXCComp.ValueIsNumeric: boolean; var vName : string; idx : integer; V : TVariable; begin Result := True; if not (Token in [TOK_NUM, TOK_HEX]) then begin // what about a constant numeric variable? if Token = TOK_IDENTIFIER then begin // it is an identifier vName := GetDecoratedValue; // if it is a global constant then it can be evaluated using our // expression evaluator fCalc.SilentExpression := vName; if fCalc.ParserError then begin // what about a constant local? idx := LocalIdx(vName); if idx <> -1 then begin V := fLocals[idx]; if V.IsConstant and (V.Value <> '') then Value := V.Value else Result := False; end else Result := False; end else Value := NBCFloatToStr(fCalc.Value); end else Result := False; end; end; procedure TNXCComp.CheckNumeric; begin if not ValueIsNumeric then Expected(sNumber); end; procedure TNXCComp.CheckString; begin if (Token <> TOK_STRINGLIT) and not (DataType(Value) in [TOK_STRINGDEF, TOK_ARRAYBYTEDEF, TOK_ARRAYCHARDEF]) then Expected(sStringType); end; procedure TNXCComp.CheckStringConst; begin if (Token <> TOK_STRINGLIT) then Expected(sStringLiteral); end; {--------------------------------------------------------------} { Recognize a Decimal Digit } function TNXCComp.IsDigit(c: char): boolean; begin Result := c in ['0'..'9']; end; {--------------------------------------------------------------} { Recognize a Hex Digit } function TNXCComp.IsHex(c: char): boolean; begin Result := IsDigit(c) or (c in ['a'..'f', 'A'..'F']); end; {--------------------------------------------------------------} { Recognize an Alphanumeric } function TNXCComp.IsAlNum(c: char): boolean; begin Result := IsAlpha(c) or IsDigit(c) or (c = '.'); end; {--------------------------------------------------------------} { Recognize an Addop } function TNXCComp.IsAddop(c: char) : boolean; begin Result := c in ['+', '-']; end; {--------------------------------------------------------------} { Recognize a Mulop } function TNXCComp.IsMulop(c: char): boolean; begin Result := c in ['*', '/', '%']; end; {--------------------------------------------------------------} { Recognize a Boolean Orop } function TNXCComp.IsOrop(c: char): boolean; begin Result := c in ['|', '^']; end; {--------------------------------------------------------------} { Recognize a Relop } function TNXCComp.IsRelop(c: char): boolean; begin Result := c in ['=', '!', '<', '>']; end; {--------------------------------------------------------------} { Recognize White Space } function TNXCComp.IsWhite(c: char): boolean; begin Result := c in [' ', TAB, CR, LF, TOK_BLOCK_COMMENT, TOK_LINE_COMMENT]; end; {--------------------------------------------------------------} { Skip A Comment Field } procedure TNXCComp.SkipCommentBlock; begin repeat repeat GetCharX; until (Look = '*') or endofallsource; GetCharX; until (Look = '/') or endofallsource; GetChar; end; {--------------------------------------------------------------} { Skip A Comment To End Of Line field } procedure TNXCComp.SkipLine; begin repeat GetCharX; until (Look = LF) or endofallsource; GetChar; end; procedure TNXCComp.SkipDirectiveLine; begin fDirLine := Value + ' '; SkipWhite; repeat fDirLine := fDirLine + Look; GetCharX; until (Look = LF) or endofallsource; fDirLine := fDirLine + Look; GetChar; end; {--------------------------------------------------------------} { Skip Over Leading White Space } procedure TNXCComp.SkipWhite; begin while IsWhite(Look) and not endofallsource do begin case Look of TOK_LINE_COMMENT : SkipLine; TOK_BLOCK_COMMENT : SkipCommentBlock; else GetChar; end; end; end; {--------------------------------------------------------------} { Table Lookup } function Lookup(T: TabPtr; s: string; n: integer): integer; var i: integer; found: Boolean; begin found := false; i := n; while (i > 0) and not found do if s = T^[i] then found := true else dec(i); Result := i; end; {--------------------------------------------------------------} { Locate a Symbol in Table } { Returns the index of the entry. Zero if not present. } function TNXCComp.GlobalIdx(n: string): integer; begin Result := Lookup(@GS_Name, RootOf(n), NumGlobals); end; function TNXCComp.IsGlobal(n: string): boolean; begin Result := GlobalIdx(RootOf(n)) <> 0; end; function TNXCComp.IsGlobalConst(n: string): boolean; var i : integer; begin Result := False; i := fGlobals.IndexOfName(RootOf(n)); if i <> -1 then Result := fGlobals[i].IsConstant; end; function TNXCComp.GlobalDataType(const n: string): char; var i : integer; begin Result := #0; i := fGlobals.IndexOfName(RootOf(n)); if i <> -1 then Result := fGlobals[i].DataType; end; function TNXCComp.GlobalTypeName(const n: string): string; var i : integer; begin Result := ''; i := fGlobals.IndexOfName(RootOf(n)); if i <> -1 then Result := fGlobals[i].TypeName; end; function TNXCComp.GlobalUsesSafeCall(const n: string): boolean; var i : integer; begin Result := False; i := fGlobals.IndexOfName(RootOf(n)); if i <> -1 then Result := fGlobals[i].UseSafeCall; end; function TNXCComp.AlreadyDecorated(n: string): boolean; var i : integer; tmp : string; begin // a variable is considered to be already decorated if it // starts with "__" followed by a task name followed by DECOR_SEP // OR it starts with "__signed_stack_" // OR it starts with "__unsigned_stack_" // OR it starts with "__float_stack_" // OR it starts with %%CALLER%%_ Result := False; i := Pos('__', n); if i = 1 then begin System.Delete(n, 1, 2); // remove the '__' at the beginning Result := Pos('%%CALLER%%_', n) = 1; if Result then Exit; i := Pos(DECOR_SEP, n); if i > 1 then begin tmp := Copy(n, 1, i-1); i := fThreadNames.IndexOf(tmp); Result := (i <> -1) or (tmp = 'signed_stack') or (tmp = 'unsigned_stack') or (tmp = 'float_stack'); end; end; end; {--------------------------------------------------------------} { Look for Symbol in Parameter Table } function TNXCComp.IsOldParam(n: string): boolean; begin Result := ParamIdx(RootOf(n)) <> -1{0}; end; function TNXCComp.IsFuncParam(n: string; bStripInline : boolean): boolean; var i : integer; fp : TFunctionParameter; decvar : string; begin Result := False; // check in the fFuncParams for i := 0 to fFuncParams.Count - 1 do begin fp := fFuncParams[i]; decvar := ApplyDecoration(fp.ProcName, fp.Name, 0); if bStripInline and fp.FuncIsInline then begin if decvar = StripInline(RootOf(n)) then begin Result := True; Break; end; end else begin if decvar = RootOf(n) then begin Result := True; Break; end; end; end; end; function TNXCComp.FuncParamDataType(const n: string): char; var i : integer; fp : TFunctionParameter; decvar : string; begin Result := #0; // check in the fFuncParams for i := 0 to fFuncParams.Count - 1 do begin fp := fFuncParams[i]; decvar := ApplyDecoration(fp.ProcName, fp.Name, 0); if decvar = StripInline(RootOf(n)) then begin Result := fp.ParameterDataType; Break; end; end; end; function TNXCComp.IsParam(n: string): boolean; begin Result := IsOldParam(n); if not Result then Result := IsFuncParam(n); end; function TNXCComp.ParamIdx(n: string): integer; begin n := RootOf(n); if AlreadyDecorated(n) then Result := fParams.IndexOfName(n) else Result := fParams.IndexOfName(ApplyDecoration(fCurrentThreadName, n, 0)); end; function TNXCComp.IsParamConst(n: string): boolean; var i : integer; begin Result := False; i := ParamIdx(RootOf(n)); if i <> -1 then Result := fParams[i].IsConstant; end; { function TNXCComp.ParamConstantValue(const n: string): string; var i : integer; begin Result := n; i := ParamIdx(RootOf(n)); if i <> -1 then begin if fParams[i].IsConstant then Result := fParams[i].Value; end; end; } function TNXCComp.ParamDataType(const n: string): char; var i : integer; begin i := ParamIdx(RootOf(n)); if i <> -1 then Result := fParams[i].DataType else begin // maybe a function parameter? Result := FuncParamDataType(RootOf(n)); end; end; function TNXCComp.ParamTypeName(const n: string): string; var i : integer; begin Result := ''; i := ParamIdx(RootOf(n)); if i <> -1 then Result := fParams[i].TypeName; end; {--------------------------------------------------------------} { Look for Symbol in Local Table } function TNXCComp.IsLocal(n: string): boolean; begin Result := LocalIdx(RootOf(n)) <> -1{0}; if not Result then begin // is this a special internal variable name? end; end; function TNXCComp.LocalIdx(n: string): integer; var i : integer; begin n := RootOf(n); if AlreadyDecorated(n) then Result := fLocals.IndexOfName(n) else begin Result := -1; for i := fNestingLevel downto 0 do begin Result := fLocals.IndexOfName(ApplyDecoration(fCurrentThreadName, n, i)); if Result > -1 then break; end; end; end; function TNXCComp.IsLocalConst(n: string): boolean; var i : integer; begin Result := False; i := LocalIdx(RootOf(n)); if i <> -1 then Result := fLocals[i].IsConstant; end; function TNXCComp.LocalConstantValue(const n: string): string; var i : integer; begin Result := n; i := LocalIdx(RootOf(n)); if i <> -1 then begin if fLocals[i].IsConstant then Result := fLocals[i].Value; end; end; function TNXCComp.LocalDataType(const n: string): char; var i : integer; begin Result := #0; i := LocalIdx(RootOf(n)); if i <> -1 then Result := fLocals[i].DataType; end; function TNXCComp.LocalTypeName(const n: string): string; var i : integer; begin Result := ''; i := LocalIdx(RootOf(n)); if i <> -1 then Result := fLocals[i].TypeName; end; {--------------------------------------------------------------} { Check to See if an Identifier is in the Symbol Table } { Report an error if it's not. } procedure TNXCComp.CheckTable(const N: string); begin if not IsParam(N) and not IsLocal(N) and not IsGlobal(N) then Undefined(N); end; procedure TNXCComp.CheckGlobal(const N: string); begin if not IsGlobal(N) then Undefined(N); end; {--------------------------------------------------------------} { Check the Symbol Table for a Duplicate Identifier } { Report an error if identifier is already in table. } procedure TNXCComp.CheckDup(N: string); begin if IsGlobal(N) then Duplicate(N); end; {--------------------------------------------------------------} { Add a New Entry to Symbol Table } function TNXCComp.AddEntry(N: string; dt: char; const tname, lenexp : string; bConst, bSafeCall : boolean) : integer; var V : TVariable; begin CheckForValidDataType(dt); CheckDup(N); if NumGlobals = MAXGLOBALS then AbortMsg(sSymbolTableFull); Inc(NumGlobals); GS_Name[NumGlobals] := N; GS_Type[NumGlobals] := dt; V := fGlobals.Add; with V do begin Name := N; DataType := dt; IsConstant := bConst; UseSafeCall := bSafeCall; TypeName := tname; LenExpr := lenexp; end; Result := V.Index; end; {--------------------------------------------------------------} { Get an preprocessor directive } procedure TNXCComp.GetDirective; begin SkipWhite; if Look <> '#' then Expected(sDirective); Token := TOK_DIRECTIVE; Value := ''; repeat Value := Value + Look; GetChar; until not IsAlpha(Look); end; {--------------------------------------------------------------} { Get an Identifier } procedure TNXCComp.GetName; begin SkipWhite; if not IsAlpha(Look) then Expected(sIdentifier); Token := TOK_IDENTIFIER; Value := ''; repeat Value := Value + Look; GetChar; until not IsAlNum(Look); fExpStrHasVars := True; HandleSpecialNames; end; {--------------------------------------------------------------} { Get a Number } procedure TNXCComp.GetNum; var savedLook : char; begin SkipWhite; if not IsDigit(Look) then Expected(sNumber); savedLook := Look; GetChar; if Look in ['x', 'X'] then begin GetHexNum; end else begin Token := TOK_NUM; Value := savedLook; if not (IsDigit(Look) or (Look = '.')) then Exit; repeat Value := Value + Look; GetChar; until not (IsDigit(Look) or (Look = '.')); end; end; {--------------------------------------------------------------} { Get a Hex Number } procedure TNXCComp.GetHexNum; begin SkipWhite; GetChar(); // skip the $ (or 'x') if not IsHex(Look) then Expected(sHexNumber); Token := TOK_HEX; Value := '0x'; repeat Value := Value + Look; GetChar; until not IsHex(Look); end; {--------------------------------------------------------------} { Get a Character Literal } procedure TNXCComp.GetCharLit; var i : integer; begin GetCharX; // skip the ' Token := TOK_NUM; if Look = '\' then begin GetCharX; // skip the '\' i := Pos(Look, 'abfnrtv''"\?'); case i of 1 : Value := '7'; // bell 2 : Value := '8'; // backspace 3 : Value := '12'; // formfeed 4 : Value := '10'; // new line 5 : Value := '13'; // carriage return 6 : Value := '9'; // tab 7 : Value := '11'; // vertical tab 8 : Value := '39'; // single quote 9 : Value := '34'; // double quote 10 : Value := '92'; // backslash 11 : Value := '63'; // question mark else Value := IntToStr(Ord(Look)); end; end else begin Value := IntToStr(Ord(Look)); end; GetCharX; if Look <> '''' then Expected(sCharLiteral); GetChar; end; {--------------------------------------------------------------} { Get a string Literal } procedure TNXCComp.GetString; var bEscapeNext : boolean; begin GetCharX; // skip the " Token := TOK_STRINGLIT; if Look = '"' then begin // empty string Value := ''''''; end else begin bEscapeNext := False; Value := ''''; if (Look = '''') then Value := Value + '\''' else Value := Value + Look; repeat if not bEscapeNext then bEscapeNext := Look = '\' else bEscapeNext := False; GetCharX; if not ((Look = LF) or ((Look = '"') and not bEscapeNext)) then begin if (Look = '''') and not bEscapeNext then Value := Value + '\''' else Value := Value + Look; end; until ((Look = '"') and not bEscapeNext) or (Look = LF) or endofallsource; Value := Value + ''''; if Look <> '"' then Expected(sStringLiteral); end; GetChar; end; {--------------------------------------------------------------} { Get an Operator } procedure TNXCComp.GetOp; begin SkipWhite; Token := Look; Value := Look; GetChar; end; {--------------------------------------------------------------} { Get the Next Input Token } procedure TNXCComp.Next(bProcessDirectives : boolean); begin SkipWhite; if Look = '''' then GetCharLit else if Look = '"' then GetString else if Look = '#' then GetDirective else if IsAlpha(Look) then GetName else if IsDigit(Look) then GetNum else if Look = '$' then GetHexNum else GetOp; if bProcessDirectives then begin ProcessDirectives(False); fExpStr := fExpStr + Value; end; if not fProcessingAsmBlock and not (Token in ['<', '>', '|', '^', '&', '%', '/', '*', '-', '+', '=']) then SkipWhite; // also skip any whitespace after this token end; function IsAPICommand(const name : string) : boolean; var i : integer; begin Result := False; for i := Low(APIList) to High(APIList) do begin if APIList[i] = name then begin Result := True; Break; end; end; end; {--------------------------------------------------------------} { Scan the Current Identifier for Keywords } procedure TNXCComp.Scan; var idx : integer; begin if Token = TOK_IDENTIFIER then begin idx := Lookup(Addr(KWlist), Value, NKW); if idx <> 0 then Token := KWcode[idx + 1] else begin // is it an API command? if IsAPICommand(Value) then Token := TOK_API else if IsUserDefinedType(Value) then Token := TOK_USERDEFINEDTYPE; end; end; end; {--------------------------------------------------------------} { Match a Specific Input String } procedure TNXCComp.MatchString(x: string); begin if Value <> x then Expected('''' + x + ''''); Next; end; {--------------------------------------------------------------} { Match a Semicolon } procedure TNXCComp.Semi; begin MatchString(TOK_SEMICOLON); // if Token = TOK_SEMICOLON then // Next; end; { procedure TNXCComp.OptionalSemi; begin if Token = TOK_SEMICOLON then Next; end; } {--------------------------------------------------------------} { Output a String with Tab and CRLF } procedure TNXCComp.EmitLn(s: string); begin EmitPoundLine; NBCSource.Add(#9+s); end; procedure TNXCComp.EmitPoundLine; begin NBCSource.Add('#line ' + IntToStr(linenumber-1) + ' "' + CurrentFile + '"'); end; {--------------------------------------------------------------} { Output a String without Tab with CRLF } procedure TNXCComp.EmitLnNoTab(s: string); begin NBCSource.Add(s); end; procedure TNXCComp.EmitAsmLines(s: string); begin if Pos(#10, s) > 0 then begin fTmpAsmLines.Text := s; NBCSource.Add(Format('#pragma macro %d', [fTmpAsmLines.Count])); NBCSource.AddStrings(fTmpAsmLines); EmitPoundLine; end else NBCSource.Add(s); end; {--------------------------------------------------------------} { Generate a Unique Label } function TNXCComp.NewLabel: string; var S: string; begin S := ''; Str(LCount, S); NewLabel := LABEL_PREFIX + S; Inc(LCount); end; {--------------------------------------------------------------} { Post a Label To Output } procedure TNXCComp.PostLabel(L: string); begin EmitLnNoTab(L+':'); end; {---------------------------------------------------------------} { Initialize Parameter Table to Null } procedure TNXCComp.ClearParams; begin fParams.Clear; end; {---------------------------------------------------------------} { Initialize Locals Table to Null } procedure TNXCComp.ClearLocals; begin fLocals.Clear; fEmittedLocals.Clear; end; procedure TNXCComp.ClearGlobals; var i : integer; begin for i := 1 to MAXGLOBALS do begin GS_Name[i] := ''; GS_Type[i] := #0; GS_Size[i] := 0; GS_ReturnType[i] := #0; end; NumGlobals := 0; fGlobals.Clear; end; {--------------------------------------------------------------} { Add a Parameter to Table } procedure TNXCComp.AddParam(N: string; dt: char; const tname : string; bConst : boolean; bHasDefault : boolean; const defValue : string); begin CheckForValidDataType(dt); if IsOldParam(N) then Duplicate(N); with fParams.Add do begin Name := N; DataType := dt; IsConstant := bConst; TypeName := tname; end; end; function TNXCComp.WhatIs(const n : string) : TSymbolType; begin // calling IsOldParam and IsFuncParam separately in order to // tell IsFuncParam to strip inline decoration in this case. if IsOldParam(n) then Result := stParam else if IsFuncParam(n, True) then Result := stParam else if IsLocal(n) then Result := stLocal else if IsGlobal(n) then Result := stGlobal else if IsAPIFunc(n) then Result := stAPIFunc else if IsAPIStrFunc(n) then Result := stAPIStrFunc else Result := stUnknown; end; function TNXCComp.DataType(const n : string) : char; var p : integer; tname : string; DE : TDataspaceEntry; begin if (n = '') then Result := TOK_LONGDEF else if (n = 'true') or (n = 'false') or (n = '1') or (n = '0') then Result := TOK_BYTEDEF else begin case WhatIs(n) of stParam : begin Result := ParamDataType(n); p := Pos('.', n); if (Result = TOK_USERDEFINEDTYPE) and (p > 0) then begin tname := ParamTypeName(n); DE := DataDefinitions.FindEntryByFullName(tname + Copy(n, p, MaxInt)); Result := DataTypeOfDataspaceEntry(DE); end; end; stLocal : begin Result := LocalDataType(n); p := Pos('.', n); if (Result = TOK_USERDEFINEDTYPE) and (p > 0) then begin tname := LocalTypeName(n); DE := DataDefinitions.FindEntryByFullName(tname + Copy(n, p, MaxInt)); Result := DataTypeOfDataspaceEntry(DE); end; end; stGlobal : begin Result := GlobalDataType(n); p := Pos('.', n); if (Result = TOK_USERDEFINEDTYPE) and (p > 0) then begin tname := GlobalTypeName(n); DE := DataDefinitions.FindEntryByFullName(tname + Copy(n, p, MaxInt)); Result := DataTypeOfDataspaceEntry(DE); end; end; stAPIFunc : Result := TOK_APIFUNC; stAPIStrFunc : Result := TOK_APISTRFUNC; else // handle some special cases (register variables) if (Pos('__strretval', n) = 1) or (Pos('__strtmpbuf', n) = 1) or (Pos('__strbuf', n) = 1) then Result := TOK_STRINGDEF else if (Pos('__D0', n) = 1) or (Pos('__signed_stack_', n) = 1) or (Pos('__tmpslong', n) = 1) then Result := TOK_LONGDEF else if (Pos('__DU0', n) = 1) or (Pos('__unsigned_stack_', n) = 1) or (Pos('__tmplong', n) = 1) then Result := TOK_ULONGDEF else if (Pos('__DF0', n) = 1) or (Pos('__float_stack_', n) = 1) or (Pos('__tmpfloat', n) = 1) then Result := TOK_FLOATDEF else if (Pos('__zf', n) = 1) then Result := TOK_BYTEDEF else if (Pos('__tmpsbyte', n) = 1) then Result := TOK_CHARDEF else if (Pos('__tmpsword', n) = 1) then Result := TOK_SHORTDEF else begin Result := #0; Undefined(StripDecoration(n)); end; end; end; end; function TNXCComp.DataTypeName(const n : string) : string; begin Result := ''; case WhatIs(n) of stParam : begin Result := ParamTypeName(n); end; stLocal : begin Result := LocalTypeName(n); end; stGlobal : begin Result := GlobalTypeName(n); end; end; end; function TNXCComp.ArrayOfType(dt: char; dimensions : integer): char; begin Result := dt; if (dimensions > 4) or (dimensions < 1) then begin AbortMsg(sInvalidArrayDim); Exit; end else begin dec(dimensions); // convert 1-4 range into 0-3 range case dt of TOK_CHARDEF : begin Result := Char(Ord(TOK_ARRAYCHARDEF)+dimensions); end; TOK_SHORTDEF : begin Result := Char(Ord(TOK_ARRAYSHORTDEF)+dimensions); end; TOK_LONGDEF : begin Result := Char(Ord(TOK_ARRAYLONGDEF)+dimensions); end; TOK_BYTEDEF : begin Result := Char(Ord(TOK_ARRAYBYTEDEF)+dimensions); end; TOK_USHORTDEF : begin Result := Char(Ord(TOK_ARRAYUSHORTDEF)+dimensions); end; TOK_ULONGDEF : begin Result := Char(Ord(TOK_ARRAYULONGDEF)+dimensions); end; TOK_USERDEFINEDTYPE : begin Result := Char(Ord(TOK_ARRAYUDT)+dimensions); end; TOK_STRINGDEF : begin Result := Char(Ord(TOK_ARRAYSTRING)+dimensions); end; TOK_FLOATDEF : begin Result := Char(Ord(TOK_ARRAYFLOAT)+dimensions); end; else Result := dt; end; end; end; {---------------------------------------------------------------} { Add Primary or var } procedure TNXCComp.StoreAdd(const name : string); begin EmitLn(Format('add %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; {---------------------------------------------------------------} { Subtract Primary from var } procedure TNXCComp.StoreSub(const name : string); begin EmitLn(Format('sub %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; {---------------------------------------------------------------} { Multiply Primary with var } procedure TNXCComp.StoreMul(const name : string); begin EmitLn(Format('mul %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; {---------------------------------------------------------------} { Divide Primary with var } procedure TNXCComp.StoreDiv(const name : string); begin // check for unsafe division (signed by unsigned) if (DataType(name) in SignedTypes) and (StatementType = stUnsigned) then begin // cast the unsigned type to a signed type EmitLn(Format('mov %s, %s', [SignedRegisterName, UnsignedRegisterName])); StatementType := stSigned; end; EmitLn(Format('div %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; {---------------------------------------------------------------} { Mod Primary with var } procedure TNXCComp.StoreMod(const name : string); begin EmitLn(Format('mod %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreAbs(const name: string); begin EmitLn(Format('abs %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreAnd(const name: string); begin EmitLn(Format('and %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreOr(const name: string); begin EmitLn(Format('or %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreShift(bRight: boolean; const name: string); begin if bRight then EmitLn(Format('shr %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])) else EmitLn(Format('shl %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreSign(const name: string); begin EmitLn(Format('sign %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; procedure TNXCComp.StoreXor(const name: string); begin EmitLn(Format('xor %0:s, %0:s, %s', [GetDecoratedIdent(name), RegisterName])); end; {---------------------------------------------------------------} { increment var } procedure TNXCComp.StoreInc(const name : string; const val : integer); begin EmitLn(Format('add %0:s, %0:s, %d', [GetDecoratedIdent(name), val])); end; {---------------------------------------------------------------} { decrement var } procedure TNXCComp.StoreDec(const name : string; const val : integer); begin EmitLn(Format('sub %0:s, %0:s, %d', [GetDecoratedIdent(name), val])); end; {---------------------------------------------------------------} { Clear the Primary Register } procedure TNXCComp.ClearReg; var fmtStr : string; begin fCCSet := False; // 2009-03-18 JCH: It is never safe to use "set" with a float variable if StatementType = stFloat then fmtStr := 'mov %s, 0' else fmtStr := 'set %s, 0'; EmitLn(Format(fmtStr, [RegisterName])); end; {---------------------------------------------------------------} { Bitwise Negate the Primary Register } procedure TNXCComp.Complement; begin CheckEnhancedFirmware; fCCSet := False; EmitLn(Format('cmnt %0:s, %0:s', [RegisterName])); end; {---------------------------------------------------------------} { Negate the Primary Register } procedure TNXCComp.Negate; begin fCCSet := False; EmitLn(Format('neg %0:s, %0:s', [RegisterName])); end; {---------------------------------------------------------------} { Complement the Primary Register } procedure TNXCComp.NotIt; begin fCCSet := False; EmitLn(Format('not %0:s, %0:s', [RegisterName])); end; {---------------------------------------------------------------} { Load a Constant Value to Primary Register } procedure TNXCComp.LoadConst(n: string); var cval : int64; tmpSrc : string; begin fLastLoadedConst := n; if (Pos('.', n) > 0) or (StatementType = stFloat) then begin tmpSrc := 'mov %s, %s'; StatementType := stFloat; end else begin cval := StrToInt64Def(n, 0); if cval <= MaxInt then StatementType := stSigned else StatementType := stUnsigned; if (cval > High(smallint)) or ((cval < 0) and (not EnhancedFirmware or (cval < Low(smallint)))) then tmpSrc := 'mov %s, %s' else tmpSrc := 'set %s, %s'; end; fCCSet := False; EmitLn(Format(tmpSrc, [RegisterName, n])); end; procedure TNXCComp.CheckNotProc(const Name : string); begin if DataType(Name) in [TOK_PROCEDURE, TOK_TASK] then AbortMsg(sAssignTaskError); end; procedure TNXCComp.CheckTask(const Name : string); begin if DataType(Name) <> TOK_TASK then AbortMsg(sArgMustBeTask); end; {---------------------------------------------------------------} { Load a Variable to Primary Register } procedure TNXCComp.LoadVar(const Name: string); var dt : Char; begin CheckNotProc(Name); dt := DataType(Name); if dt = TOK_FLOATDEF then StatementType := stFloat else if not (dt in UnsignedIntegerTypes) then StatementType := stSigned else StatementType := stUnsigned; fCCSet := False; EmitLn(Format('mov %s, %s', [RegisterName, GetDecoratedIdent(Name)])); end; {---------------------------------------------------------------} { Push Primary onto Stack } procedure TNXCComp.PushPrim; begin push; EmitLn(Format('mov %1:s, %0:s', [RegisterName, tos])); end; {---------------------------------------------------------------} { Add Top of Stack to Primary } procedure TNXCComp.PopAdd; begin fCCSet := False; EmitLn(Format('add %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Subtract Primary from Top of Stack } procedure TNXCComp.PopSub; begin fCCSet := False; EmitLn(Format('sub %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Multiply Top of Stack by Primary } procedure TNXCComp.PopMul; begin fCCSet := False; EmitLn(Format('mul %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Divide Top of Stack by Primary } procedure TNXCComp.PopDiv; var p0, p1, p2 : string; begin p0 := RegisterName; p1 := tos; p2 := RegisterName; if (DataType(p1) in SignedTypes) and (DataType(p0) in UnsignedIntegerTypes) then begin // cast the unsigned type to a signed type EmitLn(Format('mov %s, %s', [SignedRegisterName, UnsignedRegisterName])); p0 := SignedRegisterName; end; fCCSet := False; EmitLn(Format('div %2:s, %1:s, %0:s', [p0, p1, p2])); pop; end; {---------------------------------------------------------------} { Modulo Top of Stack by Primary } procedure TNXCComp.PopMod; begin fCCSet := False; EmitLn(Format('mod %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { AND Top of Stack with Primary } procedure TNXCComp.PopAnd; begin fCCSet := False; EmitLn(Format('and %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { OR Top of Stack with Primary } procedure TNXCComp.PopOr; begin fCCSet := False; EmitLn(Format('or %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { XOR Top of Stack with Primary } procedure TNXCComp.PopXor; begin fCCSet := False; EmitLn(Format('xor %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Left Shift Top of Stack to Primary } procedure TNXCComp.PopLeftShift; begin fCCSet := False; EmitLn(Format('shl %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Right Shift Top of Stack to Primary } procedure TNXCComp.PopRightShift; begin fCCSet := False; EmitLn(Format('shr %2:s, %1:s, %0:s', [RegisterName, tos, RegisterName])); pop; end; {---------------------------------------------------------------} { Set zero flag based on __D0 value } procedure TNXCComp.SetZeroCC; begin fCCSet := True; EmitLn(Format('tst NEQ, %s, %s',[ZeroFlag, RegisterName])); end; function TNXCComp.FunctionReturnType(const name : string) : char; var i : integer; begin Result := #0; i := GlobalIdx(name); if (i > 0) and (GS_Type[i] = TOK_PROCEDURE) then Result := GS_ReturnType[i]; end; function TNXCComp.ValueIsStringType(var dt : char): boolean; begin if Token = TOK_IDENTIFIER then dt := DataType(Value) else dt := #0; Result := IsAPIStrFunc(Value); if not Result then begin Result := (Token = TOK_STRINGLIT) or ((Token = TOK_IDENTIFIER) and (dt in [TOK_STRINGDEF{, TOK_ARRAYBYTEDEF, TOK_ARRAYCHARDEF}])); if not Result then begin Result := FunctionReturnType(Value) in [TOK_STRINGDEF{, TOK_ARRAYBYTEDEF, TOK_ARRAYCHARDEF}]; if not Result then begin // what about a string array? Result := (Token = TOK_IDENTIFIER) and (dt in [TOK_ARRAYSTRING..TOK_ARRAYSTRING4]) and (Look = '['); end; end else begin // if we are indexing into the string then it is not really a string type if Look = '[' then Result := False; end; end; end; function TNXCComp.ValueIsArrayType: boolean; begin Result := IsArrayType(DataType(Value)); end; function TNXCComp.ValueIsUserDefinedType: boolean; begin Result := DataType(Value) = TOK_USERDEFINEDTYPE; end; procedure TNXCComp.CmpHelper(const cc, lhs, rhs: string); begin fCCSet := True; EmitLn(Format('cmp %s, %s, %s, %s',[cc, ZeroFlag, lhs, rhs])); end; procedure TNXCComp.PopCmpHelper(const cc : string); begin CmpHelper(cc, tos, RegisterName); pop; end; {---------------------------------------------------------------} { Set __zf If Compare was = } procedure TNXCComp.PopCmpEqual; begin PopCmpHelper('EQ'); end; {---------------------------------------------------------------} { Set __D0 If Compare was != } procedure TNXCComp.PopCmpNEqual; begin PopCmpHelper('NEQ'); end; {---------------------------------------------------------------} { Set __D0 If Compare was > } procedure TNXCComp.PopCmpGreater; begin PopCmpHelper('GT'); end; {---------------------------------------------------------------} { Set __D0 If Compare was < } procedure TNXCComp.PopCmpLess; begin PopCmpHelper('LT'); end; {---------------------------------------------------------------} { Set __D0 If Compare was <= } procedure TNXCComp.PopCmpLessOrEqual; begin PopCmpHelper('LTEQ'); end; {---------------------------------------------------------------} { Set __D0 If Compare was >= } procedure TNXCComp.PopCmpGreaterOrEqual; begin PopCmpHelper('GTEQ'); end; {---------------------------------------------------------------} { Store Primary to Variable } procedure TNXCComp.Store(const Name: string; bNoChecks : boolean); begin if not bNoChecks then CheckNotProc(Name); EmitLn(Format('mov %s, %s',[GetDecoratedIdent(Name), RegisterName])); end; procedure TNXCComp.StoreString(const Name : string; bNoChecks : boolean); begin if not bNoChecks then CheckNotProc(Name); EmitLn(Format('mov %s, %s', [GetDecoratedIdent(Name), StrBufName])); end; {---------------------------------------------------------------} { Branch Unconditional } procedure TNXCComp.Branch(L: string); begin EmitLn('jmp ' + L); end; {---------------------------------------------------------------} { Branch False } procedure TNXCComp.BranchFalse(L: string); begin // if the condition code has not been set then set it manually if not fCCSet then SetZeroCC; EmitLn(Format('brtst EQ, %s, %s', [L, ZeroFlag])); end; {---------------------------------------------------------------} { Branch True } procedure TNXCComp.BranchTrue(L: string); begin // if the condition code has not been set then set it manually if not fCCSet then SetZeroCC; EmitLn(Format('brtst NEQ, %s, %s', [L, ZeroFlag])); end; {--------------------------------------------------------------} { Write Header Info } procedure TNXCComp.Header; begin // do nothing end; {--------------------------------------------------------------} { Write Trailer Info } procedure TNXCComp.Trailer; var tmp : TStrings; begin DoCompilerStatusChange(sNXCGenerateTrailer); CheckForMain; // handle stack variables tmp := TStringList.Create; try tmp.AddStrings(NBCSource); NBCSource.Clear; // emit struct decls NBCSource.AddStrings(fStructDecls); EmitLnNoTab('dseg segment'); // structures EmitNXCRequiredStructs; EmitLn('__SSMArgs TNXCSetScreenMode'); EmitLn('__SPTArgs TNXCSoundPlayTone'); EmitLn('__SPFArgs TNXCSoundPlayFile'); // mutexes EmitLn('__SSMArgsMutex mutex'); EmitLn('__SPTArgsMutex mutex'); EmitLn('__SPFArgsMutex mutex'); EmitRegisters; EmitStackVariables; EmitLnNoTab('dseg ends'); NBCSource.AddStrings(tmp); // output the array initialization subroutine last EmitGlobalDataInitSubroutine; finally tmp.Free; end; end; {--------------------------------------------------------------} { Write the Prolog } procedure TNXCComp.Prolog(const name : string; bIsSub : boolean); begin if bIsSub then begin if AmInlining then begin fCurrentInlineFunction := fInlineFunctions.Add; fCurrentInlineFunction.Name := name; end else EmitLnNoTab('subroutine ' + name); end else EmitLnNoTab('thread ' + name); end; {--------------------------------------------------------------} { Write the Epilog } procedure TNXCComp.Epilog(bIsSub : boolean); begin if bIsSub then begin if AmInlining then begin DecrementInlineDepth; // dec(fInlineDepth); // fInlining := False; end else begin EmitLn('return'); EmitLnNoTab('ends'); end; end else EmitLnNoTab('endt'); EmitLnNoTab(''); end; {--------------------------------------------------------------} { Allocate Storage for a Static variable } procedure TNXCComp.AllocateHelper(const Name, aVal, Val, tname: string; dt : char); begin case dt of TOK_CHARDEF, TOK_ARRAYCHARDEF..TOK_ARRAYCHARDEF4 : EmitLn(Format('%s sbyte%s %s', [Name, aVal, Val])); TOK_SHORTDEF, TOK_ARRAYSHORTDEF..TOK_ARRAYSHORTDEF4 : EmitLn(Format('%s sword%s %s', [Name, aVal, Val])); TOK_LONGDEF, TOK_ARRAYLONGDEF..TOK_ARRAYLONGDEF4 : EmitLn(Format('%s sdword%s %s', [Name, aVal, Val])); TOK_BYTEDEF, TOK_ARRAYBYTEDEF..TOK_ARRAYBYTEDEF4 : EmitLn(Format('%s byte%s %s', [Name, aVal, Val])); TOK_USHORTDEF, TOK_ARRAYUSHORTDEF..TOK_ARRAYUSHORTDEF4 : EmitLn(Format('%s word%s %s', [Name, aVal, Val])); TOK_ULONGDEF, TOK_ARRAYULONGDEF..TOK_ARRAYULONGDEF4 : EmitLn(Format('%s dword%s %s', [Name, aVal, Val])); TOK_MUTEXDEF : EmitLn(Format('%s mutex', [Name])); TOK_FLOATDEF, TOK_ARRAYFLOAT..TOK_ARRAYFLOAT4 : EmitLn(Format('%s float%s %s', [Name, aVal, Val])); TOK_STRINGDEF : EmitLn(Format('%s byte[] %s', [Name, Val])); TOK_ARRAYSTRING..TOK_ARRAYSTRING4 : EmitLn(Format('%s byte[]%s %s', [Name, aVal, Val])); TOK_USERDEFINEDTYPE, TOK_ARRAYUDT..TOK_ARRAYUDT4 : EmitLn(Format('%s %s%s %s', [Name, tname, aVal, Val])); else AbortMsg(sUnknownDatatype); end; end; procedure TNXCComp.Allocate(const Name, aVal, Val, tname: string; dt : char); //var // oldInlining : boolean; begin if (dt in [TOK_FLOATDEF, TOK_ARRAYFLOAT..TOK_ARRAYFLOAT4]) and (FirmwareVersion < MIN_FW_VER2X) then AbortMsg(sFloatNotSupported); // 2007-07-05 JCH: // changed this function to perform no code generation of variable // declarations whatsoever if the current function is marked // as inline. // Instead all the local variable and parameter information is gathered // in data structures to be output at the point of the first call of // the inline function on a per CALLER basis (i.e., once per caller) // the variables will be decorated at that point with the CALLER name // and an indication that these are inline variables. // For each local variable and function parameter stored in the // data structures for a particular inline function the body of the // inline function code will be processed and any matching tokens // (i.e., the names of these variables) will be replaced with the // decorated version of the local variable or function parameter name if AmInlining then Exit; // variables are not output within inline functions // oldInlining := fInlining; try // fInlining := False; EmitLnNoTab('dseg segment'); AllocateHelper(Name, aVal, Val, tname, dt); EmitLnNoTab('dseg ends'); finally // fInlining := oldInlining; end; end; {---------------------------------------------------------------} { Parse and Translate a Math Factor with Leading NOT } procedure TNXCComp.NotNumericFactor; begin if Token = '~' then begin // handle unary complement Next; NumericFactor; Complement; end else if Token = '!' then // handle unary logical not begin Next; NumericFactor; NotIt; end else NumericFactor; end; {---------------------------------------------------------------} { Parse and Translate a Math Factor } procedure TNXCComp.NumericFactor; var savedtoken, rdt : char; savedvalue : string; oldNoCommas : boolean; begin if Token = TOK_OPENPAREN then begin OpenParen; // Next; oldNoCommas := fNoCommaOperator; try fNoCommaOperator := False; CommaExpression; finally fNoCommaOperator := oldNoCommas; end; CloseParen; end else begin // scan here so that Token is changed from IDENTIFIER to the // appropriate keyword token Scan; savedtoken := Token; savedvalue := Value; // JCH fix bug where function call with whitespace between function name // and open paren was causing a compiler error. (2007-12-10) if (savedtoken = TOK_IDENTIFIER) and (DataType(savedvalue) = TOK_PROCEDURE) then begin rdt := FunctionReturnType(savedvalue); if (rdt <> #0) and (rdt <> TOK_STRINGDEF) then DoCall(savedvalue) else AbortMsg(sInvalidReturnType); end else begin Next; case savedtoken of TOK_IDENTIFIER : begin if Token = '[' then begin fArrayIndexStack.Clear; // DoArrayIndex(DataType(fLHSName), fLHSName, savedvalue); // DoArrayIndex(ArrayBaseType(DataType(savedvalue)), fLHSName, savedvalue); DoNewArrayIndex(DataType(savedvalue), savedvalue, fLHSName); end else if ((Token = '+') and (Look = '+')) or ((Token = '-') and (Look = '-')) then begin // increment/decrement LoadVar(savedvalue); if Token = '+' then StoreInc(savedvalue, 1) else StoreDec(savedvalue, 1); Next; Next; end // The next two blocks are not exactly C with respect to operator precedence // A better way to allow for assignment/math assignment within an expression // should be found. 2010-06-07 JCH else if (Token in ['+', '-', '/', '*', '%', '&', '|', '^']) and (Look = '=') then begin MathAssignment(savedvalue); LoadVar(savedvalue); end else if (Token = '=') and (Look <> '=') then begin // var = expression rather than var == expression // i.e., an assignment statement Next; DoAssignValue(savedvalue, DataType(savedvalue)); LoadVar(savedvalue); end // // end of not exactly C handling of assignment/math assignment // else if savedvalue = 'true' then LoadConst('1') else if savedvalue = 'false' then LoadConst('0') else if IsAPIFunc(savedvalue) then begin DoCallAPIFunc(savedvalue); end else if IsArrayType(fLHSDataType) and not fProcessingMathAssignment then begin rdt := DataType(savedvalue); if not TypesAreCompatible(fLHSDataType, rdt) then AbortMsg(sDatatypesNotCompatible) else EmitLn(Format('mov %s, %s', [GetDecoratedIdent(fLHSName), GetDecoratedIdent(savedvalue)])); end else if (fLHSDataType = TOK_USERDEFINEDTYPE) and not fProcessingMathAssignment then begin if GetUDTType(fLHSName) <> GetUDTType(savedvalue) then AbortMsg(sUDTNotEqual) else EmitLn(Format('mov %s, %s', [GetDecoratedIdent(fLHSName), GetDecoratedIdent(savedvalue)])); end else LoadVar(savedvalue); end; TOK_ASM : begin DoAsm(fLHSDataType); end; TOK_NUM, TOK_HEX : begin LoadConst(savedvalue); end; '-' : begin if Token = TOK_NUM then begin LoadConst(savedvalue+value); Next; end else Expected(sMathFactor); end; else Expected(sMathFactor); end; end; end; end; {--------------------------------------------------------------} { Recognize and Translate a Multiply } procedure TNXCComp.Multiply; begin Next; NotNumericFactor; PopMul; end; {-------------------------------------------------------------} { Recognize and Translate a Divide } procedure TNXCComp.Divide; begin Next; NotNumericFactor; PopDiv; end; {-------------------------------------------------------------} { Recognize and Translate a Module } procedure TNXCComp.Modulo; begin Next; NotNumericFactor; PopMod; end; {---------------------------------------------------------------} { Parse and Translate a Math Term } procedure TNXCComp.Term; begin NotNumericFactor; while IsMulop(Token) do begin PushPrim; case Token of '*': Multiply; '/': Divide; '%': Modulo; end; end; end; {--------------------------------------------------------------} { Recognize and Translate an Add } procedure TNXCComp.Add; begin Next; Term; PopAdd; end; {-------------------------------------------------------------} { Recognize and Translate a Subtract } procedure TNXCComp.Subtract; begin Next; Term; PopSub; end; {---------------------------------------------------------------} { Parse and Translate an Expression } procedure TNXCComp.Expression; var prev, lenVal : integer; oldExpStr, optExp : string; begin fExpStrHasVars := False; // 2009-04-09 JCH: // Store the old expression string and restore it at the end of this routine // so that recursive optimizations do not destroy the previous level of // the expression. This fixes the bug caused by commenting out // "and not (fExpStr[1] in ['+', '-'])" in the OptimizeExpression function // below. Without this, an expression like x = MyFunc(233)+10; was being // optimized to x = 10; oldExpStr := fExpStr; try // set the old expression to be everything except for the first token in // the new expression (aka "Value"). lenVal := Length(Value); Delete(oldExpStr, Length(oldExpStr)-lenVal+1, lenVal); // now start our new expression with the current token fExpStr := Value; prev := NBCSource.Count; if IncrementOrDecrement then begin // handle pre-increment or pre-decrement unary operators DoPreIncOrDec(true); end else begin if IsAddOp(Token) then ClearReg // handle + and - unary operators else Term; while IsAddop(Token) do begin PushPrim; case Token of '+': Add; '-': Subtract; end; end; optExp := OptimizeExpression(prev); end; finally fExpStr := oldExpStr + optExp + Value; end; end; function TNXCComp.OptimizeExpression(const idx: integer) : string; begin fLastExpressionOptimizedToConst := False; System.Delete(fExpStr, Length(fExpStr), 1); Result := fExpStr; if (OptimizeLevel >= 1) and (NBCSource.Count > (idx+1)) and not fExpStrHasVars then begin // 2009-03-18 JCH: I do not recall why I added the check for // + and - as the first character of an expression // I haven't been able to detect any harm in removing this check but // it could be something very obscure that will come up again // 2009-04-09 JCH: See my comment in the Expression function above. // The commented-out code was preventing a bug that had far too many // lines of code being removed if an expression ended in +nnn or -nnn. if (fExpStr <> '') {and not (fExpStr[1] in ['+', '-'])} then begin fCalc.SilentExpression := fExpStr; if not fCalc.ParserError then begin if StatementType = stFloat then fExpStr := NBCFloatToStr(fCalc.Value) else fExpStr := IntToStr(Trunc(fCalc.Value)); Result := fExpStr; // in theory, we can replace all the lines between idx and // NBCSource.Count with one line while NBCSource.Count > idx do NBCSource.Delete(NBCSource.Count-1); LoadConst(fExpStr); fExpStr := ''; fLastExpressionOptimizedToConst := True; end; end; end; end; {---------------------------------------------------------------} { Parse and Translate a String Expression } procedure TNXCComp.StringConcatAssignment(const Name: string); begin if Look = '=' then begin Next; // move to '=' Next; // move to next token StringExpression(Name, True); StoreString(Name); end else AbortMsg(sInvalidStringAssign); end; function TNXCComp.GetDecoratedIdent(const val : string) : string; var i : integer; begin Result := val; if not AlreadyDecorated(val) then begin case WhatIs(val) of stParam : Result := ApplyDecoration(fCurrentThreadName, val, 0); stLocal : begin // apply decoration at greatest nesting level and iterate // until we find the right value. for i := fNestingLevel downto 0 do begin Result := ApplyDecoration(fCurrentThreadName, val, i); if IsLocal(Result) then break; end; end; else Result := val; end; end; end; function TNXCComp.GetDecoratedValue : string; begin Result := GetDecoratedIdent(Value); end; function TNXCComp.StringExpression(const Name : string; bAdd : boolean) : boolean; var asmStr, val, aval, tmpStr : string; dt : char; AHV : TArrayHelperVar; begin Result := False; SkipWhite; fCCSet := False; asmStr := ''; if Look = TOK_OPENPAREN then begin // a function call that returns a string val := Value; if DataType(val) = TOK_PROCEDURE then begin if FunctionReturnType(val) = TOK_STRINGDEF then DoCall(val) else Expected(sStringReturnValue); end else begin Next; // move to TOK_OPENPAREN StringFunction(val); end; tmpStr := StrRetValName; if bAdd then asmStr := Format('strcat %s, %s, ', [StrBufName, GetDecoratedIdent(Name)]) else asmStr := Format('strcat %s, ', [StrBufName]); end else if Look = '[' then begin val := Value; Next; fArrayIndexStack.Clear; Result := DoNewArrayIndex(DataType(val), val, StrRetValName); tmpStr := StrRetValName; if bAdd then asmStr := Format('strcat %s, %s, ', [StrBufName, GetDecoratedIdent(Name)]) else asmStr := Format('strcat %s, ', [StrBufName]); end else if Value = 'asm' then begin // asm Next; dt := #0; DoAsm(dt); fSemiColonRequired := True; if dt <> TOK_STRINGDEF then Expected(sStringReturnValue) else begin tmpStr := StrRetValName; if bAdd then asmStr := Format('strcat %s, %s, ', [StrBufName, GetDecoratedIdent(Name)]) else asmStr := Format('strcat %s, ', [StrBufName]); end; end else begin CheckString; tmpStr := GetDecoratedValue; if bAdd then asmStr := Format('strcat %s, %s, ', [StrBufName, GetDecoratedIdent(Name)]) else asmStr := Format('strcat %s, ', [StrBufName]); Next; end; // in all cases we may want to recurse if Token = '+' then begin // we are overloading the + for string concatenation // we need to store the value from this string expression into // a temporary variable so that it is not overwritten by // recursing into subsequent string expressions AHV := fArrayHelpers.GetHelper(fCurrentThreadName, '', TOK_ARRAYBYTEDEF); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, TOK_ARRAYBYTEDEF, '', ''); // move result of string expression to newly allocated temporary variable EmitLn(Format('mov %s, %s', [aval, tmpStr])); Next; // skip past the + asmStr := asmStr + StrCatHelper(aval + ', ', '+'); { while Token = '+' do begin Next; // skip past + CheckString; asmStr := asmStr + ', ' + GetDecoratedValue; Next; end; } finally fArrayHelpers.ReleaseHelper(AHV); end; end else begin // no string concatenation asmStr := asmStr + tmpStr; // add in the variable from this string expression end; if asmStr <> '' then EmitLn(asmStr); end; procedure TNXCComp.EqualArrayOrUDT(const lhs : string); var rhs : string; begin Next; // two equal signs of equality comparison MatchString('='); CheckIdent; rhs := Value; Next; CmpHelper('EQ', lhs, GetDecoratedIdent(rhs)); StoreZeroFlag; end; procedure TNXCComp.LessArrayOrUDT(const lhs : string); var rhs : string; begin Next; case Token of '=' : begin Next; CheckIdent; rhs := Value; Next; CmpHelper('LTEQ', lhs, GetDecoratedIdent(rhs)); end; '>' : begin Next; CheckIdent; rhs := Value; Next; CmpHelper('NEQ', lhs, GetDecoratedIdent(rhs)); end; else CheckIdent; rhs := Value; Next; CmpHelper('LT', lhs, GetDecoratedIdent(rhs)); end; StoreZeroFlag; end; procedure TNXCComp.GreaterArrayOrUDT(const lhs: string); var rhs : string; begin Next; case Token of '=' : begin Next; CheckIdent; rhs := Value; Next; CmpHelper('GTEQ', lhs, GetDecoratedIdent(rhs)); end; else CheckIdent; rhs := Value; Next; CmpHelper('GT', lhs, GetDecoratedIdent(rhs)); end; StoreZeroFlag; end; procedure TNXCComp.NEqualArrayOrUDT(const lhs: string); var rhs : string; begin Next; if Token = '=' then begin Next; CheckIdent; rhs := Value; Next; CmpHelper('NEQ', lhs, GetDecoratedIdent(rhs)); StoreZeroFlag; end else Expected('"!="'); end; procedure TNXCComp.EqualString; begin Next; // two equal signs of equality comparison MatchString('='); StringExpression(''); CmpHelper('EQ', StrTmpBufName, StrBufName); StoreZeroFlag; end; procedure TNXCComp.LessString; begin Next; case Token of '=' : begin Next; StringExpression(''); CmpHelper('LTEQ', StrTmpBufName, StrBufName); end; '>' : begin Next; StringExpression(''); CmpHelper('NEQ', StrTmpBufName, StrBufName); end; else StringExpression(''); CmpHelper('LT', StrTmpBufName, StrBufName); end; StoreZeroFlag; end; procedure TNXCComp.GreaterString; begin Next; case Token of '=' : begin Next; StringExpression(''); CmpHelper('GTEQ', StrTmpBufName, StrBufName); end; else StringExpression(''); CmpHelper('GT', StrTmpBufName, StrBufName); end; StoreZeroFlag; end; procedure TNXCComp.NEqualString; begin Next; if Token = '=' then begin Next; StringExpression(''); CmpHelper('NEQ', StrTmpBufName, StrBufName); StoreZeroFlag; end else Expected('"!="'); end; procedure TNXCComp.StringRelation; var valLeftOnStack : boolean; begin (* The Expression function handles ++, --, +, -, ~, and ! unary operators for numeric expressions. Do I need to handle these operators for string expressions (on both lhs and rhs)? *) valLeftOnStack := StringExpression(''); if IsRelop(Token) then begin // copy to temp string buffer EmitLn(Format('mov %s, %s', [StrTmpBufName, StrBufName])); case Token of '=': EqualString; '<': LessString; '>': GreaterString; '!': NEqualString; end; end else begin if not valLeftOnStack then LoadConst('1'); // a string expression is "true" end; end; procedure TNXCComp.ArrayOrUDTRelation; var lhs : string; begin (* The Expression function handles ++, --, +, -, ~, and ! unary operators for numeric expressions. Do I need to handle these operators for array/UDT expressions (on both lhs and rhs)? *) // only variables are allowed here - no expressions CheckIdent; lhs := GetDecoratedIdent(Value); Next; if IsRelop(Token) then begin case Token of '=': EqualArrayOrUDT(lhs); '<': LessArrayOrUDT(lhs); '>': GreaterArrayOrUDT(lhs); '!': NEqualArrayOrUDT(lhs); end; end else begin // is the left hand side an array, udt or a scalar? if IsArrayType(fLHSDataType) or IsUDT(fLHSDataType) then begin // do something clever fUDTOnStack := lhs; end else LoadConst('1'); // an array or UDT expression is "true" end; end; procedure TNXCComp.NumericRelation; var savedToken, savedLook : Char; begin NumericRelationLTGT; while ((Token = '=') and (Look = '=')) or // C/C++ equal ((Token = '!') and (Look = '=')) or // C/C++ not equal ((Token = '<') and (Look = '>')) do // pascal not equal begin savedToken := Token; savedLook := Look; PushPrim; Next; Next; NumericRelationLTGT; if (savedToken = '=') and (savedLook = '=') then PopCmpEqual else PopCmpNEqual; StoreZeroFlag; end; end; procedure TNXCComp.NumericRelationLTGT; var savedToken, savedLook : Char; begin NumericShiftLeftRight; while (not ((Token = '<') and (Look = '>'))) and // not <> (pascal not equal) (((Token = '<') and (Look = '=')) or // <= ((Token = '<') and (Look <> '<')) or // < (not left shift) ((Token = '>') and (Look = '=')) or // >= ((Token = '>') and (Look <> '>'))) do // > (not right shift) begin savedToken := Token; savedLook := Look; PushPrim; if (Look = '=') then // handle <= and >= case Next; Next; NumericShiftLeftRight; if (savedToken = '<') and (savedLook = '=') then // <= PopCmpLessOrEqual else if (savedToken = '<') and (savedLook <> '<') then // < PopCmpLess else if (savedToken = '>') and (savedLook = '=') then // >= PopCmpGreaterOrEqual else // > PopCmpGreater; StoreZeroFlag; end; end; procedure TNXCComp.NumericShiftLeftRight; var savedToken, savedLook : Char; begin Expression; while ((Token = '<') and (Look = '<')) or // << ((Token = '>') and (Look = '>')) do // >> begin savedToken := Token; savedLook := Look; PushPrim; Next; Next; Expression; if (savedToken = '<') and (savedLook = '<') then PopLeftShift else PopRightShift; end; end; {---------------------------------------------------------------} { Parse and Translate a Relation } procedure TNXCComp.Relation; var dt : char; begin // would it be better to check for unary operators before branching by // relation type??? if ValueIsStringType(dt) then begin if (Look <> '[') or (dt in [TOK_ARRAYSTRING..TOK_ARRAYSTRING4]) then begin StringRelation; end else NumericRelation; end else if (Token = TOK_IDENTIFIER) and (ValueIsArrayType or ValueIsUserDefinedType) then begin if Look = '[' then begin { dt := RemoveArrayDimension(DataType(Value)); if IsArrayType(dt) then AbortMsg(sInvalidArrayExpr) else } NumericRelation; end else begin ArrayOrUDTRelation; end; end else begin NumericRelation; end; end; procedure TNXCComp.StoreZeroFlag; begin // 2009-10-13 JCH // we can't afford to store the zero flag sometimes to the signed register // and other times to the unsigned register or, worse, to the float register // so we always reset the statement type before we store the flag. ResetStatementType; EmitLn(Format('mov %s, %s', [RegisterName, ZeroFlag])); end; {---------------------------------------------------------------} { Parse and Translate a Boolean Term } procedure TNXCComp.BoolTerm; var L : string; begin L := NewLabel; // 2010-05-27 JCH new code for BoolTerm BitOr; while (Token = '&') and (Look = '&') do begin // move to the second '&' Next; // move past the second '&' Next; // convert D0 to boolean value if necessary if not fCCSet then begin SetZeroCC; StoreZeroFlag; end; BranchFalse(L); PushPrim; BitOr; if not fCCSet then begin // convert D0 to boolean value if necessary SetZeroCC; StoreZeroFlag; end; PopAnd; end; PostLabel(L); end; procedure TNXCComp.BitOr; begin BitXor; while (Token = '|') and (Look <> '|') do begin Next; PushPrim; BitXor; PopOr; end; end; procedure TNXCComp.BitXor; begin BitAnd; while (Token = '^') do begin Next; PushPrim; BitAnd; PopXor; end; end; procedure TNXCComp.BitAnd; begin Relation; while (Token = '&') and (Look <> '&') do begin Next; PushPrim; Relation; PopAnd; end; end; procedure TNXCComp.CommaExpression; begin BoolExpression; if fNoCommaOperator then Exit; // handle comma? if Token = TOK_COMMA then begin Next; // skip past the comma CommaExpression; end; end; {---------------------------------------------------------------} { Parse and Translate a Boolean Expression } procedure TNXCComp.BoolExpression; var L1, L2 : string; begin fCCSet := False; BoolSubExpression; while Token = '?' do begin // we are parsing a ?: expression Next; L1 := NewLabel; L2 := NewLabel; BranchFalse(L1); CommaExpression; Branch(L2); MatchString(':'); PostLabel(L1); CommaExpression; PostLabel(L2); end; // ResetStatementType; end; // BoolTerm || BoolTerm procedure TNXCComp.BoolSubExpression; var L : string; // bLogicalOr : boolean; begin L := NewLabel; BoolTerm; while (Token = '|') and (Look = '|') do begin // advance to second '|' Next; // advance past the second '|' Next; // convert D0 to boolean value if necessary if not fCCSet then begin SetZeroCC; StoreZeroFlag; end; BranchTrue(L); PushPrim; BoolTerm; if not fCCSet then begin // convert D0 to boolean value if necessary SetZeroCC; StoreZeroFlag; end; PopOr; end; PostLabel(L); end; function TNXCComp.GetParamName(procname: string; idx: integer): string; var i : integer; begin Result := ''; i := fFuncParams.IndexOf(procname, idx); if i <> -1 then Result := ApplyDecoration(procname, fFuncParams[i].Name, 0); end; function DataTypeToParamType(ptype : char) : TFuncParamType; begin case ptype of TOK_ARRAYCHARDEF..TOK_ARRAYCHARDEF4, TOK_CHARDEF : Result := fptSBYTE; TOK_ARRAYSHORTDEF..TOK_ARRAYSHORTDEF4, TOK_SHORTDEF : Result := fptSWORD; TOK_ARRAYLONGDEF..TOK_ARRAYLONGDEF4, TOK_LONGDEF : Result := fptSLONG; TOK_ARRAYBYTEDEF..TOK_ARRAYBYTEDEF4, TOK_BYTEDEF : Result := fptUBYTE; TOK_ARRAYUSHORTDEF..TOK_ARRAYUSHORTDEF4, TOK_USHORTDEF : Result := fptUWORD; TOK_ARRAYULONGDEF..TOK_ARRAYULONGDEF4, TOK_ULONGDEF : Result := fptULONG; TOK_ARRAYUDT..TOK_ARRAYUDT4, TOK_USERDEFINEDTYPE : Result := fptUDT; TOK_ARRAYSTRING..TOK_ARRAYSTRING4, TOK_STRINGDEF : Result := fptString; TOK_ARRAYFLOAT..TOK_ARRAYFLOAT4, TOK_FLOATDEF : Result := fptFloat; TOK_MUTEXDEF : Result := fptMutex; else Result := fptUBYTE; end; end; procedure TNXCComp.AddFunctionParameter(pname, varname, tname: string; idx: integer; ptype : char; bIsConst, bIsRef, bIsArray : boolean; aDim : integer; bHasDefault : boolean; defValue : string); begin // if this function is not an inline function then we will automagically // convert any Const not Ref parameter into a Const Ref parameter if bIsConst and not bIsRef and not AmInlining then bIsRef := True; // convert to const ref type (* // add a check here for a parameter that is const but not reference // when we are not inlining if bIsConst and not bIsRef and not AmInlining and (ptype in NonAggregateTypes) then ReportProblem(linenumber, CurrentFile, sConstNotInline, false); // AbortMsg(sConstNotInline); *) with fFuncParams.Add do begin ProcName := pname; Name := varname; ParamType := DataTypeToParamType(ptype); ParamTypeName := tname; ParamIndex := idx; IsArray := bIsArray; IsConstant := bIsConst; IsReference := bIsRef; ArrayDimension := aDim; FuncIsInline := AmInlining; HasDefault := bHasDefault; DefaultValue := defValue; end; end; function TNXCComp.FunctionParameterCount(const name : string) : integer; begin Result := fFuncParams.ParamCount(name); end; function TNXCComp.FunctionRequiredParameterCount(const name : string) : integer; begin Result := fFuncParams.RequiredParamCount(name); end; function TNXCComp.FunctionParameterType(const name: string; idx: integer): char; var i : integer; begin Result := #0; i := fFuncParams.IndexOf(name, idx); if i <> -1 then Result := fFuncParams[i].ParameterDataType; end; function TNXCComp.FunctionParameterTypeName(const name: string; idx: integer): string; var i : integer; begin Result := ''; i := fFuncParams.IndexOf(name, idx); if i <> -1 then Result := fFuncParams[i].ParamTypeName; end; function TNXCComp.FunctionParameterIsConstant(const name: string; idx: integer): boolean; var i : integer; begin Result := False; i := fFuncParams.IndexOf(name, idx); if i <> -1 then Result := fFuncParams[i].IsConstant; end; function TNXCComp.FunctionParameterHasDefault(const name: string; idx: integer): boolean; var i : integer; begin Result := False; i := fFuncParams.IndexOf(name, idx); if i <> -1 then Result := fFuncParams[i].HasDefault; end; function TNXCComp.FunctionParameterDefaultValue(const name: string; idx: integer): string; var i : integer; begin Result := ''; i := fFuncParams.IndexOf(name, idx); if i <> -1 then Result := fFuncParams[i].DefaultValue; end; function TNXCComp.GetFunctionParam(const procname : string; idx : integer) : TFunctionParameter; var i : integer; begin Result := nil; i := fFuncParams.IndexOf(procname, idx); if i <> -1 then Result := fFuncParams[i]; end; function TNXCComp.AdvanceToNextParam : string; begin Result := ''; Next; while not ((Token in [TOK_CLOSEPAREN, TOK_COMMA]) or endofallsource) do begin Result := Result + Value; Next; end; Result := Trim(Result); end; procedure TNXCComp.DoCall(procname : string); var protocount, protoreqcount, acount, idx, i : integer; dt, rdt, pdt, oldLHSDT : char; parname, parvalue, junk, oldLHSName : string; bError : boolean; fp : TFunctionParameter; fInputs : TStrings; bFunctionIsInline, bSafeCall : boolean; inlineFunc : TInlineFunction; begin fNoCommaOperator := True; try fUDTOnStack := ''; // by default there is no UDT/Array on the return stack if fFunctionNameCallStack.IndexOf(procname) = -1 then begin fFunctionNameCallStack.Add(procname); try // is procname the same as the current thread name // (i.e., is this a recursive function call)? if procname = fCurrentThreadName then AbortMsg(sRecursiveNotAllowed); // is procname an inline function? idx := fInlineFunctions.IndexOfName(procname); bFunctionIsInline := idx <> -1; if bFunctionIsInline then begin inlineFunc := fInlineFunctions[idx]; if inlineFunc.Parameters.Count = 0 then inlineFunc.Parameters := fFuncParams; inlineFunc.CurrentCaller := fCurrentThreadName; end else inlineFunc := nil; fInputs := TStringList.Create; try acount := 0; protocount := FunctionParameterCount(procname); protoreqcount := FunctionRequiredParameterCount(procname); Next; bError := Value <> TOK_OPENPAREN; if not bError then OpenParen else Expected('"("'); if bFunctionIsInline and (inlineFunc.Callers.IndexOf(fCurrentThreadName) = -1) then begin inlineFunc.Callers.Add(fCurrentThreadName); // first call in this thread to this inline function // output all parameters and local variables with decoration EmitInlineParametersAndLocals(inlineFunc); // make sure the very first call to this inline function // by this thread doesn't get optimized out fExpStr := '__DO_NOT_OPTIMIZE!@#$%_'; end; bSafeCall := GlobalUsesSafeCall(procname); // acquire the mutex if not bFunctionIsInline and (SafeCalls or bSafeCall) then begin EmitLnNoTab('#pragma safecalling'); EmitLn(Format('acquire __%s_mutex', [procname])); end; while not bError and (Token <> TOK_CLOSEPAREN) do begin if acount >= protocount then begin AbortMsg(sTooManyArgs); bError := True; end; fp := GetFunctionParam(procname, acount); if Assigned(fp) then begin dt := FunctionParameterType(procname, acount); parname := GetParamName(procname, acount); if bFunctionIsInline then parname := InlineName(fCurrentThreadName, parname); // now process the current parameter oldLHSDT := fLHSDataType; oldLHSName := fLHSName; fLHSDataType := dt; fLHSName := parname; try // reference types cannot take expressions if fp.IsVarReference then begin CheckIdent; parvalue := GetDecoratedValue; pdt := DataType(parvalue); if fp.IsArray then begin if not IsArrayType(pdt, True) then Expected(sArrayDatatype); end; fInputs.AddObject(parvalue, fp); EmitLn(Format('mov %s, %s', [parname, parvalue])); junk := AdvanceToNextParam; if junk <> '' then AbortMsg(sExpNotSupported) else CheckTypeCompatibility(fp, pdt, parvalue); end // beginning of addition for handling expressions for UDT and array parameters else if fp.IsArray or (fp.ParamType = fptUDT) then begin fInputs.AddObject('', fp); if IsArrayType(dt) then begin DoArrayAssignValue(parname, '', dt); end else if dt = TOK_USERDEFINEDTYPE then begin GetAndStoreUDT(parname); end; end // end of addition for handling expressions for UDT and array parameters // beginning of previously commented out block else if fp.IsConstant and not fp.IsReference then begin // must be a number (or constant expression) or a string literal if dt = TOK_STRINGDEF then begin parvalue := Value; CheckStringConst; fp.ConstantValue := parvalue; fInputs.AddObject(parvalue, fp); if bFunctionIsInline then begin i := inlineFunc.Parameters.IndexOf(inlineFunc.Name, acount); if i <> -1 then begin inlineFunc.Parameters[i].Assign(fp); end; end; EmitLn(Format('mov %s, %s', [parname, parvalue])); Next; end else if dt <> #0 then begin // collect tokens to TOK_CLOSEPAREN or TOK_COMMA parvalue := Value; SkipWhite; // skip any whitespace just in case while not (Look in [TOK_CLOSEPAREN, TOK_COMMA]) or endofallsource do begin Next; parvalue := parvalue + Value; end; Next; fCalc.SilentExpression := GetValueOf(parvalue); if not fCalc.ParserError then begin parvalue := NBCFloatToStr(fCalc.Value); fCalc.SetVariable(parname, fCalc.Value); fp.ConstantValue := parvalue; fInputs.AddObject(parvalue, fp); if bFunctionIsInline then begin i := inlineFunc.Parameters.IndexOf(inlineFunc.Name, acount); if i <> -1 then begin inlineFunc.Parameters[i].Assign(fp); end; end; EmitLn(Format('mov %s, %s', [parname, parvalue])); end else begin if IsParamConst(parvalue) then begin fp.ConstantValue := ApplyDecoration(fCurrentThreadName, parvalue, 0); // fp.ConstantValue := parvalue; fInputs.AddObject(parvalue, fp); if bFunctionIsInline then begin i := inlineFunc.Parameters.IndexOf(inlineFunc.Name, acount); if i <> -1 then begin inlineFunc.Parameters[i].Assign(fp); end; end; end else begin fInputs.AddObject('', fp); Expected(sConstOrConstExpr); end; end; end; end // end of previously commented out block else begin fInputs.AddObject('', fp); // pass in True to make it so that no checks are performed // in Store and StoreString DoAssignValue(parname, dt, False); end; finally fLHSDataType := oldLHSDT; fLHSName := oldLHSName; end; end; inc(acount); Scan; if acount < protoreqcount then begin MatchString(TOK_COMMA); Scan; end else begin // we are now supposed to either have a comma or a close paren // depending on the value of acount compared to protocount if (acount < protocount) and not (Token in [TOK_COMMA, TOK_CLOSEPAREN]) then begin MatchString(TOK_COMMA); Scan; end else begin if Token = TOK_COMMA then begin Next; Scan; end; end; end; end; if Value = TOK_CLOSEPAREN then begin CloseParen; // look up the decorated function name given the procname // and the types of all the parameters passed into the function // if we find a function with the right name and parameters // then keep going. Otherwise report an error // if the number of parameters provided is less than the function's // defined number of parameters if protoreqcount > acount then AbortMsg(sTooFewParams); while acount < protocount do begin // use default values for all the arguments not provided fp := GetFunctionParam(procname, acount); if Assigned(fp) then begin parname := GetParamName(procname, acount); if bFunctionIsInline then parname := InlineName(fCurrentThreadName, parname); parvalue := FunctionParameterDefaultValue(procname, acount); EmitLn(Format('mov %s, %s', [parname, parvalue])); end; inc(acount); end; if bFunctionIsInline then inlineFunc.Emit(NBCSource) else EmitLn('call '+procname); fCCSet := False; for i := 0 to fInputs.Count - 1 do begin fp := TFunctionParameter(fInputs.Objects[i]); if fp.IsVarReference then begin // must copy out the non-const references parname := GetParamName(procname, i); if bFunctionIsInline then parname := InlineName(fCurrentThreadName, parname); EmitLn(Format('mov %s, %s', [fInputs[i], parname])); end; end; rdt := FunctionReturnType(procname); if rdt = TOK_STRINGDEF then begin // copy value from subroutine to register if bFunctionIsInline then EmitLn(Format('mov %s, %s', [StrRetValName, StrBufName(InlineName(fCurrentThreadName, procname))])) else EmitLn(Format('mov %s, %s', [StrRetValName, StrBufName(procname)])); end else if IsUDT(rdt) or IsArrayType(rdt) then begin // tell the compiler that a UDT/Array is on stack if bFunctionIsInline then fUDTOnStack := Format('__result_%s', [InlineName(fCurrentThreadName, procname)]) else fUDTOnStack := Format('__result_%s', [procname]); end else if rdt in NonAggregateTypes then begin // copy value from subroutine to register if rdt = TOK_FLOATDEF then StatementType := stFloat else if not (rdt in UnsignedIntegerTypes) then StatementType := stSigned else StatementType := stUnsigned; if bFunctionIsInline then EmitLn(Format('mov %s, %s', [RegisterName, RegisterName(InlineName(fCurrentThreadName, procname))])) else EmitLn(Format('mov %s, %s', [RegisterName, RegisterName(procname)])); end; // release the mutex if not bFunctionIsInline and (SafeCalls or bSafeCall) then EmitLn(Format('release __%s_mutex', [procname])); end else Expected('")"'); finally fInputs.Free; end; finally fFunctionNameCallStack.Delete(fFunctionNameCallStack.Count - 1); end; end else begin AbortMsg(sNestedCallsError); end; finally fNoCommaOperator := False; end; end; procedure TNXCComp.StoreArray(const name, idx, val : string); begin // move RHS to array[idx] or set array = to RHS if idx = '' then EmitLn(Format('arrbuild %0:s, %s', [GetDecoratedIdent(name), val])) else EmitLn(Format('replace %0:s, %0:s, %s, %s', [GetDecoratedIdent(name), idx, val])); end; function TNXCComp.RemoveArrayDimension(dt: char): char; begin Result := dt; if IsArrayType(dt) then begin case dt of TOK_ARRAYFLOAT : Result := TOK_FLOATDEF; TOK_ARRAYSTRING : Result := TOK_STRINGDEF; TOK_ARRAYUDT : Result := TOK_USERDEFINEDTYPE; TOK_ARRAYCHARDEF : Result := TOK_CHARDEF; TOK_ARRAYSHORTDEF : Result := TOK_SHORTDEF; TOK_ARRAYLONGDEF : Result := TOK_LONGDEF; TOK_ARRAYBYTEDEF : Result := TOK_BYTEDEF; TOK_ARRAYUSHORTDEF : Result := TOK_USHORTDEF; TOK_ARRAYULONGDEF : Result := TOK_ULONGDEF; else Result := Char(Ord(dt)-1); end; end else if dt = TOK_STRINGDEF then Result := TOK_BYTEDEF; end; function TNXCComp.AddArrayDimension(dt: char): char; begin case dt of TOK_FLOATDEF : Result := TOK_ARRAYFLOAT; TOK_STRINGDEF : Result := TOK_ARRAYSTRING; TOK_USERDEFINEDTYPE : Result := TOK_ARRAYUDT; TOK_CHARDEF : Result := TOK_ARRAYCHARDEF; TOK_SHORTDEF : Result := TOK_ARRAYSHORTDEF; TOK_LONGDEF : Result := TOK_ARRAYLONGDEF; TOK_BYTEDEF : Result := TOK_ARRAYBYTEDEF; TOK_USHORTDEF : Result := TOK_ARRAYUSHORTDEF; TOK_ULONGDEF : Result := TOK_ARRAYULONGDEF; else if IsArrayType(dt) then begin Result := Char(Ord(dt)+1); // if ArrayBaseType(Result) <> ArrayBaseType(dt) then // AbortMsg(sInvalidArrayDim); end else Result := dt; end; end; procedure TNXCComp.ArrayAssignment(const name : string; dt : char; bIndexed : boolean); var tmp, aval, udType, tmpUDTName : string; oldType : char; AHV : TArrayHelperVar; begin tmp := ''; if bIndexed then begin Next; oldType := fLHSDataType; try fLHSDataType := TOK_LONGDEF; CommaExpression; finally fLHSDataType := oldType; end; MatchString(']'); push; tmp := tos; EmitLn(Format('mov %s, %s', [tmp, RegisterName])); dt := RemoveArrayDimension(dt); fLHSDataType := RemoveArrayDimension(fLHSDataType); end; // check for additional levels of indexing if (Token = '[') and (IsArrayType(dt) or (dt = TOK_STRINGDEF)) then begin udType := ''; if IsUDT(ArrayBaseType(dt)) then udType := GetUDTType(name); // get a temporary thread-safe variable of the right type AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, dt); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, dt, udType, ''); // set the variable to the specified element from previous array EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(name), tmp])); // pass its name into the call to ArrayAssignment ArrayAssignment(aval, dt, True); // store temporary thread-safe variable back into previous array StoreArray(name, tmp, aval); finally fArrayHelpers.ReleaseHelper(AHV); end; end else if (Token = '.') and IsUDT(dt) then // check for struct member notation begin // set the variable to the specified element from previous array udType := ''; if IsUDT(ArrayBaseType(dt)) then udType := GetUDTType(name); // get a temporary thread-safe variable of the right type AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, dt); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, dt, udType, ''); // set the variable to the specified element from previous array EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(name), tmp])); // process dots tmpUDTName := aval; tmpUDTName := tmpUDTName + Value; // add the dot Next; tmpUDTName := tmpUDTName + Value; // add everything else // set value to full udt name Value := tmpUDTName; // recurse to the Assignment procedure Assignment; // store temporary thread-safe variable back into previous array StoreArray(name, tmp, aval); finally fArrayHelpers.ReleaseHelper(AHV); end; end else if Token in ['+', '-', '/', '*', '%', '&', '|', '^', '>', '<'] then begin if (dt in NonAggregateTypes) and bIndexed then begin // get the indexed value if dt = TOK_FLOATDEF then StatementType := stFloat else if not (dt in UnsignedIntegerTypes) then StatementType := stSigned else StatementType := stUnsigned; push; aval := tos; EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(name), tmp])); MathAssignment(aval); StoreArray(name, tmp, aval); pop; end // 2011-02-11 - Added code to handle math assignment for arrays of UDTs else if IsUDT(dt) and bIndexed then begin // dt is not non-aggregated // set the variable to the specified element from previous array udType := ''; if IsUDT(ArrayBaseType(dt)) then udType := GetUDTType(name); // get a temporary thread-safe variable of the right type AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, dt); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, dt, udType, ''); // set the variable to the specified element from previous array EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(name), tmp])); MathAssignment(aval); // store temporary thread-safe variable back into previous array StoreArray(name, tmp, aval); finally fArrayHelpers.ReleaseHelper(AHV); end; end // 2011-02-11 - End of new code for arrays of UDTs else begin MathAssignment(name); end; end else begin MatchString('='); DoArrayAssignValue(name, tmp, dt); end; if bIndexed then pop; end; procedure TNXCComp.CheckDataType(dt: char); var rhsDT : char; begin rhsDT := DataType(Value); if Look = '[' then rhsDT := RemoveArrayDimension(rhsDT); if (IsArrayType(rhsDT) <> IsArrayType(dt)) or (GetArrayDimension(rhsDT) <> GetArrayDimension(dt)) then AbortMsg(sDatatypesNotCompatible); end; procedure TNXCComp.DoArrayAssignValue(const aName, idx: string; dt: char); var oldType : Char; oldName, udType : string; AHV : TArrayHelperVar; begin if dt = TOK_STRINGDEF then begin // name of array variable is of type string StringExpression(aName); StoreArray(aName, idx, StrBufName); end else if (Token = TOK_IDENTIFIER) and IsUDT(DataType(Value)) {dt = TOK_USERDEFINEDTYPE} then begin CheckIdent; CheckDataType(dt); StoreArray(aName, idx, GetDecoratedValue); Next; end else if IsArrayType(dt) then begin // lhs is an array. That means we can only have a factor on the rhs. if idx = '' then begin if Token = '!' then begin Next; NumericFactor; if fUDTOnStack <> '' then begin Store(aName); fUDTOnStack := ''; end; EmitLn(Format('not %0:s, %0:s', [GetDecoratedIdent(aName)])); end else begin NumericFactor; if fUDTOnStack <> '' then begin Store(aName); fUDTOnStack := ''; end; end; end else begin if Look = '[' then begin oldType := fLHSDataType; oldName := fLHSName; try udType := ''; if IsUDT(ArrayBaseType(dt)) then udType := GetUDTType(aName); AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, dt); try fLHSDataType := dt; fLHSName := AHV.Name; if fGlobals.IndexOfName(fLHSName) = -1 then AddEntry(fLHSName, dt, udType, ''); NumericFactor; if fUDTOnStack <> '' then begin Store(fLHSName); fUDTOnStack := ''; end; StoreArray(aName, idx, fLHSName); finally fArrayHelpers.ReleaseHelper(AHV); end; finally fLHSDataType := oldType; fLHSName := oldName; end; end else begin CheckIdent; CheckDataType(dt); StoreArray(aName, idx, GetDecoratedValue); Next; end; end; end else begin // since this is an assignment statement we do not allow comma operators // due to the = operator having a higher precedence than the , operator. BoolExpression; StoreArray(aName, idx, RegisterName); end; end; procedure TNXCComp.MathAssignment(const name : string); var savedtoken : char; // oldType : char; begin fProcessingMathAssignment := True; try // Look has to be '=', '+', or '-' or it's all messed up if Look = '=' then begin savedtoken := Token; Next; // move to '=' Next; // move to next token (* // 2009-06-24 JCH - to make such things as += work with scalars on the RHS // and arrays or UDTs on the left I wrapped the boolexpression in // try/finally which sets/resets the LHS data type // !!! THIS MIGHT BREAK SOMETHING !!! oldType := fLHSDataType; try fLHSDataType := TOK_LONGDEF; BoolExpression; finally fLHSDataType := oldType; end; *) // 2010-05-05 JCH - to make += work with non-scalars on the RHS I undid the // above change. Testing seems to prove that scalars on the RHS still // work correctly. BoolExpression; // end of 2010-05-05 changes case savedtoken of '+' : StoreAdd(name); '-' : StoreSub(name); '*' : StoreMul(name); '/' : StoreDiv(name); '%' : StoreMod(name); '&' : StoreAnd(name); '|' : StoreOr(name); '^' : StoreXor(name); end; end else if (Token = '+') and (Look = '+') then begin Next; // move to second + Next; // Semi; StoreInc(name, 1); end else if (Token = '-') and (Look = '-') then begin Next; // move to second - Next; // Semi; StoreDec(name, 1); end else if (Token = '+') and (Look = '-') then begin Next; // move to - if Look = '=' then begin Next; // move to '=' Next; // move to next token BoolExpression; StoreSign(name); end else AbortMsg(sInvalidAssignment); end else if (Token = '|') and (Look = '|') then begin Next; // move to second | if Look = '=' then begin Next; // move to '=' Next; // move to next token BoolExpression; StoreAbs(name); end else AbortMsg(sInvalidAssignment); end else if ((Token = '>') and (Look = '>')) or ((Token = '<') and (Look = '<')) then begin savedtoken := Token; Next; // move to second > or < if Look = '=' then begin Next; // move to '=' Next; // move to next token BoolExpression; StoreShift(savedtoken='>', name); end else AbortMsg(sInvalidAssignment); end else AbortMsg(sInvalidAssignment); finally fProcessingMathAssignment := False; end; end; procedure TNXCComp.DoLabel; var lbl : string; begin lbl := Value; Next; // the colon if not IsGlobal(lbl) then begin AddEntry(lbl, TOK_LABEL, '', ''); PostLabel(lbl); end else Duplicate(lbl); fSemiColonRequired := False; Next; end; procedure TNXCComp.DoStart; var taskname : string; begin Next; taskname := Value; CheckTask(taskname); Next; EmitLn(Format('start %s', [taskname])); end; procedure TNXCComp.DoStopTask; var taskname : string; begin Next; taskname := Value; CheckTask(taskname); Next; EmitLn(Format('stopthread %s', [taskname])); end; procedure TNXCComp.DoSetPriority; var taskname : string; begin // priority task, value Next; taskname := Value; CheckTask(taskname); Next; MatchString(TOK_COMMA); CheckNumeric; EmitLn(Format('priority %s, %s', [taskname, Value])); Next; end; {--------------------------------------------------------------} { Parse and Translate an Assignment Statement } procedure TNXCComp.Assignment; var Name: string; dt : char; begin if IncrementOrDecrement then begin DoPreIncOrDec(false); end else begin if not IsParam(Value) and not IsLocal(Value) and not IsGlobal(Value) and not IsAPIFunc(Value) and not IsAPIStrFunc(Value) then Undefined(Value); Name := Value; dt := DataType(Name); if dt = TOK_PROCEDURE then begin DoCall(Name); end else if dt = TOK_TASK then begin AbortMsg(sInvalidUseOfTaskName); SkipLine; Next; end else if dt = TOK_APIFUNC then begin Next; DoCallAPIFunc(Name); // functions should set register end else if dt = TOK_APISTRFUNC then begin Next; StringFunction(Name); // functions should set register end else begin Next; fLHSDataType := dt; fLHSName := Name; try CheckNotConstant(Name); if (Token = '[') or IsArrayType(dt) then begin ArrayAssignment(Name, dt, Token = '['); end else if dt = TOK_USERDEFINEDTYPE then begin UDTAssignment(Name); end else if Token in ['+', '-', '/', '*', '%', '&', '|', '^', '>', '<'] then begin if (Token = '+') and (Look = '=')and (dt = TOK_STRINGDEF) then StringConcatAssignment(Name) else MathAssignment(Name); end else if Token = '=' then begin MatchString('='); DoAssignValue(Name, dt); end else begin // just an identifier but not assignment operator // put it on the stack LoadVar(Name); end; finally fLHSDataType := TOK_LONGDEF; fLHSName := ''; end; end; end; end; procedure TNXCComp.DoAssignValue(const aName: string; dt: char; bNoChecks : boolean); begin if dt = TOK_STRINGDEF then begin StringExpression(aName); StoreString(aName, bNoChecks); end else begin // no comma expression here since the assignment operator has a // higher precedence than the comma operator BoolExpression; Store(aName, bNoChecks); end; end; {---------------------------------------------------------------} { Recognize and Translate an IF Construct } procedure TNXCComp.DoIf(const lend, lstart : string); var L1, L2: string; begin Next; OpenParen; CommaExpression; CloseParen; L1 := NewLabel; L2 := L1; BranchFalse(L1); Block(lend, lstart); CheckSemicolon; fSemiColonRequired := Token = TOK_ELSE; if Token = TOK_ELSE then begin Next; L2 := NewLabel; Branch(L2); PostLabel(L1); Block(lend, lstart); end; PostLabel(L2); end; {--------------------------------------------------------------} { Parse and Translate a WHILE Statement } procedure TNXCComp.DoWhile; var L1, L2: string; begin Next; OpenParen; L1 := NewLabel; L2 := NewLabel; PostLabel(L1); CommaExpression; CloseParen; BranchFalse(L2); Block(L2, L1); Branch(L1); PostLabel(L2); end; procedure TNXCComp.DoDoWhile; var L1, L2: string; begin Next; L1 := NewLabel; L2 := NewLabel; PostLabel(L1); Block(L2, L1); MatchString('while'); OpenParen; CommaExpression; CloseParen; BranchFalse(L2); Branch(L1); PostLabel(L2); end; procedure TNXCComp.DoRepeat; var L1, L2: string; svar : string; begin Next; OpenParen; L1 := NewLabel; L2 := NewLabel; CommaExpression; CloseParen; push; svar := tos; EmitLn(Format('mov %s, %s',[svar, RegisterName])); PostLabel(L1); StoreDec(svar); EmitLn('brtst LT,' + L2 + ', ' + svar); Block(L2, L1); Branch(L1); PostLabel(L2); pop; end; function StringToBool(const aValue : string) : boolean; begin Result := aValue = 'TRUE'; end; procedure TNXCComp.DoSwitch(const lstart : string); var L2 : string; idx : integer; bSwitchIsString : boolean; dt : char; begin Next; OpenParen; bSwitchIsString := ValueIsStringType(dt); if bSwitchIsString then StringExpression('') else CommaExpression; CloseParen; L2 := NewLabel; idx := SwitchFixupIndex; inc(fSwitchDepth); try ClearSwitchFixups; SwitchFixups.Add(Format('%d_Type=%s', [fSwitchDepth, IntToStr(Ord(bSwitchIsString))])); SwitchRegisterNames.Add(Format('%d=%s', [fSwitchDepth, RegisterName])); Block(L2, lstart); PostLabel(L2); FixupSwitch(idx, L2); finally dec(fSwitchDepth); end; end; function TNXCComp.GetCaseConstant: string; begin Result := ''; // collect tokens up to ':' (this allows for constant expressions) while (Token <> ':') and not endofallsource do begin Result := Result + Value; Next; end; // convert true|false to TRUE|FALSE if (Result = 'true') or (Result = 'false') then Result := UpperCase(Result); if IsLocal(Result) then Result := GetDecoratedIdent(Result); Result := CheckConstant(Result); end; procedure TNXCComp.DoSwitchCase; var L1 : string; caseval, stackval, tmp : string; begin caseval := ''; if fSwitchDepth > 0 then begin Next; // move past 'case' caseval := GetCaseConstant; MatchString(':'); // token should be ':' at this point L1 := NewLabel; PostLabel(L1); if SwitchIsString then stackval := StrBufName else stackval := SwitchRegisterName; tmp := Format('%d_Cases=%s', [fSwitchDepth, caseval]); if SwitchFixups.IndexOf(tmp) <> -1 then AbortMsg(sCaseDuplicateNotAllowed) else begin SwitchFixups.Add(tmp); SwitchFixups.Add(Format('%d=brcmp EQ, %s, %s, %s', [fSwitchDepth, L1, caseval, stackval])); end; fSemiColonRequired := False; end else AbortMsg(sCaseInvalid); end; procedure TNXCComp.DoSwitchDefault; var L1 : string; begin if fSwitchDepth > 0 then begin Next; // move past 'default' MatchString(':'); L1 := NewLabel; PostLabel(L1); SwitchFixups.Add(Format('%d=jmp %s', [fSwitchDepth, L1])); fSemiColonRequired := False; end else AbortMsg(sDefaultInvalid); end; procedure TNXCComp.ClearSwitchFixups; var i : integer; tmpType, tmpCases, tmpDepth, name : string; begin // remove all fixups with depth == fSwitchDepth tmpDepth := IntTostr(fSwitchDepth); tmpType := Format('%d_Type', [fSwitchDepth]); tmpCases := Format('%d_Cases', [fSwitchDepth]); for i := SwitchFixups.Count - 1 downto 0 do begin name := SwitchFixups.Names[i]; if (name = tmpDepth) or (name = tmpType) or (name = tmpCases) then SwitchFixups.Delete(i); end; for i := SwitchRegisterNames.Count - 1 downto 0 do begin if SwitchRegisterNames.Names[i] = tmpDepth then SwitchRegisterNames.Delete(i); end; end; function TNXCComp.SwitchIsString: Boolean; var i : integer; tmpType : string; begin Result := False; tmpType := Format('%d_Type', [fSwitchDepth]); for i := 0 to SwitchFixups.Count - 1 do begin if SwitchFixups.Names[i] = tmpType then begin Result := Boolean(StrToIntDef(SwitchFixups.ValueFromIndex[i], 0)); Break; end; end; end; function TNXCComp.SwitchRegisterName: string; var i : integer; begin Result := RegisterName; for i := 0 to SwitchRegisterNames.Count - 1 do begin if SwitchRegisterNames.Names[i] = IntToStr(fSwitchDepth) then begin Result := SwitchRegisterNames.ValueFromIndex[i]; break; end; end; end; procedure TNXCComp.FixupSwitch(idx : integer; lbl : string); var i : integer; cnt : integer; tmpDepth : string; begin // always add a jump to the end of the switch in case // there aren't any default labels in the switch tmpDepth := IntToStr(fSwitchDepth); SwitchFixups.Add(Format('%d=jmp %s', [fSwitchDepth, lbl])); cnt := 0; for i := 0 to SwitchFixups.Count - 1 do begin if SwitchFixups.Names[i] = tmpDepth then begin NBCSource.Insert(idx+cnt, SwitchFixups.ValueFromIndex[i]); inc(cnt); end; end; end; function TNXCComp.SwitchFixupIndex: integer; begin Result := NBCSource.Count; end; function TNXCComp.ReplaceTokens(const line: string) : string; begin Result := line; // line is already trimmed if Length(Result) = 0 then Exit; Result := Replace(Result, '__RETURN__', Format(#13#10'mov %s,', [SignedRegisterName])); Result := Replace(Result, '__RETURNS__', Format(#13#10'mov %s,', [SignedRegisterName])); if Pos('__RETURNU__', Result) > 0 then begin Result := Replace(Result, '__RETURNU__', Format(#13#10'mov %s,', [UnsignedRegisterName])); if StatementType <> stUnsigned then StatementType := stUnsigned; end; if Pos('__RETURNF__', Result) > 0 then begin Result := Replace(Result, '__RETURNF__', Format(#13#10'mov %s,', [FloatRegisterName])); if StatementType <> stFloat then StatementType := stFloat; end; Result := Replace(Result, '__TMPBYTE__', TempSignedByteName); Result := Replace(Result, '__TMPWORD__', TempSignedWordName); Result := Replace(Result, '__TMPLONG__', TempSignedLongName); Result := Replace(Result, '__TMPULONG__', TempUnsignedLongName); Result := Replace(Result, '__TMPFLOAT__', TempFloatName); Result := Replace(Result, '__RETVAL__', SignedRegisterName); if Pos('__FLTRETVAL__', Result) > 0 then begin Result := Replace(Result, '__FLTRETVAL__', FloatRegisterName); if StatementType <> stFloat then StatementType := stFloat; end; if Pos('__URETVAL__', Result) > 0 then begin Result := Replace(Result, '__URETVAL__', UnsignedRegisterName); if StatementType <> stUnsigned then StatementType := stUnsigned; end; Result := Replace(Result, '__STRRETVAL__', StrRetValName); Result := Replace(Result, '__STRBUFFER__', StrBufName); Result := Replace(Result, '__STRTMPBUFFER__', StrTmpBufName); Result := Replace(Result, '__GENRETVAL__', RegisterName); Result := Replace(Result, 'true', 'TRUE'); Result := Replace(Result, 'false', 'FALSE'); Result := Replace(Result, 'asminclude', '#include'); end; function TNXCComp.DecorateVariables(const asmStr: string): string; var Lex : TGenLexer; len : integer; bPartOfStruct, bPastFirstKeyword : boolean; procedure AddToResult; begin if (Lex.Id = piIdent) or (bPastFirstKeyword and (Lex.Id = piKeyWord)) then begin // is this a local variable or a parameter? if bPartOfStruct then Result := Result + Lex.Token else Result := Result + GetDecoratedIdent(Lex.Token); end else Result := Result + Lex.Token; if not bPartOfStruct then bPartOfStruct := Lex.Token = '.' else bPartOfStruct := (Lex.Token = '.') or (Lex.Id in [piIdent]); end; begin Result := ''; len := Length(asmStr); if len > 0 then begin Lex := TNBCLexer.CreateLexer; try bPartOfStruct := False; bPastFirstKeyword := False; Lex.SetStartData(@asmStr[1], len); while not Lex.AtEnd do begin AddToResult; if not bPastFirstKeyword and (Lex.Id = piKeyWord) then bPastFirstKeyword := True; Lex.Next; end; if Lex.Id <> piUnknown then AddToResult; finally Lex.Free; end; end; end; procedure TNXCComp.DoAsm(var dt : char); var asmStr : string; nestLevel : integer; begin // gather everything within asm block and output it fProcessingAsmBlock := True; try EmitPoundLine; MatchString(TOK_BEGIN); if Value <> TOK_END then begin asmStr := Value + ' ' + Look; repeat nestLevel := 0; repeat GetCharX; if Look = TOK_BEGIN then inc(nestLevel); if (Look <> TOK_END) or (nestLevel > 0) then asmStr := asmStr + Look; if Look = TOK_END then dec(nestLevel); until ((nestLevel < 0) and (Look = TOK_END)) or (Look = LF) or endofallsource; if Pos('__STRRETVAL__', asmStr) > 0 then dt := TOK_STRINGDEF else if Pos('__FLTRETVAL__', asmStr) > 0 then dt := TOK_FLOATDEF else dt := TOK_LONGDEF; asmStr := ReplaceTokens(Trim(asmStr)); asmStr := DecorateVariables(asmStr); if (asmStr <> '') or (Look <> TOK_END) then EmitAsmLines(asmStr); asmStr := ''; until (Look = TOK_END) or endofallsource; GetChar; // get the end token fSemiColonRequired := False; end; Next; finally fProcessingAsmBlock := False; end; end; {--------------------------------------------------------------} { Parse and Translate a FOR Statement } procedure TNXCComp.DoFor; var L1, L2, L3, L4: string; begin Next; OpenParen; Scan; L1 := NewLabel; L2 := NewLabel; L3 := NewLabel; L4 := NewLabel; inc(fNestingLevel); try if Token in [TOK_UNSIGNED, TOK_LONGDEF, TOK_SHORTDEF, TOK_CHARDEF, TOK_BYTEDEF, TOK_STRINGDEF, TOK_FLOATDEF] then begin DoLocals(fCurrentThreadName); end else begin if Token <> TOK_SEMICOLON then begin fNoCommaOperator := True; try Assignment; while Token = TOK_COMMA do begin Next; Assignment; end; finally fNoCommaOperator := False; end; end; Semi; end; PostLabel(L1); if Token <> TOK_SEMICOLON then CommaExpression else LoadConst('1'); Semi; BranchFalse(L2); Branch(L3); PostLabel(L4); if Token <> TOK_CLOSEPAREN then begin fNoCommaOperator := True; try Assignment; while Token = TOK_COMMA do begin Next; Assignment; end; finally fNoCommaOperator := False; end; end; CloseParen; Branch(L1); PostLabel(L3); Block(L2, L4); Branch(L4); PostLabel(L2); finally DecrementNestingLevel; end; end; function IndexOfAPICommand(const name : string) : integer; begin for Result := Low(APIList) to High(APIList) do begin if APIList[Result] = name then Exit; end; Result := -1; end; procedure TNXCComp.DoAPICommands(const lend, lstart : string); var idx : integer; begin idx := IndexOfAPICommand(Value); case idx of API_BREAK : DoBreakContinue(idx, lend); API_CONTINUE : DoBreakContinue(idx, lstart); API_RETURN : DoReturn; API_ONFWD, API_ONREV : DoOnFwdRev; API_ONFWDEX, API_ONREVEX : DoOnFwdRevEx; API_ONFWDREG, API_ONREVREG : DoOnFwdRevReg; API_ONFWDREGEX, API_ONREVREGEX : DoOnFwdRevRegEx; API_ONFWDREGPID, API_ONREVREGPID : DoOnFwdRevRegPID; API_ONFWDREGEXPID, API_ONREVREGEXPID : DoOnFwdRevRegExPID; API_OFF, API_COAST, API_FLOAT : DoStopMotors; API_OFFEX, API_COASTEX : DoStopMotorsEx; API_ONFWDSYNC, API_ONREVSYNC : DoOnFwdRevSync; API_ONFWDSYNCEX, API_ONREVSYNCEX : DoOnFwdRevSyncEx; API_ONFWDSYNCPID, API_ONREVSYNCPID : DoOnFwdRevSyncPID; API_ONFWDSYNCEXPID, API_ONREVSYNCEXPID : DoOnFwdRevSyncExPID; API_RESETTACHOCOUNT, API_RESETBLOCKTACHOCOUNT, API_RESETROTATIONCOUNT, API_RESETALLTACHOCOUNTS : DoResetCounters; API_ROTATEMOTOR, API_ROTATEMOTOREX, API_ROTATEMOTORPID, API_ROTATEMOTOREXPID : DoRotateMotors(idx); { API_SETSENSORTYPE, API_SETSENSORMODE : DoSetSensorTypeMode(idx); API_CLEARSENSOR, API_SETSENSORTOUCH, API_SETSENSORLIGHT, API_SETSENSORSOUND, API_SETSENSORLOWSPEED, API_RESETSENSOR : DoClearSetResetSensor; } API_PRECEDES, API_FOLLOWS : DoPrecedesFollows; API_ACQUIRE, API_RELEASE : DoAcquireRelease; API_EXITTO : DoExitTo; API_SETINPUT, API_SETOUTPUT : DoSetInputOutput(idx); API_STOP : DoStop; API_GOTO : DoGoto; else AbortMsg(sUnknownAPICommand); end; end; {--------------------------------------------------------------} { Parse and Translate a Single Statement } procedure TNXCComp.Statement(const lend, lstart : string); var dt : Char; begin fUDTOnStack := ''; // a UDT can't remain on the stack across a statement boundary ResetStatementType; fSemiColonRequired := True; if Token = TOK_BEGIN then Block(lend, lstart) else begin ProcessDirectives; case Token of TOK_IF: DoIf(lend, lstart); TOK_WHILE: DoWhile; TOK_FOR: DoFor; TOK_DO: DoDoWhile; TOK_REPEAT: DoRepeat; TOK_SWITCH: DoSwitch(lstart); TOK_CASE: DoSwitchCase; TOK_DEFAULT: DoSwitchDefault; TOK_START: DoStart; TOK_STOP: DoStopTask; TOK_PRIORITY: DoSetPriority; TOK_ASM: begin Next; dt := #0; DoAsm(dt); end; TOK_API: DoAPICommands(lend, lstart); TOK_IDENTIFIER: begin if Look = ':' then DoLabel else Assignment; end; TOK_HEX, TOK_NUM, '+', '-': begin CommaExpression; end; TOK_CLOSEPAREN : CloseParen; TOK_SEMICOLON : ;// do nothing TOK_END : fSemiColonRequired := False; end; EmitPoundLine; end; end; {--------------------------------------------------------------} { Parse and Translate a Block of Statements } function TNXCComp.Block(const lend, lstart : string) : boolean; begin Result := Value = TOK_BEGIN; if Result then begin Next; inc(fNestingLevel); try BlockStatements(lend, lstart); finally DecrementNestingLevel; end; MatchString(TOK_END); fSemiColonRequired := False; Scan; end else begin Scan; CommaStatement(lend, lstart); end; end; procedure TNXCComp.CheckBytesRead(const oldBytesRead: integer); begin if fBytesRead = oldBytesRead then begin AbortMsg(sParserError); SkipLine; Next; end; end; procedure TNXCComp.BlockStatements(const lend, lstart: string); var oldBytesRead : integer; begin Scan; while not (Token in [TOK_END, TOK_ELSE]) and not endofallsource do begin oldBytesRead := fBytesRead; DoLocals(fCurrentThreadName); CommaStatement(lend, lstart); CheckSemicolon; CheckBytesRead(oldBytesRead); end; end; {--------------------------------------------------------------} { Allocate Storage for a Variable } procedure TNXCComp.AllocLocal(const sub, tname : string; dt : char; bConst : boolean); var savedval : string; ival, aval, lenexpr, varName : string; bIsArray, bDone, bOpen : boolean; idx, dimensions : integer; V : TVariable; begin Next; Scan; // it is possible that the user has declared a variable using the "long int" or "short int" syntax. // we want to support that syntax. if Token = TOK_SHORTDEF then begin if dt in [TOK_LONGDEF, TOK_ULONGDEF, TOK_SHORTDEF, TOK_USHORTDEF] then Next; end; if Token <> TOK_IDENTIFIER then Expected(sVariableName); savedval := Value; ival := ''; Next; aval := ''; lenexpr := ''; bIsArray := False; if (Token = '[') {and (Look = ']') }then begin // declaring an array bDone := False; bOpen := False; while not bDone {Token in ['[', ']']} do begin lenexpr := lenexpr + Value; if Token in ['[', ']'] then aval := aval + Token; if bOpen and (Token = ']') then bOpen := False else if not bOpen and (Token = '[') then bOpen := True else if (bOpen and (Token = '[')) or (not bOpen and (Token = ']')) then AbortMsg(sInvalidArrayDeclaration); Next; if not bOpen and (Token <> '[') then bDone := True; end; dimensions := Length(aval) div 2; // number of array dimensions dt := ArrayOfType(dt, dimensions); bIsArray := True; end; if bIsArray and bConst then AbortMsg(sConstLocArrNotSupported); varName := ApplyDecoration(sub, savedval, fNestingLevel); idx := AddLocal(varName, dt, tname, bConst, lenexpr); if (Token = TOK_COMMA) or (Token = TOK_SEMICOLON) then begin if bConst then Expected(sConstInitialization); // no need to allocate if we've already emitted this name&type if fEmittedLocals.IndexOf(varName+tname) = -1 then Allocate(varName, aval, ival, tname, dt); if bIsArray and (lenexpr <> '') then InitializeArray(varName, aval, ival, tname, dt, lenexpr); end else if Token = '=' then begin // move past the '=' sign fLHSDataType := dt; fLHSName := savedval; try Next; ival := ''; if fEmittedLocals.IndexOf(varName+tname) = -1 then Allocate(varName, aval, ival, tname, dt); if bIsArray then begin ival := GetInitialValue(dt); DoLocalArrayInit(varName, ival, dt); // if not bIsArray then // DoArrayAssignValue(savedval, '', dt) end else if dt = TOK_USERDEFINEDTYPE then begin GetAndStoreUDT(savedval); end else begin DoAssignValue(savedval, dt); if fLastExpressionOptimizedToConst and (idx <> -1) then begin V := fLocals[idx]; if V.IsConstant then V.Value := fLastLoadedConst; end; end; finally fLHSDataType := TOK_LONGDEF; fLHSName := ''; end; end else Next; fEmittedLocals.Add(varName+tname); end; function TNXCComp.GetInitialValue(dt : char): string; var nestLevel, i : integer; tmpExpr : string; procedure UpdateResultWithValueForArrayTypes; begin if tmpExpr <> '' then begin if ArrayBaseType(dt) = TOK_STRINGDEF then begin Result := Result + tmpExpr + Value; tmpExpr := ''; end else begin fCalc.SilentExpression := tmpExpr; if not fCalc.ParserError then begin if ArrayBaseType(dt) = TOK_FLOATDEF then begin tmpExpr := NBCFloatToStr(fCalc.Value); end else tmpExpr := IntToStr(Trunc(fCalc.Value)) end else AbortMsg(sInvalidConstExpr); Result := Result + tmpExpr + Value; tmpExpr := ''; end; end else Result := Result + Value; end; begin Result := ''; // handle string variables differently if dt = TOK_STRINGDEF then begin if Token = TOK_IDENTIFIER then begin // try to resolve this as a constant string into a string literal i := fConstStringMap.IndexOfName(Value); if i <> -1 then begin Token := TOK_STRINGLIT; Value := fConstStringMap.ValueFromIndex[i]; end; end; Result := Value; if Token <> TOK_STRINGLIT then AbortMsg(sInvalidStringInit); Next; end else if IsArrayType(dt) or IsUDT(dt) then begin // array and struct initialization could involve nested {} pairs if Token <> TOK_BEGIN then AbortMsg(sInvalidArrayInit); nestLevel := 1; while ((Token <> TOK_END) or (nestLevel > 0)) and not endofallsource do begin if Token = TOK_BEGIN then begin tmpExpr := ''; UpdateResultWithValueForArrayTypes; end else if Token in [TOK_END, TOK_COMMA] then begin UpdateResultWithValueForArrayTypes; end else begin tmpExpr := tmpExpr + Value; end; Next; if Token = TOK_BEGIN then inc(nestLevel) else if Token = TOK_END then dec(nestLevel); end; if Token = TOK_END then begin UpdateResultWithValueForArrayTypes; Next; end else AbortMsg(sInvalidArrayInit); end else begin if dt = TOK_MUTEXDEF then AbortMsg(sInitNotAllowed); // not a string, not an array, not a mutex. Must be a scalar type or user-defined type while not (Token in [TOK_COMMA, TOK_SEMICOLON]) and not endofallsource do begin Result := Result + Value; Next; end; Result := Trim(Result); if dt in NonAggregateTypes then begin // evaluate so that constants and expressions are handled properly if Result = 'false' then Result := '0' else if Result = 'true' then Result := '1' else begin fCalc.SilentExpression := Result; if not fCalc.ParserError then begin if dt = TOK_FLOATDEF then Result := NBCFloatToStr(fCalc.Value) else Result := IntToStr(Trunc(fCalc.Value)); end else AbortMsg(sInvalidConstExpr); end; end; end; end; procedure TNXCComp.AllocGlobal(const tname : string; dt : char; bInline, bSafeCall, bConst : boolean); var savedval, ival, aval, lenexpr : string; dimensions, idx : integer; bArray : boolean; begin Next; Scan; // it is possible that the user has declared a variable using the "long int" or "short int" syntax. // we want to support that syntax. if Token = TOK_SHORTDEF then begin if dt in [TOK_LONGDEF, TOK_ULONGDEF, TOK_SHORTDEF, TOK_USHORTDEF] then begin Next; Scan; end; end; if Token <> TOK_IDENTIFIER then Expected(sVariableName); // optional initial value savedval := Value; ival := ''; Next; // it is possible that we are looking at a function declaration // rather than a variable declaration. if Token = TOK_OPENPAREN then begin FunctionBlock(savedval, tname, dt, bInline, bSafeCall); fSemiColonRequired := False; end else begin fSemiColonRequired := True; CheckDup(savedval); if bInline then AbortMsg(sInlineInvalid); if bSafeCall then AbortMsg(sSafeCallInvalid); aval := ''; lenexpr := ''; bArray := False; dimensions := 0; if Token = '[' then begin aval := ProcessArrayDimensions(lenexpr); dimensions := Length(aval) div 2; // number of array dimensions dt := ArrayOfType(dt, dimensions); bArray := True; end; AddEntry(savedval, dt, tname, lenexpr, bConst); if (Token = TOK_COMMA) or (Token = TOK_SEMICOLON) then begin if bConst then Expected(sConstInitialization); Allocate(savedval, aval, ival, tname, dt); end else if Token = '=' then begin if bArray and (ArrayBaseType(dt) = TOK_STRINGDEF) then inc(dimensions); // move past the '=' sign Next; ival := GetInitialValue(dt); // lookup global and set its value idx := fGlobals.IndexOfName(savedval); if idx <> -1 then begin // do not set the value for 1 dimensional arrays since the initial // values can be set statically if dimensions <> 1 then fGlobals[idx].Value := ival; end; // the value must be a numeric constant expression if the type // is an integer type if bConst then begin if dt in NonAggregateTypes then begin if dt = TOK_FLOATDEF then fCalc.SetVariable(savedval, NBCStrToFloatDef(ival, 0)) else fCalc.SetVariable(savedval, StrToInt64Def(ival, 0)); end else if dt = TOK_STRINGDEF then begin // string constants - use a variable name to value map (string list) fConstStringMap.Add(savedval+'='+ival); end; // it is now okay to have const struct types since you can initialize them // else if not bArray then // AbortMsg(sInvalidConstExpr); end; // arrays with > 1 dimension cannot be initialized statically if dimensions > 1 then ival := ''; Allocate(savedval, aval, ival, tname, dt); end else Next; end; end; function TNXCComp.GetVariableType(vt : char; bUnsigned : boolean) : char; begin if not bUnsigned then Result := vt else case vt of TOK_LONGDEF : Result := TOK_ULONGDEF; TOK_SHORTDEF : Result := TOK_USHORTDEF; TOK_CHARDEF : Result := TOK_BYTEDEF; else if vt = TOK_FLOATDEF then AbortMsg(sNoUnsignedFloat); Result := vt; end; end; {--------------------------------------------------------------} { Parse and Translate Global Declarations } procedure TNXCComp.TopDecls; var vt : char; bUnsigned, bInline, bSafeCall, bConst : boolean; oldBytesRead : Integer; dt : char; tname : string; begin DoCompilerStatusChange(sNXCProcessGlobals); bUnsigned := False; bInline := False; bSafeCall := False; bConst := False; Scan; if Token = TOK_IDENTIFIER then CheckForTypedef(bUnsigned, bConst, bInline, bSafeCall); while not (Token in [TOK_TASK, TOK_PROCEDURE]) and not endofallsource do begin oldBytesRead := fBytesRead; case Token of TOK_ASM: begin Next; dt := #0; DoAsm(dt); Scan; end; TOK_DIRECTIVE : begin ProcessDirectives; Scan; end; TOK_CONST : begin Next; Scan; bConst := True; end; TOK_UNSIGNED : begin Next; Scan; bUnsigned := True; end; TOK_INLINE : begin Next; Scan; bInline := True; end; TOK_SAFECALL : begin Next; Scan; bSafeCall := True; end; TOK_TYPEDEF : begin ProcessTypedef; end; TOK_ENUM: begin ProcessEnum(true); end; TOK_STRUCT : begin ProcessStruct(False); end; TOK_USERDEFINEDTYPE, TOK_LONGDEF, TOK_SHORTDEF, TOK_CHARDEF, TOK_BYTEDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF : begin tname := Value; vt := Token; AllocGlobal(tname, GetVariableType(vt, bUnsigned), bInline, bSafeCall, bConst); while Token = TOK_COMMA do AllocGlobal(tname, GetVariableType(vt, bUnsigned), bInline, bSafeCall, bConst); CheckSemicolon; bUnsigned := False; bInline := False; bSafeCall := False; bConst := False; end; else // nothing here right now Semi; Scan; end; if Token = TOK_IDENTIFIER then CheckForTypedef(bUnsigned, bConst, bInline, bSafeCall); CheckBytesRead(oldBytesRead); end; if bInLine then IncrementInlineDepth; // fInlining := bInLine; fSafeCalling := bSafeCall; end; function TNXCComp.AddLocal(name : string; dt : char; const tname : string; bConst : boolean; const lenexp : string) : integer; var l, IL : TVariable; bAmInlining : boolean; // bIsParam, bIsLocal : boolean; begin CheckForValidDataType(dt); Result := -1; bAmInlining := AmInlining; // bIsLocal := IsLocal(name); // bIsParam := IsParam(name); // // if we are inlining then only check IsLocal // if (bAmInlining and bIsLocal) or // ((not bAmInlining) and (bIsLocal or bIsParam)) then if IsParam(name) or IsLocal(name) then Duplicate(name) else begin l := fLocals.Add; l.Name := name; l.DataType := dt; l.IsConstant := bConst; l.TypeName := tname; l.LenExpr := lenexp; l.Level := fNestingLevel; if bAmInlining and Assigned(fCurrentInlineFunction) then begin IL := fCurrentInlineFunction.LocalVariables.Add; IL.Assign(l); end; Result := l.Index; end; end; procedure TNXCComp.DoLocals(const sub : string); var bIsUnsigned, bIsConst, bDummy : boolean; dt : char; tname : string; begin fNoCommaOperator := True; try bIsUnsigned := False; bIsConst := False; bDummy := False; Scan; if Token = TOK_IDENTIFIER then CheckForTypedef(bIsUnsigned, bIsConst, bDummy, bDummy); while (Token in [TOK_DIRECTIVE, TOK_UNSIGNED, TOK_CONST, TOK_TYPEDEF, TOK_STRUCT, TOK_ENUM, TOK_USERDEFINEDTYPE, TOK_LONGDEF, TOK_SHORTDEF, TOK_CHARDEF, TOK_BYTEDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF]) and not endofallsource do begin case Token of TOK_DIRECTIVE : begin ProcessDirectives; Scan; end; TOK_CONST : begin Next; Scan; bIsConst := True; end; TOK_UNSIGNED : begin Next; Scan; bIsUnsigned := True; end; TOK_TYPEDEF : begin ProcessTypedef; end; TOK_ENUM : begin ProcessEnum(False); end; TOK_STRUCT : begin ProcessStruct(False); end; TOK_USERDEFINEDTYPE, TOK_LONGDEF, TOK_SHORTDEF, TOK_CHARDEF, TOK_BYTEDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF : begin tname := Value; dt := Token; AllocLocal(sub, tname, GetVariableType(dt, bIsUnsigned), bIsConst); while Token = TOK_COMMA do AllocLocal(sub, tname, GetVariableType(dt, bIsUnsigned), bIsConst); Semi; Scan; bIsUnsigned := False; bIsConst := False; end; else Expected(sValidProgBlock); end; if Token = TOK_IDENTIFIER then CheckForTypedef(bIsUnsigned, bIsConst, bDummy, bDummy); end; finally fNoCommaOperator := False; end; end; const HASPROTO = 2; HASNOPROTO = 3; function TNXCComp.FormalList(protoexists : boolean; var procname : string) : integer; var protocount : integer; pltype : integer; pcount : integer; ptype : char; varnam : string; bIsUnsigned, bIsArray, bIsConst, bIsRef, bError : boolean; bHasDefault, bRequireDefaults : boolean; aval, tname, defValue : string; dimensions : integer; oldBytesRead : integer; procedure CheckParam1; begin AbortMsg(sBadPrototype); bError := True; if protocount >= MAXPARAMS then AbortMsg(sMaxParamCountExceeded); inc(protocount); end; procedure CheckParamHasProto; begin if not protoexists then begin Expected(sDataType); bError := True; end; if pcount >= MAXPARAMS then begin AbortMsg(sMaxParamCountExceeded); bError := True; end; if not bError then begin AddParam(ApplyDecoration(procname, varnam, 0), FunctionParameterType(procname, pcount), FunctionParameterTypeName(procname, pcount), FunctionParameterIsConstant(procname, pcount), FunctionParameterHasDefault(procname, pcount), FunctionParameterDefaultValue(procname, pcount)); inc(pcount); if pcount > protocount then begin AbortMsg(sTooManyArgs); bError := True; end; end; end; procedure CheckParamHasNoProto; var fpDT : char; fpType : string; fpIsConst : boolean; begin if pcount >= MAXPARAMS then begin AbortMsg(sMaxParamCountExceeded); bError := True; end; if protoexists and not bError and (pcount >= protocount) then begin AbortMsg(sTooManyArgs); bError := True; end; if protoexists and not bError then begin // compare known type to specified type fpDT := FunctionParameterType(procname, pcount); fpType := FunctionParameterTypeName(procname, pcount); fpIsConst := FunctionParameterIsConstant(procname, pcount); if (fpDT <> ptype) or (fpType <> tname) or (fpIsConst <> bIsConst) then begin AbortMsg(sFuncParamDeclMismatch); bError := True; end; end; if not bError then begin AddParam(ApplyDecoration(procname, varnam, 0), ptype, tname, bIsConst, bHasDefault, defValue); if not protoexists then begin Allocate(ApplyDecoration(procname, varnam, 0), aval, '', tname, ptype); AddFunctionParameter(procname, varnam, tname, pcount, ptype, bIsConst, bIsRef, bIsArray, dimensions, bHasDefault, defValue); inc(protocount); end; inc(pcount); end; end; procedure CheckPLType; begin case pltype of 1 : CheckParam1; HASPROTO : CheckParamHasProto; HASNOPROTO : CheckParamHasNoProto; end; end; procedure ProcessTypes(const bFirstParam : boolean); var bInline, bSafeCall : boolean; begin bIsUnsigned := False; bIsArray := False; bIsConst := False; bIsRef := False; ptype := #0; if Token = TOK_CONST then begin bIsConst := True; Next; Scan; if bFirstParam then pltype := 1; end; // new code starts here tname := Value; if Token = TOK_UNSIGNED then begin bIsUnsigned := True; Next; Scan; if bFirstParam then pltype := 1; tname := tname + ' ' + Value; end; Value := tname; CheckForTypedef(bIsUnsigned, bIsConst, bInline, bSafeCall); // re-assign type name variable in case CheckForTypedef changed it. tname := Value; ptype := Token; if bFirstParam then pltype := 1; Next; Scan; if (Token <> '[') and (Token <> TOK_COMMA) and (Token <> TOK_CLOSEPAREN) and (Token <> '&') and (Token <> TOK_IDENTIFIER) then begin AbortMsg(sUnexpectedChar); bError := True; end; (* if Token = TOK_UNSIGNED then begin bIsUnsigned := True; Next; Scan; if bFirstParam then pltype := 1; end; if Token in [TOK_CHARDEF, TOK_BYTEDEF, TOK_SHORTDEF, TOK_LONGDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF, TOK_USERDEFINEDTYPE, TOK_STRINGLIT] then begin ptype := Token; tname := Value; if bFirstParam then pltype := 1; Next; Scan; if (Token <> '[') and (Token <> TOK_COMMA) and (Token <> TOK_CLOSEPAREN) and (Token <> '&') and (Token <> TOK_IDENTIFIER) then begin AbortMsg(sUnexpectedChar); bError := True; end; end else if bIsUnsigned then begin AbortMsg(sMissingDataType); bError := True; end; *) if Token = '&' then begin bIsRef := True; Next; Scan; end; end; procedure CheckParamTypeAndArrays; begin if pltype = HASNOPROTO then begin ptype := GetVariableType(ptype, bIsUnsigned); if ptype = #0 then bError := True; CheckForValidDataType(ptype); if not bError then begin aval := ''; dimensions := 0; if (Token = '[') and (Look = ']') then begin // declaring an array while Token in ['[', ']'] do begin aval := aval + Token; Next; end; bIsArray := True; dimensions := Length(aval) div 2; // number of array dimensions ptype := ArrayOfType(ptype, dimensions); end; end; end; end; procedure CheckForDefaultArgumentValue; begin bHasDefault := False; defValue := ''; // check for optional equal sign if Token = '=' then begin bHasDefault := True; Next; defValue := Value; if defValue = '-' then begin Next; defValue := defValue + Value; end; Next; end; if bRequireDefaults and not bHasDefault then begin AbortMsg(sDefaultParamError); bError := True; end; if bHasDefault then bRequireDefaults := True; end; begin bRequireDefaults := False; dimensions := 0; protocount := 0; pcount := 0; pltype := 0; if protoexists then protocount := FunctionParameterCount(procname); bError := False; while (Token <> TOK_CLOSEPAREN) and not endofallsource do begin oldBytesRead := fBytesRead; if bError then Break; Scan; // handle void all by itself if Token = TOK_PROCEDURE then begin Next; Scan; Continue; end; ProcessTypes(true); if Token = TOK_IDENTIFIER then begin varnam := Value; Next; Scan; if pltype = 1 then pltype := HASNOPROTO else pltype := HASPROTO; end; CheckParamTypeAndArrays; // check for optional = and default value CheckForDefaultArgumentValue; if bError then Continue; CheckPLType; // process remaining parameters while (Token = TOK_COMMA) and not endofallsource do begin if bError then Break; Next; Scan; if (pltype = 1) or (pltype = HASNOPROTO) then ProcessTypes(false); if (pltype = HASPROTO) or (pltype = HASNOPROTO) then begin if Token = TOK_IDENTIFIER then begin varnam := Value; Next; Scan; end else begin Expected(sVariableName); bError := True; end; end; CheckParamTypeAndArrays; // check for optional = and default value CheckForDefaultArgumentValue; if bError then Continue; CheckPLType; end; // while Token = TOK_COMMA CheckBytesRead(oldBytesRead); end; // while Token <> TOK_CLOSEPAREN if protoexists and (pcount < protocount) then AbortMsg(sTooFewArgs); if bError then while (Token <> TOK_CLOSEPAREN) and not endofallsource do Next; // eat tokens up to TOK_CLOSEPAREN Result := pltype; end; procedure TNXCComp.ProcedureBlock; var Name : string; protoexists, bIsSub : boolean; savedToken : char; begin while Token in [TOK_INLINE, TOK_SAFECALL, TOK_PROCEDURE, TOK_TASK] do begin if Token = TOK_INLINE then begin Next; IncrementInlineDepth; end; if Token = TOK_SAFECALL then begin Next; fSafeCalling := True; end; bIsSub := Token = TOK_PROCEDURE; if AmInlining and not bIsSub then AbortMsg(sInlineInvalid); if fSafeCalling and not bIsSub then AbortMsg(sSafeCallInvalid); savedToken := Token; Next; Scan; CheckIdent; Name := Value; DoCompilerStatusChange(Format(sNXCProcedure, [Name])); if bIsSub and (Name = 'main') then AbortMsg(sMainMustBeTask); protoexists := False; Next; DoCommonFuncProcDecl(protoexists, Name, '', savedToken, #0, AmInlining, fSafeCalling); if Token = TOK_BEGIN then begin Prolog(Name, bIsSub); MatchString(TOK_BEGIN); if Name = 'main' then begin InitializeGlobalArrays; InitializeGraphicOutVars; end; ClearLocals; fNestingLevel := 0; DoLocals(Name); BlockStatements(); Epilog(bIsSub); // MatchString(TOK_END) must be after the epilog or process directives // can be called while still inlining MatchString(TOK_END); Scan; end else begin if protoexists then Expected(sProtoAlreadyDefined); Scan; end; ClearParams; // DecrementInlineDepth; // fInlining := False; fSafeCalling := False; TopDecls; end; end; procedure TNXCComp.DoCommonFuncProcDecl(var bProtoExists : boolean; var Name : string; const tname : string; const tok, dt: char; bInline, bSafeCall : boolean); var procexists : integer; pltype : integer; bIsSub : boolean; begin bIsSub := tok = TOK_PROCEDURE; // TODO: move this code after the processing of the formal list of parameters // so that we can decorate the function name before checking for duplicates procexists := GlobalIdx(Name); if procexists <> 0 then begin if not (GS_Type[procexists] in [TOK_PROCEDURE, TOK_TASK]) then Duplicate(Name); if GS_Size[procexists] = 0 then bProtoExists := True else Duplicate(Name); end else begin // define a mutex for this function if safecall if bIsSub and (SafeCalls or bSafeCall) then EmitMutexDeclaration(Name); AddEntry(Name, tok, tname, '', False, bSafeCall); GS_ReturnType[NumGlobals] := dt; if (dt <> #0) and (IsArrayType(dt) or IsUDT(dt)) then AddEntry(Format('__result_%s', [Name]), dt, tname, ''); end; OpenParen; if bIsSub then pltype := FormalList(bProtoExists, Name) else begin pltype := 0; // allow for the possibility that tasks have (void) args if Value = 'void' then Next; end; CloseParen; fCurrentThreadName := Name; fThreadNames.Add(Name); // allow for "stuff" after the close parenthesis and before either ; or { Scan; ProcessDirectives; // just in case there are any in between the ) and the { // now it has to either be a ; or a { if not (Token in [TOK_SEMICOLON, TOK_BEGIN]) then AbortMsg(sInvalidFuncDecl); if Token = TOK_SEMICOLON then begin // this is a function declaration (a prototype) - not a function definition pltype := 1; Next; end; if Token = TOK_BEGIN then begin if pltype = 1 then AbortMsg(sNotValidForPrototype); if bProtoExists then GS_Size[procexists] := 1 else GS_Size[NumGlobals] := 1; end; end; procedure TNXCComp.FunctionBlock(Name, tname : string; dt: char; bInline, bSafeCall : boolean); var protoexists : boolean; begin DoCompilerStatusChange(Format(sNXCFunction, [Name])); if bInline then IncrementInlineDepth; if Name = 'main' then AbortMsg(sMainMustBeTask); protoexists := False; DoCommonFuncProcDecl(protoexists, Name, tname, TOK_PROCEDURE, dt, bInline, bSafeCall); if Token = TOK_BEGIN then begin Prolog(Name, True); MatchString(TOK_BEGIN); ClearLocals; fNestingLevel := 0; DoLocals(Name); BlockStatements(); Epilog(True); // MatchString(TOK_END) must be after the epilog or process directives // can be called while still inlining MatchString(TOK_END); Scan; end else begin if protoexists then Expected(sProtoAlreadyDefined); Scan; end; ClearParams; end; {--------------------------------------------------------------} { Initialize } procedure TNXCComp.Init; begin fNoCommaOperator := False; fProcessingMathAssignment := False; fInlineDepth := 0; fLastExpressionOptimizedToConst := False; fLastLoadedConst := ''; fCurrentLine := ''; totallines := 1; linenumber := 1; ClearParams; fStackDepth := 0; MaxStackDepth := 0; GetChar; Next; end; {--------------------------------------------------------------} { Parse and Translate a Program } procedure TNXCComp.Prog; begin Header; TopDecls; if Token in [TOK_INLINE, TOK_SAFECALL, TOK_PROCEDURE, TOK_TASK] then ProcedureBlock; Trailer; end; { TNXCComp } constructor TNXCComp.Create; begin inherited Create; fMaxPreprocDepth := 10; fMaxErrors := 0; NumGlobals := 0; endofallsource := False; fEnhancedFirmware := False; fFirmwareVersion := 128; // 1.28 NXT 2.0 firmware fIgnoreSystemFile := False; fWarningsOff := False; fDD := TDataDefs.Create; fNamedTypes := TMapList.Create; fNamedTypes.CaseSensitive := True; fNamedTypes.Duplicates := dupError; fDefines := TStringList.Create; fEmittedLocals := TStringList.Create; fEmittedLocals.CaseSensitive := True; fEmittedLocals.Sorted := True; fLocals := TVariableList.Create; fParams := TVariableList.Create; fGlobals := TVariableList.Create; fFuncParams := TFunctionParameters.Create; fInlineFunctionStack := TObjectStack.Create; fInlineFunctions := TInlineFunctions.Create; fArrayHelpers := TArrayHelperVars.Create; fTmpAsmLines := TStringList.Create; fStackVarNames := TStringList.Create; fNBCSrc := TStringList.Create; fMS := TMemoryStream.Create; fMessages := TStringList.Create; fIncludeDirs := TStringList.Create; fAPIFunctions := TStringList.Create; fAPIFunctions.CaseSensitive := True; fAPIFunctions.Sorted := True; fAPIStrFunctions := TStringList.Create; fAPIStrFunctions.CaseSensitive := True; fAPIStrFunctions.Sorted := True; fThreadNames := TStringList.Create; fThreadNames.CaseSensitive := True; fThreadNames.Sorted := True; fThreadNames.Duplicates := dupIgnore; fSwitchFixups := TStringList.Create; fSwitchRegNames := TStringList.Create; fSwitchDepth := 0; fFunctionNameCallStack := TStringList.Create; fFunctionNameCallStack.CaseSensitive := True; fConstStringMap := TStringList.Create; fConstStringMap.CaseSensitive := True; fConstStringMap.Sorted := True; fArrayIndexStack := TStringList.Create; fStructDecls := TStringList.Create; fInlineStack := TObjectList.Create(false); fCalc := TNBCExpParser.Create(nil); fCalc.PascalNumberformat := False; fCalc.CaseSensitive := True; fCalc.StandardDefines := True; fCalc.ExtraDefines := True; LoadAPIFunctions; fOptimizeLevel := 0; Clear; end; destructor TNXCComp.Destroy; begin FreeAndNil(fDD); FreeAndNil(fNamedTypes); FreeAndNil(fDefines); FreeAndNil(fEmittedLocals); FreeAndNil(fLocals); FreeAndNil(fParams); FreeAndNil(fGlobals); FreeAndNil(fFuncParams); FreeAndNil(fInlineFunctionStack); FreeAndNil(fInlineFunctions); FreeAndNil(fArrayHelpers); FreeAndNil(fTmpAsmLines); FreeAndNil(fStackVarNames); FreeAndNil(fNBCSrc); FreeAndNil(fMS); FreeAndNil(fMessages); FreeAndNil(fIncludeDirs); FreeAndNil(fAPIFunctions); FreeAndNil(fAPIStrFunctions); FreeAndNil(fFunctionNameCallStack); FreeAndNil(fConstStringMap); FreeAndNil(fArrayIndexStack); FreeAndNil(fStructDecls); FreeAndNil(fThreadNames); // FreeAndNil(fParamNames); FreeAndNil(fSwitchFixups); FreeAndNil(fSwitchRegNames); FreeAndNil(fInlineStack); FreeAndNil(fCalc); inherited; end; procedure TNXCComp.InternalParseStream; begin try DoCompilerStatusChange(sNXCCompBegin); DoCompilerStatusChange(Format(sCompileTargets, [FirmwareVersion, BoolToString(EnhancedFirmware)])); fFuncParams.Clear; fThreadNames.Clear; fConstStringMap.Clear; fGlobals.Clear; fBadProgram := False; fBytesRead := 0; fProgErrorCount := 0; fLastErrLine := -99; fLastErrMsg := ''; fLHSDataType := #0; fLHSName := ''; DoCompilerStatusChange(sNXCPreprocess); PreProcess; fMS.Position := 0; fParenDepth := 0; DoCompilerStatusChange(sNXCInitProgram); Init; DoCompilerStatusChange(sNXCParseProg); Prog; DoCompilerStatusChange(sNXCCodeGenComplete); except on E : EAbort do begin fBadProgram := True; // end processing file due to Abort in ReportProblem end; on E : EPreprocessorException do begin fBadProgram := True; ReportProblem(E.LineNo, CurrentFile, E.Message, true); end; on E : Exception do begin fBadProgram := True; ReportProblem(linenumber, CurrentFile, E.Message, true); end; end; end; procedure TNXCComp.Parse(aStrings: TStrings); begin Clear; if not IgnoreSystemFile then LoadSystemFile(fMS); aStrings.SaveToStream(fMS); InternalParseStream; end; procedure TNXCComp.Parse(aStream: TStream); begin Clear; if not IgnoreSystemFile then LoadSystemFile(fMS); fMS.CopyFrom(aStream, 0); InternalParseStream; end; procedure TNXCComp.Parse(const aFilename: string); var Stream : TFileStream; begin Clear; if not IgnoreSystemFile then LoadSystemFile(fMS); Stream := TFileStream.Create(aFilename, fmOpenRead or fmShareDenyWrite); try fMS.CopyFrom(Stream, 0); finally Stream.Free; end; InternalParseStream; end; procedure TNXCComp.Clear; begin fMS.Clear; NBCSource.Clear; fInlineFunctions.Clear; fArrayHelpers.Clear; fStructDecls.Clear; fMessages.Clear; fTempChar := ' '; fLHSDataType := #0; fLHSName := ''; LCount := 0; ClearLocals; ClearParams; ClearGlobals; end; {--------------------------------------------------------------} { Recognize and Translate a break/continue } procedure TNXCComp.DoBreakContinue(idx : integer; const lbl: string); var val : string; begin val := APIList[idx]; MatchString(val); // Semi; if lbl <> '' then Branch(lbl) else AbortMsg(Format(sInvalidBreakContinue, [val])); end; procedure TNXCComp.DoOnFwdRev; var op, arg1 : string; begin //OnFwd(ports, pwr) //OnRev(ports, pwr) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s)',[op, arg1, RegisterName])); end; procedure TNXCComp.DoOnFwdRevEx; var op, arg1, arg3 : string; begin //OnFwdEx(ports, pwr, reset) //OnRevEx(ports, pwr, reset) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; MatchString(TOK_COMMA); // reset CheckNumeric; arg3 := Value; Next; CloseParen; EmitLn(Format('%s(%s, %s, %s)',[op, arg1, RegisterName, arg3])); end; procedure TNXCComp.DoOnFwdRevReg; var op, arg1, svar : string; begin //OnFwdReg(ports, pwr, regmode) //OnRevReg(ports, pwr, regmode) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; svar := tos; EmitLn(Format('mov %s, %s',[svar, RegisterName])); MatchString(TOK_COMMA); // regmode BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s)',[op, arg1, svar, RegisterName])); pop; end; procedure TNXCComp.DoOnFwdRevRegEx; var op, arg1, svar, arg4 : string; begin //OnFwdRegEx(ports, pwr, regmode, reset) //OnRevRegEx(ports, pwr, regmode, reset) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; svar := tos; EmitLn(Format('mov %s, %s',[svar, RegisterName])); MatchString(TOK_COMMA); // regmode BoolExpression; MatchString(TOK_COMMA); // reset CheckNumeric; arg4 := Value; Next; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s)',[op, arg1, svar, RegisterName, arg4])); pop; end; procedure TNXCComp.DoOnFwdRevSync; var op, ports, pwr : string; begin //OnFwdSync(ports, pwr, turnpct) //OnRevSync(ports, pwr, turnpct) op := Value; Next; OpenParen; // ports ports := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; pwr := tos; EmitLn(Format('mov %s, %s',[pwr, RegisterName])); MatchString(TOK_COMMA); // turnpct BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s)',[op, ports, pwr, RegisterName])); pop; end; procedure TNXCComp.DoOnFwdRevSyncEx; var op, ports, pwr, arg4 : string; begin //OnFwdSyncEx(ports, pwr, turnpct, reset) //OnRevSyncEx(ports, pwr, turnpct, reset) op := Value; Next; OpenParen; // ports ports := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; pwr := tos; EmitLn(Format('mov %s, %s',[pwr, RegisterName])); MatchString(TOK_COMMA); // turnpct BoolExpression; MatchString(TOK_COMMA); // reset CheckNumeric; arg4 := Value; Next; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s)',[op, ports, pwr, RegisterName, arg4])); pop; end; procedure TNXCComp.DoOnFwdRevRegPID; var op, arg1, svar, regvar, pvar, ivar : string; begin //OnFwdRegPID(ports, pwr, regmode, p, i, d) //OnRevRegPID(ports, pwr, regmode, p, i, d) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; svar := tos; EmitLn(Format('mov %s, %s',[svar, RegisterName])); MatchString(TOK_COMMA); // regmode BoolExpression; push; regvar := tos; EmitLn(Format('mov %s, %s',[regvar, RegisterName])); MatchString(TOK_COMMA); // p BoolExpression; push; pvar := tos; EmitLn(Format('mov %s, %s',[pvar, RegisterName])); MatchString(TOK_COMMA); // i BoolExpression; push; ivar := tos; EmitLn(Format('mov %s, %s',[ivar, RegisterName])); MatchString(TOK_COMMA); // d BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s)',[op, arg1, svar, regvar, pvar, ivar, RegisterName])); pop; pop; pop; pop; end; procedure TNXCComp.DoOnFwdRevRegExPID; var op, arg1, svar, arg4, regvar, pvar, ivar : string; begin //OnFwdRegExPID(ports, pwr, regmode, reset, p, i, d) //OnRevRegExPID(ports, pwr, regmode, reset, p, i, d) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; svar := tos; EmitLn(Format('mov %s, %s',[svar, RegisterName])); MatchString(TOK_COMMA); // regmode BoolExpression; push; regvar := tos; EmitLn(Format('mov %s, %s',[regvar, RegisterName])); MatchString(TOK_COMMA); // reset CheckNumeric; arg4 := Value; MatchString(TOK_COMMA); // p BoolExpression; push; pvar := tos; EmitLn(Format('mov %s, %s',[pvar, RegisterName])); MatchString(TOK_COMMA); // i BoolExpression; push; ivar := tos; EmitLn(Format('mov %s, %s',[ivar, RegisterName])); MatchString(TOK_COMMA); // d BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s, %s)',[op, arg1, svar, regvar, arg4, pvar, ivar, RegisterName])); pop; pop; pop; pop; end; procedure TNXCComp.DoOnFwdRevSyncPID; var op, ports, pwr, turnvar, pvar, ivar : string; begin //OnFwdSyncPID(ports, pwr, turnpct, p, i, d) //OnRevSyncPID(ports, pwr, turnpct, p, i, d) op := Value; Next; OpenParen; // ports ports := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; pwr := tos; EmitLn(Format('mov %s, %s',[pwr, RegisterName])); MatchString(TOK_COMMA); // turnpct BoolExpression; push; turnvar := tos; EmitLn(Format('mov %s, %s',[turnvar, RegisterName])); MatchString(TOK_COMMA); // p BoolExpression; push; pvar := tos; EmitLn(Format('mov %s, %s',[pvar, RegisterName])); MatchString(TOK_COMMA); // i BoolExpression; push; ivar := tos; EmitLn(Format('mov %s, %s',[ivar, RegisterName])); MatchString(TOK_COMMA); // d BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s)',[op, ports, pwr, turnvar, pvar, ivar, RegisterName])); pop; pop; pop; pop; end; procedure TNXCComp.DoOnFwdRevSyncExPID; var op, ports, pwr, arg4, turnvar, pvar, ivar : string; begin //OnFwdSyncExPID(ports, pwr, turnpct, reset, p, i, d) //OnRevSyncExPID(ports, pwr, turnpct, reset, p, i, d) op := Value; Next; OpenParen; // ports ports := GetDecoratedValue; Next; MatchString(TOK_COMMA); // pwr BoolExpression; push; pwr := tos; EmitLn(Format('mov %s, %s',[pwr, RegisterName])); MatchString(TOK_COMMA); // turnpct BoolExpression; push; turnvar := tos; EmitLn(Format('mov %s, %s',[turnvar, RegisterName])); MatchString(TOK_COMMA); // reset CheckNumeric; arg4 := Value; MatchString(TOK_COMMA); // p BoolExpression; push; pvar := tos; EmitLn(Format('mov %s, %s',[pvar, RegisterName])); MatchString(TOK_COMMA); // i BoolExpression; push; ivar := tos; EmitLn(Format('mov %s, %s',[ivar, RegisterName])); MatchString(TOK_COMMA); // d BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s, %s)',[op, ports, pwr, turnvar, arg4, pvar, ivar, RegisterName])); pop; pop; pop; pop; end; procedure TNXCComp.DoRotateMotors(idx: integer); var op, ports, pwr, angle, turnpct, bsync, bstop, p, i : string; begin //RotateMotor(ports, pwr, angle) //RotateMotorEx(ports, pwr, angle, turnpct, bSync, bStop) //RotateMotorPID(ports, pwr, angle, p, i, d) //RotateMotorExPID(ports, pwr, angle, turnpct, bSync, bStop, p, i, d) op := Value; Next; OpenParen; // ports ports := GetDecoratedValue; Next; MatchString(TOK_COMMA); // power BoolExpression; push; pwr := tos; EmitLn(Format('mov %s, %s',[pwr, RegisterName])); MatchString(TOK_COMMA); // angle BoolExpression; if idx = API_ROTATEMOTOR then begin // RotateMotor CloseParen; EmitLn(Format('%s(%s, %s, %s)', [op, ports, pwr, RegisterName])) end else if idx = API_ROTATEMOTORPID then begin // RotateMotorPID push; angle := tos; EmitLn(Format('mov %s, %s',[angle, RegisterName])); MatchString(TOK_COMMA); // P BoolExpression; push; p := tos; EmitLn(Format('mov %s, %s',[p, RegisterName])); MatchString(TOK_COMMA); // I BoolExpression; push; i := tos; EmitLn(Format('mov %s, %s',[i, RegisterName])); MatchString(TOK_COMMA); // D BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s)', [op, ports, pwr, angle, p, i, RegisterName])); pop; pop; pop; end else begin // RotateMotorEx or RotateMotorExPID push; angle := tos; EmitLn(Format('mov %s, %s',[angle, RegisterName])); MatchString(TOK_COMMA); // turn pct BoolExpression; push; turnpct := tos; EmitLn(Format('mov %s, %s',[turnpct, RegisterName])); MatchString(TOK_COMMA); // bsync BoolExpression; push; bsync := tos; EmitLn(Format('mov %s, %s',[bsync, RegisterName])); MatchString(TOK_COMMA); // bStop BoolExpression; if idx = API_ROTATEMOTOREX then begin CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s)', [op, ports, pwr, angle, turnpct, bsync, RegisterName])); end else begin // RotateMotorExPID push; bstop := tos; EmitLn(Format('mov %s, %s',[bstop, RegisterName])); MatchString(TOK_COMMA); // P BoolExpression; push; p := tos; EmitLn(Format('mov %s, %s',[p, RegisterName])); MatchString(TOK_COMMA); // I BoolExpression; push; i := tos; EmitLn(Format('mov %s, %s',[i, RegisterName])); MatchString(TOK_COMMA); // D BoolExpression; CloseParen; EmitLn(Format('%s(%s, %s, %s, %s, %s, %s, %s, %s, %s)', [op, ports, pwr, angle, turnpct, bsync, bstop, p, i, RegisterName])); pop; pop; pop; end; pop; pop; pop; end; pop; end; procedure TNXCComp.DoAcquireRelease; var op, val : string; begin // Acquire(mutex); // Release(mutex); op := LowerCase(Value); Next; OpenParen; // mutex val := GetDecoratedValue; CheckIdent; CheckGlobal(val); // mutex must be a global variable if DataType(val) <> TOK_MUTEXDEF then Expected(sMutexType); Next; CloseParen; EmitLn(op + ' ' + val); end; procedure TNXCComp.DoPrecedesFollows; var op, val : string; begin // Precedes(x, y, z, ...); // Follows(x, y, z); op := LowerCase(Value); Next; OpenParen; val := Value; CheckIdent; CheckGlobal(val); // task names must be global if DataType(val) <> TOK_TASK then Expected(sTaskName); Next; while Value = TOK_COMMA do begin val := val + Value; // the comma Next; CheckIdent; CheckGlobal(Value); val := val + ' ' + Value; // the next value Next; end; CloseParen; EmitLn(op + ' ' + val); end; procedure TNXCComp.DoExitTo; var op, val : string; begin // ExitTo(task); op := LowerCase(Value); Next; OpenParen; // task val := Value; CheckIdent; CheckGlobal(val); // must be global name if DataType(val) <> TOK_TASK then Expected(sTaskName); Next; CloseParen; EmitLn(op + ' ' + val); end; procedure TNXCComp.DoStop; begin // Stop(stop?); Next; OpenParen; // stop? BoolExpression; CloseParen; EmitLn(Format('stop %s',[RegisterName])); end; procedure TNXCComp.DoGoto; begin // goto labelName; Next; // labelName CheckIdent; Branch(Value); // EmitLn(Format('jmp %s',[Value])); Next; end; procedure TNXCComp.DoSetInputOutput(const idx: integer); var port, pchk, field, val, asmstr : string; i, cnt, iport : integer; begin // SetInput(port, field, value) // SetOutput(ports, field, value [, field, value, ...]) Next; OpenParen; // port port := GetDecoratedValue; Next; MatchString(TOK_COMMA); // field CheckNumeric; field := Value; Next; MatchString(TOK_COMMA); // value BoolExpression; if idx = API_SETINPUT then begin // SetInput CloseParen; EmitLn(Format('setin %s, %s, %s', [RegisterName, port, field])); end else begin // setout can take additional optional field/value pairs cnt := 0; pchk := port; if idx = API_SETOUTPUT then begin iport := StrToIntDef(port, 0); case iport of OUT_AB : port := '__OUT_AB'; OUT_AC : port := '__OUT_AC'; OUT_BC : port := '__OUT_BC'; OUT_ABC : port := '__OUT_ABC'; end; end; asmstr := Format('setout %s, %s', [port, field]); while (Token = TOK_COMMA) and not endofallsource do begin inc(cnt); push; val := tos; EmitLn(Format('mov %s, %s',[val, RegisterName])); Next; // field CheckNumeric; field := Value; Next; MatchString(TOK_COMMA); // value BoolExpression; asmstr := asmstr + Format(', %s, %s', [val, field]); end; CloseParen; asmstr := asmstr + Format(', %s', [RegisterName]); EmitLn(Format('compif EQ, isconst(%s), FALSE', [pchk])); EmitLn(asmstr); EmitLn('compelse'); EmitLn(Format('compchk LT, %s, 0x07', [pchk])); EmitLn(Format('compchk GTEQ, %s, 0x00', [pchk])); EmitLn(asmstr); EmitLn('compend'); for i := 0 to cnt - 1 do pop; end; end; procedure TNXCComp.DoReturn; var rdt : char; idx : integer; bFuncStyle : boolean; begin // return idx := GlobalIdx(fCurrentThreadName); if GS_Type[idx] <> TOK_PROCEDURE then AbortMsg(sReturnInvalid); rdt := FunctionReturnType(fCurrentThreadName); Next; // leave return value on "stack" if rdt = TOK_STRINGDEF then begin bFuncStyle := Token = TOK_OPENPAREN; if bFuncStyle then Next; StringExpression(''); if bFuncStyle then Next; end else if IsUDT(rdt) or IsArrayType(rdt) then begin // currently this code only supports returning a variable for UDTs or Arrays // TODO : add support for an array or UDT expression bFuncStyle := Token = TOK_OPENPAREN; if bFuncStyle then Next; fLHSDataType := rdt; fLHSName := Format('__result_%s',[fCurrentThreadName]); try NumericFactor; finally fLHSDataType := TOK_LONGDEF; fLHSName := ''; end; { // 2008-12-14 JCH - needed the decorated value rather than just Value EmitLn(Format('mov __result_%s, %s',[fCurrentThreadName, GetDecoratedValue])); // 2008-12-14 JCH The next line fixes a bug where parser gets out // of sync with the end of the return statement Next; // move to the ')' or ';' } if bFuncStyle then Next; end else if rdt <> #0 then begin CommaExpression; MoveToCorrectRegister(rdt); end; // Semi; EmitLn('return'); end; procedure TNXCComp.DoResetCounters; var op, arg1 : string; begin // ResetTachoCount(ports) // ResetBlockTachoCount(ports) // ResetRotationCount(ports) // ResetAllTachoCounts(ports) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; CloseParen; EmitLn(op + TOK_OPENPAREN + arg1 + TOK_CLOSEPAREN); end; procedure TNXCComp.DoStopMotors; var op, arg1 : string; begin // Off(ports) // Coast(ports) // Float(ports) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; CloseParen; EmitLn(op + TOK_OPENPAREN + arg1 + TOK_CLOSEPAREN); end; procedure TNXCComp.DoStopMotorsEx; var op, arg1, arg2 : string; begin // OffEx(ports, reset) // CoastEx(ports, reset) op := Value; Next; OpenParen; // ports arg1 := GetDecoratedValue; Next; MatchString(TOK_COMMA); // reset CheckNumeric; arg2 := Value; Next; CloseParen; EmitLn(Format('%s(%s, %s)', [op, arg1, arg2])); end; procedure TNXCComp.PreProcess; var P : TLangPreprocessor; i, idx : integer; tmpFile, tmpMsg : string; begin P := TLangPreprocessor.Create(GetPreProcLexerClass, ExtractFilePath(ParamStr(0)), lnNXC, MaxPreprocessorDepth); try P.OnPreprocessorStatusChange := HandlePreprocStatusChange; P.AddPoundLineToMultiLineMacros := True; P.Defines.AddDefines(Defines); if EnhancedFirmware then P.Defines.Define('__ENHANCED_FIRMWARE'); P.Defines.AddEntry('__FIRMWARE_VERSION', IntToStr(FirmwareVersion)); P.AddIncludeDirs(IncludeDirs); if not IgnoreSystemFile then begin P.SkipIncludeFile('NBCCommon.h'); P.SkipIncludeFile('NXCDefs.h'); end; P.Preprocess(CurrentFile, fMS); for i := 0 to P.Warnings.Count - 1 do begin tmpMsg := P.Warnings.ValueFromIndex[i]; idx := Pos('|', tmpMsg); tmpFile := Copy(tmpMsg, 1, idx-1); Delete(tmpMsg, 1, idx); ReportProblem(StrToIntDef(P.Warnings.Names[i], 0), tmpFile, tmpMsg, false); end; finally P.Free; end; end; procedure TNXCComp.ProcessDirectives(bScan : boolean); begin while Token = TOK_DIRECTIVE do begin // look for #line statements if LowerCase(Value) = '#line' then begin SkipDirectiveLine; HandlePoundLine; Next(False); end else begin SkipDirectiveLine; Next(False); end; EmitPoundLine; EmitLnNoTab(Trim(fDirLine)); // EmitLn(Trim(fDirLine)); if bScan then Scan; end; end; procedure TNXCComp.HandlePoundLine; var i : integer; tmpLine, tmpFile : string; begin i := Pos('#line ', fDirLine); if i = 1 then begin // this is a special preprocessor line tmpLine := Trim(fDirLine); Delete(tmpLine, 1, 6); i := Pos(' ', tmpLine); linenumber{[slevel]} := StrToIntDef(Copy(tmpLine, 1, i - 1), linenumber{[slevel]}); IncLineNumber; Delete(tmpLine, 1, i); tmpFile := Replace(tmpLine, '"', ''); CurrentFile := tmpFile; end; end; procedure TNXCComp.IncLineNumber; begin linenumber := linenumber + 1; inc(totallines); end; function TNXCComp.APIFuncNameToID(procname: string): integer; begin Result := StrToIntDef(fAPIFunctions.Values[procname], -1); end; function TNXCComp.APIStrFuncNameToID(procname: string): integer; begin Result := StrToIntDef(fAPIStrFunctions.Values[procname], -1); end; function TNXCComp.IsAPIFunc(procname: string): boolean; begin Result := fAPIFunctions.IndexOfName(procname) <> -1; end; function TNXCComp.IsAPIStrFunc(procname: string): boolean; begin Result := fAPIStrFunctions.IndexOfName(procname) <> -1; end; procedure TNXCComp.AddAPIFunction(const name: string; id: integer); begin fAPIFunctions.Add(name + '=' + IntToStr(id)); end; procedure TNXCComp.AddAPIStringFunction(const name: string; id: integer); begin fAPIStrFunctions.Add(name + '=' + IntToStr(id)); end; function TNXCComp.tos : string; begin Result := fStackVarNames[fStackVarNames.Count - 1]; // set statement type based on type on top of stack if Pos('__float_stack_', Result) <> 0 then StatementType := stFloat else if (Pos('__signed_stack_', Result) <> 0) and (StatementType <> stFloat) then StatementType := stSigned; { if fStatementType = stFloat then Result := Format('__float_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]) else if fStatementType = stUnsigned then Result := Format('__unsigned_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]) else Result := Format('__signed_stack_%3.3d%s', [fStackDepth, fCurrentThreadName]); } end; function TNXCComp.TempSignedByteName: string; begin Result := Format('__tmpsbyte%s', [fCurrentThreadName]); end; function TNXCComp.TempSignedWordName: string; begin Result := Format('__tmpsword%s', [fCurrentThreadName]); end; function TNXCComp.TempSignedLongName: string; begin Result := Format('__tmpslong%s', [fCurrentThreadName]); end; function TNXCComp.TempUnsignedLongName: string; begin Result := Format('__tmplong%s', [fCurrentThreadName]); end; function TNXCComp.TempFloatName: string; begin Result := Format('__tmpfloat%s', [fCurrentThreadName]); end; function TNXCComp.RegisterNameByStatementType(st : TStatementType; name : string = '') : string; begin if fUDTOnStack <> '' then begin Result := fUDTOnStack; fUDTOnStack := ''; // once it has been used it is removed from the stack end else begin if st = stFloat then Result := FloatRegisterName(name) else if st = stUnsigned then Result := UnsignedRegisterName(name) else Result := SignedRegisterName(name); end; end; function TNXCComp.RegisterName(name : string): string; begin if fUDTOnStack <> '' then begin Result := fUDTOnStack; fUDTOnStack := ''; // once it has been used it is removed from the stack end else begin if fStatementType = stFloat then Result := FloatRegisterName(name) else if fStatementType = stUnsigned then Result := UnsignedRegisterName(name) else Result := SignedRegisterName(name); end; end; function TNXCComp.SignedRegisterName(name: string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__D0%s',[name]); end; function TNXCComp.UnsignedRegisterName(name: string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__DU0%s',[name]); end; function TNXCComp.FloatRegisterName(name: string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__DF0%s',[name]); end; function TNXCComp.ZeroFlag: string; begin Result := Format('__zf%s', [fCurrentThreadName]); end; function TNXCComp.StrTmpBufName(name : string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__strtmpbuf%s', [name]); end; function TNXCComp.StrBufName(name : string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__strbuf%s', [name]); end; function TNXCComp.StrRetValName(name : string): string; begin if name = '' then name := fCurrentThreadName; Result := Format('__strretval%s', [name]); end; procedure TNXCComp.EmitRegisters; var j, k, idx, LastRegIdx : integer; f : TInlineFunction; H : TArrayHelperVar; dt : Char; name, tname : string; function EmitFmt(const idx : integer) : string; begin Result := REGVARS_ARRAY[idx] + ' ' + REGVARTYPES_ARRAY[idx]; end; begin LastRegIdx := High(REGVARS_ARRAY); if FirmwareVersion < MIN_FW_VER2X then dec(LastRegIdx, 2); for j := 0 to fArrayHelpers.Count - 1 do begin H := fArrayHelpers[j]; dt := H.DataType; name := H.Name; tname := GlobalTypeName(name); AllocateHelper(name, DataTypeToArrayDimensions(dt), '', tname, dt); end; for j := 0 to fThreadNames.Count - 1 do begin name := fThreadNames[j]; if fInlineFunctions.IndexOfName(name) = -1 then begin for idx := Low(REGVARS_ARRAY) to LastRegIdx do EmitLn(Format(EmitFmt(idx), [name])); dt := FunctionReturnType(name); if IsUDT(dt) or IsArrayType(dt) then begin tname := GlobalTypeName(name); AllocateHelper(Format('__result_%s', [name]), DataTypeToArrayDimensions(dt), '', tname, dt); end; end; end; for j := 0 to fInlineFunctions.Count - 1 do begin f := fInlineFunctions[j]; for k := 0 to f.Callers.Count - 1 do begin name := InlineName(f.Callers[k], f.Name); for idx := Low(REGVARS_ARRAY) to LastRegIdx do EmitLn(Format(EmitFmt(idx), [name])); dt := FunctionReturnType(f.Name); if IsUDT(dt) or IsArrayType(dt) then begin tname := GlobalTypeName(f.Name); AllocateHelper(Format('__result_%s', [name]), DataTypeToArrayDimensions(dt), '', tname, dt); end; end; end; end; procedure TNXCComp.EmitStackVariables; var i, j, k : integer; f : TInlineFunction; name : string; begin for j := 0 to fThreadNames.Count - 1 do begin name := fThreadNames[j]; if fInlineFunctions.IndexOfName(name) = -1 then begin for i := 1 to MaxStackDepth do begin EmitLn(Format('__signed_stack_%3.3d%s slong', [i, name])); end; for i := 1 to MaxStackDepth do begin EmitLn(Format('__unsigned_stack_%3.3d%s long', [i, name])); end; if FirmwareVersion >= MIN_FW_VER2X then begin for i := 1 to MaxStackDepth do begin EmitLn(Format('__float_stack_%3.3d%s float', [i, name])); end; end; end; end; for j := 0 to fInlineFunctions.Count - 1 do begin f := fInlineFunctions[j]; for k := 0 to f.Callers.Count - 1 do begin name := InlineName(f.Callers[k], f.Name); for i := 1 to MaxStackDepth do begin EmitLn(Format('__signed_stack_%3.3d%s slong', [i, name])); end; for i := 1 to MaxStackDepth do begin EmitLn(Format('__unsigned_stack_%3.3d%s long', [i, name])); end; if FirmwareVersion >= MIN_FW_VER2X then begin for i := 1 to MaxStackDepth do begin EmitLn(Format('__float_stack_%3.3d%s float', [i, name])); end; end; end; end; end; const APISF_NUMTOSTR = 0; APISF_STRCAT = 1; APISF_SUBSTR = 2; APISF_FLATTEN = 3; APISF_STRREPLACE = 4; APISF_FORMATNUM = 5; procedure TNXCComp.StringFunction(const Name : string); var id : integer; op : string; begin id := APIStrFuncNameToID(Name); case id of APISF_NUMTOSTR, APISF_FLATTEN : begin OpenParen; BoolExpression; CloseParen; if id = APISF_NUMTOSTR then op := 'numtostr' else op := 'flatten'; EmitLn(Format('%s %s, %s', [op, StrRetValName, RegisterName])); end; APISF_STRCAT : DoStrCat; APISF_SUBSTR : DoSubString; APISF_STRREPLACE : DoStrReplace; APISF_FORMATNUM : DoFormatNum; else AbortMsg(Format(sNotAnAPIStrFunc, [Name])); end; end; procedure TNXCComp.DoStrReplace; var str, strnew, idx : string; begin // StrReplace(string, idx, strnew) OpenParen; // string StringExpression(''); EmitLn(Format('mov %s, %s', [StrTmpBufName, StrBufName])); str := StrTmpBufName; MatchString(TOK_COMMA); // idx BoolExpression; push; idx := tos; EmitLn(Format('mov %s, %s', [idx, RegisterName])); MatchString(TOK_COMMA); // strnew StringExpression(''); EmitLn(Format('mov %s, %s', [StrRetValName, StrBufName])); strnew := StrRetValName; CloseParen; // strip the null from the replacement string so that it doesn't embed a null // in the middle of the output string EmitLn(Format('strtoarr %s, %s', [StrBufName, strnew])); EmitLn(Format('strreplace %s, %s, %s, %s', [StrRetValName, str, idx, StrBufName])); pop; end; procedure TNXCComp.DoStrCat; var asmStr : string; begin // StrCat(str1, str2, ..., strN) OpenParen; asmstr := Format('strcat %s, ', [StrRetValName]) + StrCatHelper('', ','); CloseParen; EmitLn(asmStr); end; function TNXCComp.StrCatHelper(const oldasmstr : string; recurseToken : Char) : string; var AHV : TArrayHelperVar; aval : string; begin StringExpression(''); AHV := fArrayHelpers.GetHelper(fCurrentThreadName, '', TOK_ARRAYBYTEDEF); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, TOK_ARRAYBYTEDEF, '', ''); // move result of string expression to newly allocated temporary variable EmitLn(Format('mov %s, %s', [aval, StrBufName])); if Token = recurseToken then begin Next; // skip past the recurse token (comma or + depending on the context) Result := oldasmstr + StrCatHelper(aval + ', ', ','); end else Result := oldasmstr + aval; finally fArrayHelpers.ReleaseHelper(AHV); end; end; procedure TNXCComp.DoSubString; var str, idx : string; begin // SubStr(string, idx, len) OpenParen; // string StringExpression(''); str := StrBufName; MatchString(TOK_COMMA); // idx BoolExpression; push; idx := tos; EmitLn(Format('mov %s, %s', [idx, RegisterName])); MatchString(TOK_COMMA); // len BoolExpression; CloseParen; EmitLn(Format('strsubset %s, %s, %s, %s', [StrRetValName, str, idx, RegisterName])); pop; end; const APIF_ABS = 0; APIF_SIGN = 1; APIF_RANDOM = 2; APIF_GETINPUT = 3; APIF_GETOUTPUT = 4; APIF_RESETSCREEN = 7; APIF_TEXTOUT = 8; APIF_NUMOUT = 9; APIF_PLAYTONEEX = 12; APIF_PLAYFILEEX = 13; APIF_BUTTONPRESSED = 18; APIF_BUTTONCOUNT = 19; APIF_READBUTTONEX = 20; APIF_DRAWPOINT = 22; APIF_DRAWLINE = 23; APIF_DRAWCIRCLE = 24; APIF_DRAWRECT = 25; APIF_DRAWGRAPHIC = 26; APIF_DRAWGRAPHICEX = 27; APIF_STRTONUM = 31; APIF_STRLEN = 32; APIF_STRINDEX = 33; APIF_ASM = 34; APIF_DRAWGRAPHICAR = 35; APIF_DRAWGRAPHICAREX = 36; APIF_DRAWPOLY = 37; APIF_DRAWELLIPSE = 38; APIF_FONTTEXTOUT = 39; APIF_FONTNUMOUT = 40; // APIF_SIZEOF = 41; procedure TNXCComp.DoCallAPIFunc(procname: string); var arg, parg, op, asmStr : string; id : integer; dt : char; begin fCCSet := False; ResetStatementType; id := APIFuncNameToID(procname); case id of APIF_ASM : begin dt := #0; DoAsm(dt); fSemiColonRequired := True; end; APIF_RANDOM : begin OpenParen; if Value = TOK_CLOSEPAREN then begin CloseParen; EmitLn(Format('SignedRandom(%0:s)', [RegisterName])); end else begin BoolExpression; CloseParen; EmitLn(Format('Random(%0:s, %0:s)', [RegisterName])); end; end; APIF_ABS, APIF_SIGN : begin OpenParen; BoolExpression; CloseParen; case id of APIF_ABS : asmStr := 'abs %0:s, %0:s'; APIF_SIGN : asmStr := 'sign %0:s, %0:s'; end; EmitLn(Format(asmStr, [RegisterName])); end; APIF_GETINPUT, APIF_GETOUTPUT : begin // GetInput(port, field) // GetOutput(port, field) OpenParen; // port parg := GetDecoratedValue; Next; MatchString(TOK_COMMA); // field CheckNumeric; arg := Value; Next; CloseParen; case id of APIF_GETINPUT : op := 'getin'; APIF_GETOUTPUT : op := 'getout'; end; EmitLn(Format('%s %s, %s, %s', [op, RegisterName, parg, arg])); end; APIF_RESETSCREEN : DoResetScreen; APIF_TEXTOUT, APIF_NUMOUT : DoTextNumOut(id); APIF_PLAYTONEEX : DoPlayToneEx; APIF_PLAYFILEEX : DoPlayFileEx; APIF_BUTTONPRESSED, APIF_BUTTONCOUNT, APIF_READBUTTONEX : DoReadButton(id); APIF_DRAWPOINT : DoDrawPoint; APIF_DRAWLINE, APIF_DRAWRECT : DoDrawLineRect(id); APIF_DRAWCIRCLE : DoDrawCircle; APIF_DRAWGRAPHIC, APIF_DRAWGRAPHICEX, APIF_DRAWGRAPHICAR, APIF_DRAWGRAPHICAREX : DoDrawGraphic(id); APIF_STRTONUM : DoStrToNum; APIF_STRLEN : DoStrLen; APIF_STRINDEX : DoStrIndex; APIF_DRAWPOLY : DoDrawPoly; APIF_DRAWELLIPSE : DoDrawEllipse; APIF_FONTTEXTOUT, APIF_FONTNUMOUT : DoFontTextNumOut(id); // APIF_SIZEOF : DoSizeOf; else AbortMsg(Format(sNotAnAPIFunc, [procname])); end; end; (* procedure TNXCComp.DoSizeOf; var val : integer; arg, savedval : string; savedtok : Char; begin // sizeof(var or type) OpenParen; Scan; arg := ''; savedtok := #0; while Token <> TOK_CLOSEPAREN do begin // unsigned and const do not change the type size so skip them if not (Token in [TOK_CONST, TOK_UNSIGNED]) then begin savedval := Value; savedtok := Token; arg := arg + Value + ' '; if Token = TOK_IDENTIFIER then Break; end; Next; Scan; end; arg := Trim(arg); if savedtok := TOK_IDENTIFIER then begin // first look up the type from the variable name end else begin // get type from type name end; //????????? CloseParen; EmitLn(Format('mov %s, %s', [RegisterName, IntToStr(val)])); end; *) procedure TNXCComp.DoStrIndex; var arg : string; begin // StrIndex(string, idx) OpenParen; // string StringExpression(''); arg := StrBufName; MatchString(TOK_COMMA); // idx BoolExpression; CloseParen; EmitLn(Format('strindex %0:s, %s, %0:s',[RegisterName, arg])); end; procedure TNXCComp.DoStrLen; var arg : string; begin // StrLen(string) OpenParen; // string StringExpression(''); arg := StrBufName; CloseParen; EmitLn(Format('strlen %s, %s', [RegisterName, arg])); end; procedure TNXCComp.DoStrToNum; var arg : string; begin // StrToNum(string) OpenParen; // string StringExpression(''); arg := StrBufName; CloseParen; push; EmitLn(Format('strtonum %0:s, %s, %s, NA, NA', [RegisterName, tos, arg])); pop; end; procedure TNXCComp.DoResetScreen; begin OpenParen; CloseParen; EmitLn('acquire __SSMArgsMutex'); EmitLn('set __SSMArgs.ScreenMode, 0'); EmitLn('syscall SetScreenMode, __SSMArgs'); EmitLn(Format('mov %s, __SSMArgs.Result', [RegisterName])); EmitLn('release __SSMArgsMutex'); end; procedure TNXCComp.DoTextNumOut(idx: integer); var x, y, txt, val : string; bCls : boolean; begin //TextOut(x,y,txt,options=false) //NumOut(x,y,num,options=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); if idx = APIF_NUMOUT then begin BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; val := tos; EmitLn(Format('mov %s, %s', [val, RegisterName])); MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __TextOutMutex'); EmitLn('mov __TextOutArgs.Location.X, ' + x); EmitLn('mov __TextOutArgs.Location.Y, ' + y); if bCls then begin EmitLn('mov __TextOutArgs.Options, ' + RegisterName); EmitLn(Format('numtostr __TextOutArgs.Text, %s',[val])); end else begin EmitLn('set __TextOutArgs.Options, 0'); EmitLn(Format('numtostr __TextOutArgs.Text, %s',[RegisterName])); end; EmitLn('syscall DrawText, __TextOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __TextOutArgs.Result',[RegisterName])); EmitLn('release __TextOutMutex'); if bCls then pop; end else begin StringExpression(''); txt := StrBufName; bCls := Token = TOK_COMMA; if bCls then begin MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __TextOutMutex'); EmitLn('mov __TextOutArgs.Location.X, ' + x); EmitLn('mov __TextOutArgs.Location.Y, ' + y); if bCls then EmitLn('mov __TextOutArgs.Options, ' + RegisterName) else EmitLn('set __TextOutArgs.Options, 0'); EmitLn('mov __TextOutArgs.Text, ' + txt); EmitLn('syscall DrawText, __TextOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __TextOutArgs.Result',[RegisterName])); EmitLn('release __TextOutMutex'); end; pop; pop; end; procedure TNXCComp.DoFontTextNumOut(idx: integer); var x, y, fntname, txt, val : string; bCls : boolean; begin //FontTextOut(x,y,file,txt,options=false) //FontNumOut(x,y,file,num,options=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = file StringExpression(''); EmitLn(Format('mov %s, %s', [StrTmpBufName, StrBufName])); fntname := StrTmpBufName; MatchString(TOK_COMMA); if idx = APIF_FONTNUMOUT then begin BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; val := tos; EmitLn(Format('mov %s, %s', [val, RegisterName])); MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __FontOutMutex'); EmitLn('mov __FontOutArgs.Location.X, ' + x); EmitLn('mov __FontOutArgs.Location.Y, ' + y); EmitLn('mov __FontOutArgs.Filename, ' + fntname); if bCls then begin EmitLn('mov __FontOutArgs.Options, ' + RegisterName); EmitLn(Format('numtostr __FontOutArgs.Text, %s',[val])); end else begin EmitLn('set __FontOutArgs.Options, 0'); EmitLn(Format('numtostr __FontOutArgs.Text, %s',[RegisterName])); end; EmitLn('syscall DrawFont, __FontOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __FontOutArgs.Result',[RegisterName])); EmitLn('release __FontOutMutex'); if bCls then pop; end else begin StringExpression(''); txt := StrBufName; bCls := Token = TOK_COMMA; if bCls then begin MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __FontOutMutex'); EmitLn('mov __FontOutArgs.Location.X, ' + x); EmitLn('mov __FontOutArgs.Location.Y, ' + y); EmitLn('mov __FontOutArgs.Filename, ' + fntname); if bCls then EmitLn('mov __FontOutArgs.Options, ' + RegisterName) else EmitLn('set __FontOutArgs.Options, 0'); EmitLn('mov __FontOutArgs.Text, ' + txt); EmitLn('syscall DrawFont, __FontOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __FontOutArgs.Result',[RegisterName])); EmitLn('release __FontOutMutex'); end; pop; pop; end; procedure TNXCComp.DoDrawPoint; var x, y : string; bCls : boolean; begin //PointOut(x,y,cls=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = cls BoolExpression; end; CloseParen; EmitLn('acquire __PointOutMutex'); EmitLn('mov __PointOutArgs.Location.X, ' + x); if bCls then begin EmitLn('mov __PointOutArgs.Location.Y, ' + y); EmitLn('mov __PointOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __PointOutArgs.Location.Y, ' + RegisterName); EmitLn('set __PointOutArgs.Options, 0'); end; EmitLn('syscall DrawPoint, __PointOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __PointOutArgs.Result',[RegisterName])); EmitLn('release __PointOutMutex'); pop; if bCls then pop; end; procedure TNXCComp.DoDrawPoly; var pts : string; bCls : boolean; begin //PolyOut(points,options=false) OpenParen; // arg1 = points pts := GetDecoratedValue; Next; bCls := Token = TOK_COMMA; if bCls then begin MatchString(TOK_COMMA); // arg2 = cls BoolExpression; end; CloseParen; EmitLn('acquire __PolyOutMutex'); EmitLn('mov __PolyOutArgs.Points, ' + pts); if bCls then begin EmitLn('mov __PolyOutArgs.Options, ' + RegisterName); end else begin EmitLn('set __PolyOutArgs.Options, 0'); end; EmitLn('syscall DrawPolygon, __PolyOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __PolyOutArgs.Result',[RegisterName])); EmitLn('release __PolyOutMutex'); end; procedure TNXCComp.DoDrawLineRect(idx : integer); var x, y, x2, y2 : string; bCls : boolean; begin //LineOut(x1,y1,x2,y2,cls=false) //RectOut(x1,y1,width,height,cls=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = x2 BoolExpression; push; x2 := tos; EmitLn(Format('mov %s, %s', [x2, RegisterName])); MatchString(TOK_COMMA); // arg4 = y2 BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; y2 := tos; EmitLn(Format('mov %s, %s', [y2, RegisterName])); MatchString(TOK_COMMA); // arg5 = cls BoolExpression; end; CloseParen; if idx = APIF_DRAWRECT then begin EmitLn('acquire __RectOutMutex'); EmitLn('mov __RectOutArgs.Location.X, ' + x); EmitLn('mov __RectOutArgs.Location.Y, ' + y); EmitLn('mov __RectOutArgs.Size.Width, ' + x2); if bCls then begin EmitLn('mov __RectOutArgs.Size.Height, ' + y2); EmitLn('mov __RectOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __RectOutArgs.Size.Height, ' + RegisterName); EmitLn('set __RectOutArgs.Options, 0'); end; EmitLn('syscall DrawRect, __RectOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __RectOutArgs.Result',[RegisterName])); EmitLn('release __RectOutMutex'); end else begin EmitLn('acquire __LineOutMutex'); EmitLn('mov __LineOutArgs.StartLoc.X, ' + x); EmitLn('mov __LineOutArgs.StartLoc.Y, ' + y); EmitLn('mov __LineOutArgs.EndLoc.X, ' + x2); if bCls then begin EmitLn('mov __LineOutArgs.EndLoc.Y, ' + y2); EmitLn('mov __LineOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __LineOutArgs.EndLoc.Y, ' + RegisterName); EmitLn('set __LineOutArgs.Options, 0'); end; EmitLn('syscall DrawLine, __LineOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __LineOutArgs.Result',[RegisterName])); EmitLn('release __LineOutMutex'); end; pop; pop; pop; if bCls then pop; end; procedure TNXCComp.DoDrawCircle; var x, y, radius : string; bCls : boolean; begin //CircleOut(x1,y1,radius,cls=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = radius BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; radius := tos; EmitLn(Format('mov %s, %s', [radius, RegisterName])); MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __CircleOutMutex'); EmitLn('mov __CircleOutArgs.Center.X, ' + x); EmitLn('mov __CircleOutArgs.Center.Y, ' + y); if bCls then begin EmitLn('mov __CircleOutArgs.Size, ' + radius); EmitLn('mov __CircleOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __CircleOutArgs.Size, ' + RegisterName); EmitLn('set __CircleOutArgs.Options, 0'); end; EmitLn('syscall DrawCircle, __CircleOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __CircleOutArgs.Result',[RegisterName])); EmitLn('release __CircleOutMutex'); pop; pop; if bCls then pop; end; procedure TNXCComp.DoDrawEllipse; var x, y, radiusX, radiusY : string; bCls : boolean; begin //EllipseOut(x,y,radiusX,radiusY,cls=false) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = radiusX BoolExpression; push; radiusX := tos; EmitLn(Format('mov %s, %s', [radiusX, RegisterName])); MatchString(TOK_COMMA); // arg4 = radiusY BoolExpression; bCls := Token = TOK_COMMA; if bCls then begin push; radiusY := tos; EmitLn(Format('mov %s, %s', [radiusY, RegisterName])); MatchString(TOK_COMMA); // arg5 = cls BoolExpression; end; CloseParen; EmitLn('acquire __EllipseOutMutex'); EmitLn('mov __EllipseOutArgs.Center.X, ' + x); EmitLn('mov __EllipseOutArgs.Center.Y, ' + y); EmitLn('mov __EllipseOutArgs.SizeX, ' + radiusX); if bCls then begin EmitLn('mov __EllipseOutArgs.SizeY, ' + radiusY); EmitLn('mov __EllipseOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __EllipseOutArgs.SizeY, ' + RegisterName); EmitLn('set __EllipseOutArgs.Options, 0'); end; EmitLn('syscall DrawEllipse, __EllipseOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __EllipseOutArgs.Result',[RegisterName])); EmitLn('release __EllipseOutMutex'); pop; pop; pop; if bCls then pop; end; procedure TNXCComp.DoDrawGraphic(idx : integer); var x, y, fname, vars : string; bCls : boolean; begin //GraphicOut(x,y,fname,options=0) //GraphicOutEx(x,y,fname,vars,options=0) //GraphicArrayOut(x,y,data,options=0) //GraphicArrayOutEx(x,y,data,vars,options=0) OpenParen; // arg1 = x BoolExpression; push; x := tos; EmitLn(Format('mov %s, %s', [x, RegisterName])); MatchString(TOK_COMMA); // arg2 = y BoolExpression; push; y := tos; EmitLn(Format('mov %s, %s', [y, RegisterName])); MatchString(TOK_COMMA); // arg3 = fname|data if idx in [APIF_DRAWGRAPHIC, APIF_DRAWGRAPHICEX] then begin StringExpression(''); fname := StrBufName; end else begin fname := GetDecoratedValue; if DataType(Value) <> TOK_ARRAYBYTEDEF then Expected(sByteArrayType); Next; end; if idx in [APIF_DRAWGRAPHICEX, APIF_DRAWGRAPHICAREX] then begin MatchString(TOK_COMMA); // arg4 = vars vars := GetDecoratedValue; Next; end; bCls := Token = TOK_COMMA; if bCls then begin MatchString(TOK_COMMA); // arg4 = cls BoolExpression; end; CloseParen; EmitLn('acquire __GraphicOutMutex'); if idx in [APIF_DRAWGRAPHIC, APIF_DRAWGRAPHICEX] then begin EmitLn('mov __GraphicOutArgs.Location.X, ' + x); EmitLn('mov __GraphicOutArgs.Location.Y, ' + y); if bCls then begin EmitLn('mov __GraphicOutArgs.Options, ' + RegisterName); end else begin EmitLn('mov __GraphicOutArgs.Options, 0'); end; EmitLn('mov __GraphicOutArgs.Filename, ' + fname); if idx = APIF_DRAWGRAPHICEX then EmitLn('mov __GraphicOutArgs.Variables, ' + vars) else EmitLn('mov __GraphicOutArgs.Variables, __GraphicOutEmptyVars'); EmitLn('syscall DrawGraphic, __GraphicOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __GraphicOutArgs.Result',[RegisterName])); end else begin EmitLn('mov __GraphicArrayOutArgs.Location.X, ' + x); EmitLn('mov __GraphicArrayOutArgs.Location.Y, ' + y); if bCls then begin EmitLn('mov __GraphicArrayOutArgs.Options, ' + RegisterName); end else begin EmitLn('set __GraphicArrayOutArgs.Options, 0'); end; EmitLn('mov __GraphicArrayOutArgs.Data, ' + fname); if idx = APIF_DRAWGRAPHICAREX then EmitLn('mov __GraphicArrayOutArgs.Variables, ' + vars) else EmitLn('mov __GraphicArrayOutArgs.Variables, __GraphicOutEmptyVars'); EmitLn('syscall DrawGraphicArray, __GraphicArrayOutArgs'); ResetStatementType; EmitLn(Format('mov %s, __GraphicArrayOutArgs.Result',[RegisterName])); end; EmitLn('release __GraphicOutMutex'); pop; pop; end; procedure TNXCComp.DoPlayToneEx; var freq, dur, vol : string; begin //PlayToneEx(freq, dur, vol, loop) OpenParen; // arg1 == Frequency BoolExpression; push; freq := tos; EmitLn(Format('mov %s, %s', [freq, RegisterName])); MatchString(TOK_COMMA); // arg2 == Duration BoolExpression; push; dur := tos; EmitLn(Format('mov %s, %s', [dur, RegisterName])); MatchString(TOK_COMMA); // arg3 == Volume BoolExpression; push; vol := tos; EmitLn(Format('mov %s, %s', [vol, RegisterName])); MatchString(TOK_COMMA); // arg4 == loop? BoolExpression; CloseParen; EmitLn('acquire __SPTArgsMutex'); EmitLn('mov __SPTArgs.Frequency, ' + freq); EmitLn('mov __SPTArgs.Duration, ' + dur); EmitLn('mov __SPTArgs.Volume, ' + vol); EmitLn(Format('mov __SPTArgs.Loop, %s',[RegisterName])); EmitLn('syscall SoundPlayTone, __SPTArgs'); ResetStatementType; EmitLn(Format('mov %s, __SPTArgs.Result',[RegisterName])); EmitLn('release __SPTArgsMutex'); pop; pop; pop; end; procedure TNXCComp.DoPlayFileEx; var fname, vol : string; begin //PlayFileEx(file, vol, loop?) OpenParen; // arg1 == Filename StringExpression(''); fname := StrBufName; MatchString(TOK_COMMA); // arg2 == Volume BoolExpression; push; vol := tos; EmitLn(Format('mov %s, %s', [vol, RegisterName])); MatchString(TOK_COMMA); // arg3 == loop? BoolExpression; CloseParen; EmitLn('acquire __SPFArgsMutex'); EmitLn('mov __SPFArgs.Filename, ' + fname); EmitLn('mov __SPFArgs.Volume, ' + vol); EmitLn(Format('mov __SPFArgs.Loop, %s', [RegisterName])); EmitLn('syscall SoundPlayFile, __SPFArgs'); ResetStatementType; EmitLn(Format('mov %s, __SPFArgs.Result', [RegisterName])); EmitLn('release __SPFArgsMutex'); pop; end; procedure TNXCComp.DoReadButton(idx: integer); var btn, pressed, count : string; begin // ButtonPressed(btn, reset) // ButtonCount(btn, reset) // ReadButtonEx(btn, reset, pressed, count) OpenParen; // arg1 = button index BoolExpression; push; btn := tos; EmitLn(Format('mov %s, %s', [btn, RegisterName])); MatchString(TOK_COMMA); // arg2 = reset? BoolExpression; if idx = APIF_READBUTTONEX then begin // two output args MatchString(TOK_COMMA); // pressed pressed := GetDecoratedValue; CheckIdent; CheckTable(Value); Next; MatchString(TOK_COMMA); // count count := GetDecoratedValue; CheckIdent; CheckTable(Value); Next; end; CloseParen; EmitLn('acquire __RBtnMutex'); EmitLn('mov __RBtnArgs.Index, ' + btn); EmitLn(Format('mov __RBtnArgs.Reset, %s', [RegisterName])); EmitLn('syscall ReadButton, __RBtnArgs'); ResetStatementType; if idx = APIF_BUTTONCOUNT then EmitLn(Format('mov %s, __RBtnArgs.Count',[RegisterName])) else if idx = APIF_BUTTONPRESSED then EmitLn(Format('mov %s, __RBtnArgs.Pressed',[RegisterName])) else begin EmitLn(Format('mov %s, __RBtnArgs.Pressed', [pressed])); EmitLn(Format('mov %s, __RBtnArgs.Count', [count])); EmitLn(Format('mov %s, __RBtnArgs.Result', [RegisterName])); end; EmitLn('release __RBtnMutex'); pop; end; procedure TNXCComp.LoadAPIFunctions; begin AddAPIFunction('asm', APIF_ASM); AddAPIFunction('abs', APIF_ABS); AddAPIFunction('sign', APIF_SIGN); AddAPIFunction('Random', APIF_RANDOM); AddAPIFunction('GetInput', APIF_GETINPUT); AddAPIFunction('GetOutput', APIF_GETOUTPUT); AddAPIFunction('ResetScreen', APIF_RESETSCREEN); AddAPIFunction('TextOut', APIF_TEXTOUT); AddAPIFunction('NumOut', APIF_NUMOUT); AddAPIFunction('PlayToneEx', APIF_PLAYTONEEX); AddAPIFunction('PlayFileEx', APIF_PLAYFILEEX); AddAPIFunction('ButtonPressed', APIF_BUTTONPRESSED); AddAPIFunction('ButtonCount', APIF_BUTTONCOUNT); AddAPIFunction('ReadButtonEx', APIF_READBUTTONEX); AddAPIFunction('PointOut', APIF_DRAWPOINT); AddAPIFunction('LineOut', APIF_DRAWLINE); AddAPIFunction('CircleOut', APIF_DRAWCIRCLE); AddAPIFunction('RectOut', APIF_DRAWRECT); AddAPIFunction('GraphicOut', APIF_DRAWGRAPHIC); AddAPIFunction('GraphicOutEx', APIF_DRAWGRAPHICEX); AddAPIFunction('StrToNum', APIF_STRTONUM); AddAPIFunction('StrLen', APIF_STRLEN); AddAPIFunction('StrIndex', APIF_STRINDEX); AddAPIStringFunction('NumToStr', APISF_NUMTOSTR); AddAPIStringFunction('StrCat', APISF_STRCAT); AddAPIStringFunction('SubStr', APISF_SUBSTR); AddAPIStringFunction('Flatten', APISF_FLATTEN); AddAPIStringFunction('StrReplace', APISF_STRREPLACE); AddAPIStringFunction('FormatNum', APISF_FORMATNUM); AddAPIFunction('GraphicArrayOut', APIF_DRAWGRAPHICAR); AddAPIFunction('GraphicArrayOutEx', APIF_DRAWGRAPHICAREX); AddAPIFunction('PolyOut', APIF_DRAWPOLY); AddAPIFunction('EllipseOut', APIF_DRAWELLIPSE); AddAPIFunction('FontTextOut', APIF_FONTTEXTOUT); AddAPIFunction('FontNumOut', APIF_FONTNUMOUT); // AddAPIFunction('sizeof', APIF_SIZEOF); end; function TNXCComp.GetNBCSrc: TStrings; begin if AmInlining and Assigned(fCurrentInlineFunction) then Result := fCurrentInlineFunction.Code else Result := fNBCSrc; end; { procedure TNXCComp.EmitInlineFunction(const idx: integer); begin if (idx >= 0) and (idx < fInlineFunctions.Count) then begin fInlineFunctions.Items[idx].Emit(NBCSource); end; end; } procedure TNXCComp.SetDefines(const Value: TStrings); begin fDefines.Assign(Value); end; procedure TNXCComp.CheckTypeCompatibility(fp: TFunctionParameter; dt: char; const name : string); var expectedBase, providedBase : char; begin if GetArrayDimension(fp.ParameterDataType) <> GetArrayDimension(dt) then AbortMsg(sDatatypesNotCompatible) else begin expectedBase := ArrayBaseType(fp.ParameterDataType); providedBase := ArrayBaseType(dt); if (expectedBase in NonAggregateTypes) then begin if not (providedBase in NonAggregateTypes) then Expected(sNumericType) else begin // if parameter type name is a named type then type names must match if (fNamedTypes.IndexOf(fp.ParamTypeName) <> -1) and (fp.ParamTypeName <> DataTypeName(name)) then AbortMsg(sUDTNotEqual); end; end else if (expectedBase = TOK_STRINGDEF) and (providedBase <> TOK_STRINGDEF) then Expected(sStringVarType) else if expectedBase = TOK_USERDEFINEDTYPE then begin if providedBase <> TOK_USERDEFINEDTYPE then Expected(sStructType) else begin // struct types must be the same if fp.ParamTypeName <> GetUDTType(name) then AbortMsg(sUDTNotEqual); end; end else if (expectedBase = TOK_MUTEXDEF) and (providedBase <> TOK_MUTEXDEF) then Expected(sMutexType); end; end; procedure TNXCComp.CheckNotConstant(const aName: string); begin // is this thing constant? if (IsParam(aName) and IsParamConst(aName)) or (IsLocal(aName) and IsLocalConst(aName)) or (IsGlobal(aName) and IsGlobalConst(aName)) then AbortMsg(sConstNotAllowed); end; function TNXCComp.IsStringLiteral(const aName: string) : boolean; begin Result := (Pos('"', aName) = 1) and (LastDelimiter('"', aName) = Length(aName)); end; function TNXCComp.IsCharLiteral(const aName: string) : boolean; begin Result := (Pos('''', aName) = 1) and (LastDelimiter('''', aName) = Length(aName)); end; function TNXCComp.CheckConstant(const aName: string) : string; var bIsConst : boolean; idx : integer; V : TVariable; begin // is this thing constant? Result := aName; if IsParam(aName) then begin bIsConst := IsParamConst(aName); end else if IsLocal(aName) then begin idx := LocalIdx(aName); if idx <> -1 then begin V := fLocals[idx]; bIsConst := V.IsConstant; if bIsConst then Result := V.Value; end else bIsConst := False; end else if IsGlobal(aName) then begin idx := fGlobals.IndexOfName(aName); if idx <> -1 then begin V := fGlobals[idx]; bIsConst := V.IsConstant; if bIsConst then Result := V.Value; end else bIsConst := False; end else if IsStringLiteral(aName) or IsCharLiteral(aName) then begin bIsConst := True; end else begin // perhaps it is a constant expression that can be evaluated? fCalc.SilentExpression := aName; bIsConst := not fCalc.ParserError; if bIsConst then Result := NBCFloatToStr(fCalc.Value); end; if not bIsConst then AbortMsg(sConstRequired); end; function TNXCComp.IncrementOrDecrement: boolean; begin Result := ((Token = '+') and (Look = '+')) or ((Token = '-') and (Look = '-')); end; procedure TNXCComp.DoPreIncOrDec(bPutOnStack : boolean); var bInc : boolean; begin bInc := Token = '+'; Next; Next; CheckIdent; // identifier must be an integer type if not (DataType(Value) in NonAggregateTypes) then Expected(sNumericType); if bInc then StoreInc(Value, 1) else StoreDec(Value, 1); if bPutOnStack then LoadVar(Value); Next; end; function TNXCComp.GetPreProcLexerClass: TGenLexerClass; begin Result := TNXCLexer; end; (* function TNXCComp.InlineDecoration: string; begin // if fInlining then // Result := '%%CALLER%%_' // else Result := ''; end; *) procedure TNXCComp.AddTypeNameAlias(const lbl, args: string); begin // add a named type alias if fNamedTypes.IndexOf(lbl) = -1 then fNamedTypes.AddEntry(lbl, args) else Duplicate(lbl); end; function TNXCComp.TranslateTypeName(const name: string): string; var idx : integer; tname : string; begin Result := name; idx := fNamedTypes.IndexOf(name); if idx <> -1 then begin tname := fNamedTypes.MapValue[idx]; if tname <> name then Result := TranslateTypeName(tname) else Result := tname; end; end; procedure TNXCComp.ProcessEnum(bGlobal : boolean); var bNewType : boolean; sTypeName, varName, eName : string; iEnumVal, idx : integer; dt : Char; V : TVariable; begin // enums in NXC are unsigned bytes by default dt := TOK_BYTEDEF; iEnumVal := 0; bNewType := False; sTypeName := ''; // enum [tag] { enumerators } [declarator]; // eat until semi-colon Next; Scan; // skip past the "enum" keyword // optional type name if Token = TOK_IDENTIFIER then begin bNewType := True; sTypeName := Value; Next; Scan; end; MatchString(TOK_BEGIN); Scan; // process enumerators while Token <> TOK_END do begin // name [= val] , CheckIdent; eName := Value; Next; if Token = '=' then begin Next; // skip past the equal sign to the value CheckNumeric; iEnumVal := StrToIntDef(Value, 0); Next; // skip past the value to comma or } end; dt := ValueToDataType(iEnumVal); V := nil; if bGlobal then begin idx := AddEntry(eName, dt, sTypeName, '', True); if idx <> -1 then V := fGlobals[idx]; Allocate(eName, '', IntToStr(iEnumVal), sTypeName, dt); end else begin eName := ApplyDecoration(fCurrentThreadName, eName, fNestingLevel); idx := AddLocal(eName, dt, sTypeName, True, ''); if idx <> -1 then V := fLocals[idx]; // no need to allocate if we've already emitted this name&type if fEmittedLocals.IndexOf(eName+sTypeName) = -1 then Allocate(eName, '', IntToStr(iEnumVal), sTypeName, dt); end; if Assigned(V) then V.Value := IntToStr(iEnumVal); inc(iEnumVal); if Token <> TOK_END then begin Next; Scan; end; end; // should be at TOK_END MatchString(TOK_END); if bNewType then AddTypeNameAlias(sTypeName, DataTypeToTypeName(dt)); // optional type name if Token = TOK_IDENTIFIER then begin // declare a variable of this type (only valid if bNewType is true if not bNewType then AbortMsg(sInvalidEnumDecl); varName := Value; if bGlobal then begin AddEntry(varName, dt, sTypeName, '', False); Allocate(varName, '', '', sTypeName, dt); end else begin varName := ApplyDecoration(fCurrentThreadName, varName, fNestingLevel); AddLocal(varName, dt, sTypeName, False, ''); // no need to allocate if we've already emitted this name&type if fEmittedLocals.IndexOf(varName+sTypeName) = -1 then Allocate(varName, '', '', sTypeName, dt); end; Next; Scan; // move past identifier end; Semi; // required semicolon Scan; end; procedure TNXCComp.ProcessTypedef; var basetype, newtype : string; i, lb, ln : integer; begin // typedef basetype newtype; // or // typedef struct {...} newtype; // base type can be multiple tokens (e.g., unsigned int) Next; Scan; if Token = TOK_STRUCT then begin ProcessStruct(True); end else begin basetype := ''; while Token <> TOK_SEMICOLON do begin newtype := Value; if Look <> TOK_SEMICOLON then basetype := basetype + ' ' + Value; Next; end; i := Pos(newtype, basetype); lb := Length(basetype); ln := Length(newtype); if i = lb - ln + 1 then System.Delete(basetype, lb - ln + 1, MaxInt); basetype := Trim(basetype); AddTypeNameAlias(newtype, basetype); Semi; Scan; end; end; procedure TNXCComp.LocalEmitLnNoTab(SL : TStrings; const line : string); begin SL.Add(line); end; procedure TNXCComp.LocalEmitLn(SL : TStrings; const line : string); begin SL.Add(#9+line); end; procedure TNXCComp.ProcessStruct(bTypeDef : boolean); var sname, mtype, aval, mname, mtypename, tmp : string; DE : TDataspaceEntry; dt : TDSType; SL : TStringList; i : integer; procedure AddMemberToCurrentStructure; begin // add a member to the current structure definition if mtype = 'string' then begin mtype := 'byte'; aval := '[]' + aval; end; dt := NXCStrToType(mtype, True); if dt = dsCluster then LocalEmitLn(SL, Format('%s %s%s', [mname, mtype, aval])) else LocalEmitLn(SL, Format('%s %s%s', [mname, TypeToStr(dt), aval])); DE := fCurrentStruct.SubEntries.Add; HandleVarDecl(DataDefinitions, fNamedTypes, True, DE, mname, mtype+aval, @NXCStrToType); aval := ''; end; begin // struct name {...}; // or // struct {...} name; (and bTypeDef is true) Next; SL := TStringList.Create; try // create a new structure definition fCurrentStruct := DataDefinitions.Add; fCurrentStruct.DataType := dsCluster; if not bTypeDef then begin sname := Value; AddTypeNameAlias(sname, sname); fCurrentStruct.Identifier := sname; fCurrentStruct.TypeName := sname; Next; // skip past the type name end; if Token = TOK_IDENTIFIER then begin // invalid at this location Expected(TOK_BEGIN); Next; end; MatchString(TOK_BEGIN); while (Token <> TOK_END) and not endofallsource do begin // process a member declaration // format is multi-part typename membername []; // e.g., unsigned int membername // or int membername Scan; mtypename := Value; if Token = TOK_UNSIGNED then begin Next; Scan; mtypename := mtypename + ' ' + Value; end; // make sure we translate typedefs mtype := TranslateTypeName(mtypename); Next; mname := Value; Next; aval := ''; while Token <> TOK_SEMICOLON do begin if Token = '[' then begin aval := ProcessArrayDimensions(tmp); end; if Token = ',' then begin AddMemberToCurrentStructure; Next; mname := Value; Next; end; if not (Token in [TOK_SEMICOLON, '[', ',']) then begin AbortMsg(sUnexpectedChar); Next; end; end; Semi; AddMemberToCurrentStructure; end; Next; // skip past the '}' (aka TOK_END) if bTypeDef then begin sname := Value; AddTypeNameAlias(sname, sname); fCurrentStruct.Identifier := sname; fCurrentStruct.TypeName := sname; Next; // skip past the type name end; // all struct declarations will be emitted to a special stringlist // and then output at the start of the NBC code LocalEmitLnNoTab(fStructDecls, 'dseg segment'); LocalEmitLn(fStructDecls, sname+' struct'); for i := 0 to SL.Count - 1 do LocalEmitLnNoTab(fStructDecls, SL[i]); LocalEmitLn(fStructDecls, sname+' ends'); LocalEmitLnNoTab(fStructDecls, 'dseg ends'); finally SL.Free; end; Semi; // skip past the ';' Scan; end; procedure TNXCComp.CheckForTypedef(var bUnsigned, bConst, bInline, bSafeCall : boolean); var i : integer; tmpName : string; begin tmpName := TranslateTypeName(Value); if Value <> tmpName then begin Token := TOK_IDENTIFIER; Value := tmpName; // only need to check if Value i := Pos('unsigned ', Value); if i > 0 then begin System.Delete(Value, i, 9); bUnsigned := True; end; i := Pos('const ', Value); if i > 0 then begin System.Delete(Value, i, 6); bConst := True; end; i := Pos('inline ', Value); if i > 0 then begin System.Delete(Value, i, 7); bInline := True; end; i := Pos('safecall ', Value); if i > 0 then begin System.Delete(Value, i, 9); bSafeCall := True; end; Value := Trim(Value); end; Scan; end; function TNXCComp.IsUserDefinedType(const name: string): boolean; begin Result := DataDefinitions.IndexOfName(name) <> -1; end; function TNXCComp.RootOf(const name: string): string; var p : integer; begin p := Pos('.', name); if p > 0 then Result := Copy(name, 1, p-1) else Result := name; end; function TNXCComp.DataTypeOfDataspaceEntry(DE: TDataspaceEntry): char; var dim : integer; bt : char; tmpDE : TDataspaceEntry; begin Result := #0; if not Assigned(DE) then Exit; case DE.DataType of dsUByte : Result := TOK_BYTEDEF; dsSByte : Result := TOK_CHARDEF; dsUWord : Result := TOK_USHORTDEF; dsSWord : Result := TOK_SHORTDEF; dsULong : Result := TOK_ULONGDEF; dsSLong : Result := TOK_LONGDEF; dsCluster : Result := TOK_USERDEFINEDTYPE; dsMutex : Result := TOK_MUTEXDEF; dsFloat : Result := TOK_FLOATDEF; dsArray : begin // count dimensions and find base type dim := 1; tmpDE := DE.SubEntries[0]; while tmpDE.DataType = dsArray do begin inc(dim); tmpDE := tmpDE.SubEntries[0]; end; bt := DataTypeOfDataspaceEntry(tmpDE); Result := ArrayOfType(bt, dim); // 2010-05-13 JCH - the code below was causing problems with byte array // types not being seen as compatible with parameters of that type // and not being allowed to use ++ or += since they were seen as a string type // temporarily treat byte[] as string if Result = TOK_ARRAYBYTEDEF then Result := TOK_STRINGDEF; end; else Result := #0; end; end; procedure TNXCComp.UDTAssignment(const name: string); //var // tmp, aval : string; begin if Token in ['+', '-', '/', '*', '%', '&', '|', '^'] then begin MathAssignment(name); // StoreUDT(name, tmp, aval); end else begin MatchString('='); GetAndStoreUDT(name); end; end; procedure TNXCComp.GetAndStoreUDT(const name: string); begin NotNumericFactor; if fUDTOnStack <> '' then begin Store(name); fUDTOnStack := ''; end; end; function TNXCComp.GetUDTType(n: string): string; var i : integer; root_type, root_name : string; DE : TDataspaceEntry; fp : TFunctionParameter; begin Result := ''; n := StripInline(n); case WhatIs(n) of stParam : begin i := ParamIdx(n); if i <> -1 then begin if ArrayBaseType(fParams[i].DataType) = TOK_USERDEFINEDTYPE then begin root_name := RootOf(n); if root_name <> n then begin root_type := fParams[i].TypeName; System.Delete(n, 1, Length(root_name)+1); n := root_type + '.' + n; DE := DataDefinitions.FindEntryByFullName(n); if Assigned(DE) then Result := DE.TypeName; end else Result := fParams[i].TypeName; end; end else begin // i = -1 for i := 0 to fFuncParams.Count - 1 do begin fp := fFuncParams[i]; if n = ApplyDecoration(fp.ProcName, fp.Name, 0) then begin Result := fp.ParamTypeName; Break; end; end; end; end; stLocal : begin i := LocalIdx(n); if (i <> -1) and (ArrayBaseType(fLocals[i].DataType) = TOK_USERDEFINEDTYPE) then // if i = -1 then begin // maybe this is a member of a struct which might itself be a user defined type root_name := RootOf(n); if root_name <> n then begin // i := LocalIdx(root_name); // i := fLocals.IndexOfName(root_name); // if (i <> -1) and (ArrayBaseType(fLocals[i].DataType) = TOK_USERDEFINEDTYPE) then // begin root_type := fLocals[i].TypeName; System.Delete(n, 1, Length(root_name)+1); n := root_type + '.' + n; DE := DataDefinitions.FindEntryByFullName(n); if Assigned(DE) then Result := DE.TypeName; // end; end else Result := fLocals[i].TypeName; end; // else if ArrayBaseType(fLocals[i].DataType) = TOK_USERDEFINEDTYPE then // Result := fLocals[i].TypeName; end; stGlobal : begin i := fGlobals.IndexOfName(n); if i = -1 then begin // maybe this is a member of a struct which might itself be a user defined type root_name := RootOf(n); if root_name <> n then begin i := fGlobals.IndexOfName(root_name); if (i <> -1) and (ArrayBaseType(fGlobals[i].DataType) = TOK_USERDEFINEDTYPE) then begin root_type := fGlobals[i].TypeName; System.Delete(n, 1, Length(root_name)+1); n := root_type + '.' + n; DE := DataDefinitions.FindEntryByFullName(n); if Assigned(DE) then Result := DE.TypeName; end; end; end else if ArrayBaseType(fGlobals[i].DataType) = TOK_USERDEFINEDTYPE then Result := fGlobals[i].TypeName; end; else Result := ''; AbortMsg(sUnknownUDT); end; end; procedure TNXCComp.InitializeArray(const Name, aVal, Val, tname: string; dt: char; lenexpr: string); var tmpVal, expr, tmpType, codeStr : string; idx, n, dim : integer; begin if (lenexpr = '') or (lenexpr = '[]') or (lenexpr = '[][]') or (lenexpr = '[][][]') then Exit; tmpType := tname; if tmpType = 'string' then tmpType := 'byte[]'; // grab the first array expression from lenexpr idx := Pos('[', lenexpr); n := Pos(']', lenexpr); expr := Copy(lenexpr, idx+1, n-idx-1); System.Delete(lenexpr, idx, n-idx+1); // now check dimensions dim := GetArrayDimension(dt); if dim = 1 then begin if ArrayBaseType(dt) in NonAggregateTypes then tmpVal := '0' else begin // create a variable to be used for initializing the array dec(dim); tmpVal := Format('__%s_%d', [Name, dim]); EmitLn('dseg segment'); AllocateHelper(tmpVal, '', '', tmpType, dt); EmitLn('dseg ends'); end; if expr = '' then expr := '1'; codeStr := Format('arrinit %s, %s, %s', [Name, tmpVal, expr]); EmitLn(codeStr); end else begin // recurse if needed dt := RemoveArrayDimension(dt); // define a variable at this new level tmpVal := Format('__%s_%d', [Name, dim]); EmitLn('dseg segment'); AllocateHelper(tmpVal, DataTypeToArrayDimensions(dt), '', tmpType, dt); EmitLn('dseg ends'); InitializeArray(tmpVal, aVal, Val, tname, dt, lenexpr); if expr = '' then expr := '1'; codeStr := Format('arrinit %s, %s, %s', [Name, tmpVal, expr]); EmitLn(codeStr); end; end; procedure TNXCComp.LoadSystemFile(S : TStream); var tmp : string; begin // load fMS with the contents of NBCCommon.h followed by NXCDefs.h tmp := '#line 0 "NXCDefs.h"'#13#10; S.Write(PChar(tmp)^, Length(tmp)); S.Write(nbc_common_data, High(nbc_common_data)+1); S.Write(nxc_defs_data, High(nxc_defs_data)+1); // tmp := Format('#line 0 "%s"'#13#10, [CurrentFile]); tmp := '#reset'#13#10; S.Write(PChar(tmp)^, Length(tmp)); end; procedure TNXCComp.CheckSemicolon; begin if fSemiColonRequired then begin Semi; Scan; end; end; procedure TNXCComp.CloseParen; begin dec(fParenDepth); if fParenDepth < 0 then AbortMsg(sUnmatchedCloseParen); MatchString(TOK_CLOSEPAREN); end; procedure TNXCComp.OpenParen; begin MatchString(TOK_OPENPAREN); inc(fParenDepth); end; procedure TNXCComp.InitializeGraphicOutVars; begin if IgnoreSystemFile then Exit; // do not intialization if we are not including the standard headers if not EnhancedFirmware then EmitLn('arrinit __GraphicOutEmptyVars, 0, 256') else EmitLn('arrinit __GraphicOutEmptyVars, 0, 16'); end; procedure TNXCComp.EmitMutexDeclaration(const name: string); begin EmitLn('dseg segment'); EmitLn(Format(' __%s_mutex mutex', [name])); EmitLn('dseg ends'); end; procedure TNXCComp.EmitInlineParametersAndLocals(func: TInlineFunction); var i : integer; p : TFunctionParameter; v : TVariable; varname, tname : string; dt : char; bConst : boolean; begin for i := 0 to FunctionParameterCount(func.Name) - 1 do begin p := GetFunctionParam(func.Name, i); if Assigned(p) then begin varname := InlineName(fCurrentThreadName, ApplyDecoration(p.ProcName, p.Name, 0)); tname := p.ParamTypeName; dt := p.ParameterDataType; bConst := p.IsConstant; if AmInlining then begin // call AddLocal instead if not IsLocal(varname) then AddLocal(varname, dt, tname, bConst, ''); end else begin // allocate this parameter Allocate(varname, DataTypeToArrayDimensions(dt), '', tname, dt); end; end; end; for i := 0 to func.LocalVariables.Count - 1 do begin v := func.LocalVariables[i]; varname := InlineName(fCurrentThreadName, v.Name); tname := v.TypeName; dt := v.DataType; bConst := v.IsConstant; if AmInlining then begin // call AddLocal instead if not IsLocal(varname) then AddLocal(varname, dt, tname, bConst, ''); end else begin // allocate this variable Allocate(varname, DataTypeToArrayDimensions(dt), '', tname, dt); end; end; end; function TNXCComp.TypesAreCompatible(lhs, rhs: char): boolean; var lDim, rDim : integer; lBase, rBase : Char; begin Result := ((lhs <> TOK_MUTEXDEF) and (rhs <> TOK_MUTEXDEF)) and ((lhs = rhs) or ((lhs in [TOK_ARRAYBYTEDEF, TOK_ARRAYCHARDEF, TOK_STRINGDEF]) and (rhs in [TOK_ARRAYBYTEDEF, TOK_ARRAYCHARDEF, TOK_STRINGDEF])) or ((lhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+1), TOK_ARRAYSTRING]) and (rhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+1), TOK_ARRAYSTRING])) or ((lhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+2), Chr(Ord(TOK_ARRAYSTRING)+1)]) and (rhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+2), Chr(Ord(TOK_ARRAYSTRING)+1)])) or ((lhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+3), Chr(Ord(TOK_ARRAYSTRING)+2)]) and (rhs in [Chr(Ord(TOK_ARRAYBYTEDEF)+3), Chr(Ord(TOK_ARRAYSTRING)+2)])) ); if not Result then begin if IsArrayType(lhs) or IsArrayType(rhs) then begin // dimension counts have to match and base types have to be compatible lDim := GetArrayDimension(lhs); rDim := GetArrayDimension(rhs); Result := lDim = rDim; if Result then begin // also base type compatible lBase := ArrayBaseType(lhs); rBase := ArrayBaseType(rhs); Result := ((lBase in NonAggregateTypes) and (rBase in NonAggregateTypes)) or (lBase = rBase); end; end else begin // neither is an array Result := (lhs in NonAggregateTypes) and (rhs in NonAggregateTypes); end; end; end; procedure TNXCComp.DoFormatNum; var str : string; begin // FormatNum(string, value) OpenParen; // string StringExpression(''); str := StrBufName; MatchString(TOK_COMMA); // value BoolExpression; CloseParen; EmitLn(Format('fmtnum %s, %s, %s', [StrRetValName, str, RegisterName])); end; procedure TNXCComp.DecrementNestingLevel; var i : integer; begin dec(fNestingLevel); // clear any locals defined below the current level // since they have just gone out of scope for i := fLocals.Count - 1 downto 0 do begin if fLocals[i].Level > fNestingLevel then fLocals.Delete(i); end; end; procedure TNXCComp.CheckEnhancedFirmware; begin if not EnhancedFirmware then AbortMsg(sEnhancedFirmwareReqd); end; procedure TNXCComp.InitializeGlobalArrays; begin // all this routine does is emit a call to the global array // initialization subroutine EmitLn('call __initialize_global_data'); end; procedure TNXCComp.EmitGlobalDataInitSubroutine; var i : integer; V : TVariable; aval : string; begin EmitLnNoTab('subroutine __initialize_global_data'); for i := 0 to fGlobals.Count - 1 do begin V := fGlobals[i]; if IsArrayType(V.DataType) then begin if (V.LenExpr <> '') and (V.Value = '') then begin // generate code to initialize this array. aval := DataTypeToArrayDimensions(V.DataType); InitializeArray(V.Name, aval, '', V.TypeName, V.DataType, V.LenExpr); end else if V.Value <> '' then begin DoLocalArrayInit(V.Name, V.Value, V.DataType); end; end // possibly also initialize struct types containing arrays... end; EmitLn('return'); EmitLnNoTab('ends'); end; function StripBraces(str : string) : string; begin Result := Copy(str, 2, Length(str)-2); end; procedure TNXCComp.DoLocalArrayInit(const aName, ival: string; dt: char); var asmstr, {src, }tmp : string; // i : integer; begin // generate an arrbuild asm statement for this array given the initial values asmstr := Format('arrbuild %s', [aName]); tmp := StripBraces(ival); asmstr := asmstr + ', ' + tmp; EmitLn(asmstr); end; function TNXCComp.DoNewArrayIndex(theArrayDT : Char; theArray, aLHSName : string) : boolean; var AHV : TArrayHelperVar; tmp, udType, aval, tmpUDTName, oldExpStr : string; tmpDT : char; begin Result := False; // grab the index as an expression and put it on the stack Next; tmpDT := fLHSDataType; oldExpStr := fExpStr; try fLHSDataType := TOK_LONGDEF; CommaExpression; finally fLHSDataType := tmpDT; fExpStr := oldExpStr; end; if Value <> ']' then Expected(''']'''); push; tmp := tos; EmitLn(Format('mov %s, %s', [tmp, RegisterName])); fArrayIndexStack.Add(tmp); theArrayDT := RemoveArrayDimension(theArrayDT); // check for additional levels of indexing if (Look = '[') and (IsArrayType(theArrayDT) or (theArrayDT = TOK_STRINGDEF)) then begin Next; // move to '[' udType := ''; if IsUDT(ArrayBaseType(theArrayDT)) then udType := GetUDTType(theArray); // get a temporary thread-safe variable of the right type AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, theArrayDT); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, theArrayDT, udType, ''); // set the variable to the specified element from previous array EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(theArray), tmp])); // pass its name into the call to DoNewArrayIndex Result := DoNewArrayIndex(theArrayDT, aval, aLHSName); finally fArrayHelpers.ReleaseHelper(AHV); end; end else begin // no more indexing udType := ''; if IsUDT(ArrayBaseType(theArrayDT)) then udType := GetUDTType(theArray); // get a temporary thread-safe variable of the right type AHV := fArrayHelpers.GetHelper(fCurrentThreadName, udType, theArrayDT); try aval := AHV.Name; if fGlobals.IndexOfName(aval) = -1 then AddEntry(aval, theArrayDT, udType, ''); // set the variable to the specified element from previous array EmitLn(Format('index %s, %s, %s',[aval, GetDecoratedIdent(theArray), tmp])); // check for struct member notation if (Look = '.') and IsUDT(theArrayDT) then begin Next; // move to the dot // process dots tmpUDTName := aval; tmpUDTName := tmpUDTName + Value; // add the dot Next; tmpUDTName := tmpUDTName + Value; // add everything else // set value to full udt name Value := tmpUDTName; end else begin // set value to temporary array name Value := aval; end; Token := TOK_IDENTIFIER; tmpDT := DataType(Value); if (tmpDT in NonAggregateTypes) and (aLHSName = '') then begin Result := True; // i.e., loaded a value on the stack LoadVar(Value); Next; // move to the next token end else if aLHSName <> '' then begin if tmpDT = TOK_STRINGDEF then EmitLn(Format('strcat %s, %s', [aLHSName, GetDecoratedValue])) else if tmpDT in NonAggregateTypes then begin Result := True; // loaded a value onto the stack LoadVar(Value); end else if not IsArrayType(DataType(StripInline(aLHSName))) then EmitLn(Format('mov %s, %s', [GetDecoratedIdent(aLHSName), GetDecoratedValue])) else begin Result := True; // sort of loaded a value onto the stack fUDTOnStack := Value; end; Next; // move to the next token end else begin // recurse to the NumericRelation procedure Result := True; // a numeric relation always puts a value on the stack NumericRelation; end; finally fArrayHelpers.ReleaseHelper(AHV); end; end; pop; end; procedure TNXCComp.SetStatementType(const Value: TStatementType); begin fStatementType := Value; if (Value = stFloat) and (FirmwareVersion < MIN_FW_VER2X) then AbortMsg(sFloatNotSupported); end; procedure TNXCComp.ResetStatementType; begin StatementType := stSigned; end; procedure TNXCComp.EmitNXCRequiredStructs; var SL : TStringList; begin SL := TStringList.Create; try SL.Text := 'TNXCSoundPlayFile struct'#13#10 + ' Result sbyte'#13#10 + ' Filename byte[]'#13#10 + ' Loop byte'#13#10 + ' Volume byte'#13#10 + 'TNXCSoundPlayFile ends'#13#10 + 'TNXCSoundPlayTone struct'#13#10 + ' Result sbyte'#13#10 + ' Frequency word'#13#10 + ' Duration word'#13#10 + ' Loop byte'#13#10 + ' Volume byte'#13#10 + 'TNXCSoundPlayTone ends'#13#10 + 'TNXCSetScreenMode struct'#13#10 + ' Result sbyte'#13#10 + ' ScreenMode dword'#13#10 + 'TNXCSetScreenMode ends'; NBCSource.AddStrings(SL); NBCSource.Add(''); finally SL.Free; end; end; procedure TNXCComp.CheckForMain; var i : integer; V : TVariable; begin for i := 0 to fGlobals.Count - 1 do begin V := fGlobals[i]; if (V.DataType = TOK_TASK) and (V.Name = 'main') then Exit; end; // if we get here we know that main does not exist AbortMsg(sMainTaskNotFound); end; procedure TNXCComp.DoCompilerStatusChange(const Status: string; const bDone : boolean); begin if Assigned(fOnCompilerStatusChange) then fOnCompilerStatusChange(Self, Status, bDone); end; function TNXCComp.AmInlining: boolean; begin // Result := fInlineStack.Count > 0; Result := fInlineDepth > 0; end; procedure TNXCComp.DecrementInlineDepth; begin // remove the dec(fInlineDepth); end; procedure TNXCComp.IncrementInlineDepth; begin inc(fInlineDepth); // fInlineStack.Add(TStringList.Create); end; procedure TNXCComp.HandleSpecialNames; begin if Value = '__TMPBYTE__' then Value := TempSignedByteName else if Value = '__TMPWORD__' then Value := TempSignedWordName else if Value = '__TMPLONG__' then Value := TempSignedLongName else if Value = '__TMPULONG__' then Value := TempUnsignedLongName else if Value = '__TMPFLOAT__' then Value := TempFloatName else if Value = '__RETVAL__' then Value := SignedRegisterName else if Value = '__FLTRETVAL__' then Value := FloatRegisterName else if Value = '__STRRETVAL__' then Value := StrRetValName else if Value = '__GENRETVAL__' then Value := RegisterName else if Value = 'false' then begin Value := '0'; Token := TOK_NUM; end else if Value = 'true' then begin Value := '1'; Token := TOK_NUM; end; end; function TNXCComp.GetValueOf(const name: string): string; begin Result := name; if IsLocalConst(name) then begin Result := LocalConstantValue(name); end { else if IsParamConst(name) then begin Result := ParamConstantValue(name); end; } end; procedure TNXCComp.MoveToCorrectRegister(dt: char); var cReg : string; rst : TStatementType; begin if dt in UnsignedIntegerTypes then begin creg := UnsignedRegisterName; rst := stUnsigned; end else if dt = TOK_FLOATDEF then begin creg := FloatRegisterName; rst := stFloat; end else begin creg := SignedRegisterName; rst := stSigned; end; if rst <> StatementType then EmitLn(Format('mov %s, %s', [creg, RegisterName])); end; procedure TNXCComp.CheckForValidDataType(dt: char); begin // valid data types if not (dt in [TOK_CHARDEF, TOK_SHORTDEF, TOK_LONGDEF, TOK_BYTEDEF, TOK_USHORTDEF, TOK_ULONGDEF, TOK_MUTEXDEF, TOK_FLOATDEF, TOK_STRINGDEF, TOK_USERDEFINEDTYPE..TOK_ARRAYULONGDEF4, TOK_PROCEDURE, TOK_TASK, TOK_LABEL]) then AbortMsg(sUnknownDatatype); end; procedure TNXCComp.HandlePreprocStatusChange(Sender: TObject; const StatusMsg: string); begin DoCompilerStatusChange(StatusMsg); end; procedure TNXCComp.SetCurFile(const Value: string); begin if CurrentFile <> Value then begin fCurFile := Value; DoCompilerStatusChange(Format(sCurrentFile, [Value])); end; end; function TNXCComp.ProcessArrayDimensions(var lenexpr : string) : string; var bDone, bOpen : boolean; begin lenexpr := ''; Result := ''; // declaring an array bDone := False; bOpen := False; while not bDone do begin lenexpr := lenexpr + Value; if Token in ['[', ']'] then Result := Result + Token; if bOpen and (Token = ']') then bOpen := False else if not bOpen and (Token = '[') then bOpen := True else if (bOpen and (Token = '[')) or (not bOpen and (Token = ']')) then AbortMsg(sInvalidArrayDeclaration); Next; if not bOpen and (Token <> '[') then bDone := True; end; end; procedure TNXCComp.CommaStatement(const lend, lstart: string); begin Statement(lend, lstart); if fNoCommaOperator then Exit; // handle comma? if Token = TOK_COMMA then begin Next; // skip past the comma CommaStatement(lend, lstart); end; end; end. NXT/uNBCCommon.pas0000644000175000017500000024667111537752673013614 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNBCCommon; interface uses Parser10, uNXTConstants, Classes, SysUtils; type TLangName = (lnNBC, lnNXC, lnNXCHeader, lnRICScript, lnUnknown); TNBCExpParser = class(TExpParser) private fStandardDefs: boolean; fExtraDefs: boolean; fFirmwareVersion: word; procedure SetStandardDefs(const aValue: boolean); procedure SetExtraDefs(const aValue: boolean); procedure SetFirmwareVersion(const Value: word); public constructor Create(AOwner: TComponent); override; procedure InitializeCalc; property StandardDefines : boolean read fStandardDefs write SetStandardDefs; property ExtraDefines : boolean read fExtraDefs write SetExtraDefs; property FirmwareVersion : word read fFirmwareVersion write SetFirmwareVersion; end; TStatementType = (stUnsigned, stSigned, stFloat); TSymbolType = (stUnknown, stParam, stLocal, stGlobal, stAPIFunc, stAPIStrFunc); TOnCompilerMessage = procedure(const msg : string; var stop : boolean) of object; TFuncParamType = (fptUBYTE, fptSBYTE, fptUWORD, fptSWORD, fptULONG, fptSLONG, fptUDT, fptString, fptMutex, fptFloat); TFunctionParameter = class(TCollectionItem) private fName: string; fProcName: string; fIsReference: boolean; fIsArray: boolean; fIsConstant: boolean; fParamType: TFuncParamType; fParamIndex: integer; fDim: integer; fConstValue : string; fPTName: string; fFuncIsInline: boolean; fHasDefault: boolean; fDefaultValue: string; function GetParamDataType: char; function GetIsConstReference: boolean; function GetIsVarReference: boolean; function GetConstValue: string; procedure SetConstValue(const Value: string); protected procedure AssignTo(Dest: TPersistent); override; public constructor Create(ACollection: TCollection); override; property ProcName : string read fProcName write fProcName; property Name : string read fName write fName; property ParamIndex : integer read fParamIndex write fParamIndex; property ParamType : TFuncParamType read fParamType write fParamType; property ParamTypeName : string read fPTName write fPTName; property IsReference : boolean read fIsReference write fIsReference; property IsConstant : boolean read fIsConstant write fIsConstant; property IsArray : boolean read fIsArray write fIsArray; property ArrayDimension : integer read fDim write fDim; property ParameterDataType : char read GetParamDataType; property IsVarReference : boolean read GetIsVarReference; property IsConstReference : boolean read GetIsConstReference; property ConstantValue : string read GetConstValue write SetConstValue; property FuncIsInline : boolean read fFuncIsInline write fFuncIsInline; property HasDefault : boolean read fHasDefault write fHasDefault; property DefaultValue : string read fDefaultValue write fDefaultValue; end; TFunctionParameters = class(TCollection) private function GetItem(Index: Integer): TFunctionParameter; procedure SetItem(Index: Integer; const Value: TFunctionParameter); public constructor Create; virtual; function Add: TFunctionParameter; function Insert(Index: Integer): TFunctionParameter; property Items[Index: Integer]: TFunctionParameter read GetItem write SetItem; default; function IndexOf(const procname : string; const idx : integer) : integer; overload; function ParamCount(const name : string) : integer; function RequiredParamCount(const name : string) : integer; end; TVariable = class(TCollectionItem) private fIsConst: boolean; fDataType: char; fName: string; fValue: string; fTypeName: string; fLenExpr: string; fUseSafeCall: boolean; fLevel: integer; fHasDef: boolean; fDefValue: string; protected procedure AssignTo(Dest: TPersistent); override; public constructor Create(ACollection: TCollection); override; property Name : string read fName write fName; property DataType : char read fDataType write fDataType; property IsConstant : boolean read fIsConst write fIsConst; property UseSafeCall : boolean read fUseSafeCall write fUseSafeCall; property Value : string read fValue write fValue; property TypeName : string read fTypeName write fTypeName; property LenExpr : string read fLenExpr write fLenExpr; property Level : integer read fLevel write fLevel; property HasDefault : boolean read fHasDef write fHasDef; property DefaultValue : string read fDefValue write fDefValue; end; TVariableList = class(TCollection) private function GetItem(Index: Integer): TVariable; procedure SetItem(Index: Integer; const Value: TVariable); public constructor Create; virtual; function Add: TVariable; function Insert(Index: Integer): TVariable; function IndexOfName(const name : string) : integer; property Items[Index: Integer]: TVariable read GetItem write SetItem; default; end; TInlineFunction = class(TCollectionItem) private fName: string; fCode: TStrings; fEmitCount : integer; fVariables: TVariableList; fCallers: TStrings; fParams: TFunctionParameters; fCurrentCaller: string; procedure SetCode(const Value: TStrings); procedure SetParams(const Value: TFunctionParameters); function GetEndLabel: string; function FixupLabels(const tmpCode : string) : string; public constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure Emit(aStrings : TStrings); property Name : string read fName write fName; property Code : TStrings read fCode write SetCode; property LocalVariables : TVariableList read fVariables; property Callers : TStrings read fCallers; property Parameters : TFunctionParameters read fParams write SetParams; property CurrentCaller : string read fCurrentCaller write fCurrentCaller; property EndLabel : string read GetEndLabel; end; TInlineFunctions = class(TCollection) private function GetItem(Index: Integer): TInlineFunction; procedure SetItem(Index: Integer; const Value: TInlineFunction); public constructor Create; virtual; function Add: TInlineFunction; function Insert(Index: Integer): TInlineFunction; function IndexOfName(const name : string) : integer; property Items[Index: Integer]: TInlineFunction read GetItem write SetItem; default; end; TArrayHelperVar = class(TCollectionItem) private fThreadName: string; fUDType : string; fDataType: char; fIndex : integer; fLocked : boolean; function GetName : string; public constructor Create(ACollection: TCollection); override; property ThreadName : string read fThreadName write fThreadName; property DataType : char read fDataType write fDataType; property UserDefinedType : string read fUDType write fUDType; property Index : integer read fIndex; property Locked : boolean read fLocked; property Name : string read GetName; end; TArrayHelperVars = class(TCollection) private function GetItem(Index: Integer): TArrayHelperVar; procedure SetItem(Index: Integer; const Value: TArrayHelperVar); public constructor Create; virtual; function Add: TArrayHelperVar; function Insert(Index: Integer): TArrayHelperVar; function IndexOfName(const name : string) : integer; function GetHelper(const tname, udType : string; const dt : char) : TArrayHelperVar; procedure ReleaseHelper(aHelper : TArrayHelperVar); property Items[Index: Integer]: TArrayHelperVar read GetItem write SetItem; default; end; const LABEL_PREFIX = '__NXC_Label_'; const STR_NA = 'NA'; STR_TRUE = 'TRUE'; STR_FALSE = 'FALSE'; STR_OUT_A = 'OUT_A'; STR_OUT_B = 'OUT_B'; STR_OUT_C = 'OUT_C'; OUT_A = $00; OUT_B = $01; OUT_C = $02; OUT_AB = $03; OUT_AC = $04; OUT_BC = $05; OUT_ABC = $06; STR_IN_1 = 'IN_1'; STR_IN_2 = 'IN_2'; STR_IN_3 = 'IN_3'; STR_IN_4 = 'IN_4'; IN_1 = $00; IN_2 = $01; IN_3 = $02; IN_4 = $03; STR_IO_BASE = 'IO_BASE'; STR_MOD_INPUT = 'MOD_INPUT'; STR_MOD_OUTPUT = 'MOD_OUTPUT'; STR_IO_IN_FPP = 'IO_IN_FPP'; STR_IO_OUT_FPP = 'IO_OUT_FPP'; IO_BASE = $c000; MOD_INPUT = $0000; MOD_OUTPUT = $0200; IO_IN_FPP = 6; IO_OUT_FPP = 15; type CCEncoding = record Encoding : Byte; Group : Byte; Mode : String; Symbol : String; end; const CCEncodingsCount = 6; CCEncodings : array[0..CCEncodingsCount-1] of CCEncoding = ( ( Encoding: 0; Group: 1; Mode: 'LT' ; Symbol: '<'; ), ( Encoding: 1; Group: 1; Mode: 'GT' ; Symbol: '>'; ), ( Encoding: 2; Group: 1; Mode: 'LTEQ'; Symbol: '<='; ), ( Encoding: 3; Group: 1; Mode: 'GTEQ'; Symbol: '>='; ), ( Encoding: 4; Group: 1; Mode: 'EQ' ; Symbol: '=='; ), ( Encoding: 5; Group: 1; Mode: 'NEQ' ; Symbol: '!='; ) ); type IDRec = record ID : integer; Name : string; end; const UFCount = 8; UFRecords : array[0..UFCount-1] of IDRec = ( ( ID: UF_UPDATE_MODE; Name: 'UF_UPDATE_MODE'; ), ( ID: UF_UPDATE_SPEED; Name: 'UF_UPDATE_SPEED'; ), ( ID: UF_UPDATE_TACHO_LIMIT; Name: 'UF_UPDATE_TACHO_LIMIT'; ), ( ID: UF_UPDATE_RESET_COUNT; Name: 'UF_UPDATE_RESET_COUNT'; ), ( ID: UF_UPDATE_PID_VALUES; Name: 'UF_UPDATE_PID_VALUES'; ), ( ID: UF_UPDATE_RESET_BLOCK_COUNT; Name: 'UF_UPDATE_RESET_BLOCK_COUNT'; ), ( ID: UF_UPDATE_RESET_ROTATION_COUNT; Name: 'UF_UPDATE_RESET_ROTATION_COUNT'; ), ( ID: UF_PENDING_UPDATES; Name: 'UF_PENDING_UPDATES'; ) ); const OutModeCount = 5; OutModeRecords : array[0..OutModeCount-1] of IDRec = ( ( ID: OUT_MODE_COAST; Name: 'OUT_MODE_COAST'; ), ( ID: OUT_MODE_MOTORON; Name: 'OUT_MODE_MOTORON'; ), ( ID: OUT_MODE_BRAKE; Name: 'OUT_MODE_BRAKE'; ), ( ID: OUT_MODE_REGULATED; Name: 'OUT_MODE_REGULATED'; ), ( ID: OUT_MODE_REGMETHOD; Name: 'OUT_MODE_REGMETHOD'; ) ); const OutRunStateCount = 4; OutRunStateRecords : array[0..OutRunStateCount-1] of IDRec = ( ( ID: OUT_RUNSTATE_IDLE; Name: 'OUT_RUNSTATE_IDLE'; ), ( ID: OUT_RUNSTATE_RAMPUP; Name: 'OUT_RUNSTATE_RAMPUP'; ), ( ID: OUT_RUNSTATE_RUNNING; Name: 'OUT_RUNSTATE_RUNNING'; ), ( ID: OUT_RUNSTATE_RAMPDOWN; Name: 'OUT_RUNSTATE_RAMPDOWN'; ) ); const OutRegModeCount = 3; OutRegModeRecords : array[0..OutRegModeCount-1] of IDRec = ( ( ID: OUT_REGMODE_IDLE; Name: 'OUT_REGMODE_IDLE'; ), ( ID: OUT_REGMODE_SPEED; Name: 'OUT_REGMODE_SPEED'; ), ( ID: OUT_REGMODE_SYNC; Name: 'OUT_REGMODE_SYNC'; ) ); const InTypeCount = 18; InTypeRecords : array[0..InTypeCount-1] of IDRec = ( ( ID: IN_TYPE_NO_SENSOR; Name: 'IN_TYPE_NO_SENSOR'; ), ( ID: IN_TYPE_SWITCH; Name: 'IN_TYPE_SWITCH'; ), ( ID: IN_TYPE_TEMPERATURE; Name: 'IN_TYPE_TEMPERATURE'; ), ( ID: IN_TYPE_REFLECTION; Name: 'IN_TYPE_REFLECTION'; ), ( ID: IN_TYPE_ANGLE; Name: 'IN_TYPE_ANGLE'; ), ( ID: IN_TYPE_LIGHT_ACTIVE; Name: 'IN_TYPE_LIGHT_ACTIVE'; ), ( ID: IN_TYPE_LIGHT_INACTIVE; Name: 'IN_TYPE_LIGHT_INACTIVE'; ), ( ID: IN_TYPE_SOUND_DB; Name: 'IN_TYPE_SOUND_DB'; ), ( ID: IN_TYPE_SOUND_DBA; Name: 'IN_TYPE_SOUND_DBA'; ), ( ID: IN_TYPE_CUSTOM; Name: 'IN_TYPE_CUSTOM'; ), ( ID: IN_TYPE_LOWSPEED; Name: 'IN_TYPE_LOWSPEED'; ), ( ID: IN_TYPE_LOWSPEED_9V; Name: 'IN_TYPE_LOWSPEED_9V'; ), ( ID: IN_TYPE_HISPEED; Name: 'IN_TYPE_HISPEED'; ), ( ID: IN_TYPE_COLORFULL; Name: 'IN_TYPE_COLORFULL'; ), ( ID: IN_TYPE_COLORRED; Name: 'IN_TYPE_COLORRED'; ), ( ID: IN_TYPE_COLORGREEN; Name: 'IN_TYPE_COLORGREEN'; ), ( ID: IN_TYPE_COLORBLUE; Name: 'IN_TYPE_COLORBLUE'; ), ( ID: IN_TYPE_COLORNONE; Name: 'IN_TYPE_COLORNONE'; ) ); const InModeCount = 10; InModeRecords : array[0..InModeCount-1] of IDRec = ( ( ID: IN_MODE_RAW; Name: 'IN_MODE_RAW'; ), ( ID: IN_MODE_BOOLEAN; Name: 'IN_MODE_BOOLEAN'; ), ( ID: IN_MODE_TRANSITIONCNT; Name: 'IN_MODE_TRANSITIONCNT'; ), ( ID: IN_MODE_PERIODCOUNTER; Name: 'IN_MODE_PERIODCOUNTER'; ), ( ID: IN_MODE_PCTFULLSCALE; Name: 'IN_MODE_PCTFULLSCALE'; ), ( ID: IN_MODE_CELSIUS; Name: 'IN_MODE_CELSIUS'; ), ( ID: IN_MODE_FAHRENHEIT; Name: 'IN_MODE_FAHRENHEIT'; ), ( ID: IN_MODE_ANGLESTEP; Name: 'IN_MODE_ANGLESTEP'; ), ( ID: IN_MODE_SLOPEMASK; Name: 'IN_MODE_SLOPEMASK'; ), ( ID: IN_MODE_MODEMASK; Name: 'IN_MODE_MODEMASK'; ) ); const OutputFieldIDsCount = 18; NumOutputs = 3; OutputFieldIDs : array[0..OutputFieldIDsCount-1] of IDRec = ( ( ID: UpdateFlags; Name: 'UpdateFlags'; ), ( ID: OutputMode; Name: 'OutputMode'; ), ( ID: Power; Name: 'Power'; ), ( ID: ActualSpeed; Name: 'ActualSpeed'; ), ( ID: TachoCount; Name: 'TachoCount'; ), ( ID: TachoLimit; Name: 'TachoLimit'; ), ( ID: RunState; Name: 'RunState'; ), ( ID: TurnRatio; Name: 'TurnRatio'; ), ( ID: RegMode; Name: 'RegMode'; ), ( ID: Overloaded; Name: 'Overload'; ), ( ID: RegPValue; Name: 'RegPValue'; ), ( ID: RegIValue; Name: 'RegIValue'; ), ( ID: RegDValue; Name: 'RegDValue'; ), ( ID: BlockTachoCount; Name: 'BlockTachoCount'; ), ( ID: RotationCount; Name: 'RotationCount'; ), ( ID: OutputOptions; Name: 'OutputOptions'; ), ( ID: MaxSpeed; Name: 'MaxSpeed'; ), ( ID: MaxAcceleration; Name: 'MaxAcceleration'; ) ); const InputFieldIDsCount = 6; NumInputs = 4; InputFieldIDs : array[0..InputFieldIDsCount-1] of IDRec = ( ( ID: InputType; Name: 'Type'; ), ( ID: InputMode; Name: 'InputMode'; ), ( ID: RawValue; Name: 'RawValue'; ), ( ID: NormalizedValue; Name: 'NormalizedValue'; ), ( ID: ScaledValue; Name: 'ScaledValue'; ), ( ID: InvalidData; Name: 'InvalidData'; ) ); const IOMapFieldIDsCount = (InputFieldIDsCount*NumInputs)+((OutputFieldIDsCount-3)*NumOutputs); IOMapFieldIDs : array[0..IOMapFieldIDsCount-1] of IDRec = ( // input IO Map addresses ( ID: IO_BASE+$000; Name: 'InputIOType0'; ), ( ID: IO_BASE+$001; Name: 'InputIOInputMode0'; ), ( ID: IO_BASE+$002; Name: 'InputIORawValue0'; ), ( ID: IO_BASE+$003; Name: 'InputIONormalizedValue0'; ), ( ID: IO_BASE+$004; Name: 'InputIOScaledValue0'; ), ( ID: IO_BASE+$005; Name: 'InputIOInvalidData0'; ), ( ID: IO_BASE+$006; Name: 'InputIOType1'; ), ( ID: IO_BASE+$007; Name: 'InputIOInputMode1'; ), ( ID: IO_BASE+$008; Name: 'InputIORawValue1'; ), ( ID: IO_BASE+$009; Name: 'InputIONormalizedValue1'; ), ( ID: IO_BASE+$00a; Name: 'InputIOScaledValue1'; ), ( ID: IO_BASE+$00b; Name: 'InputIOInvalidData1'; ), ( ID: IO_BASE+$00c; Name: 'InputIOType2'; ), ( ID: IO_BASE+$00d; Name: 'InputIOInputMode2'; ), ( ID: IO_BASE+$00e; Name: 'InputIORawValue2'; ), ( ID: IO_BASE+$00f; Name: 'InputIONormalizedValue2'; ), ( ID: IO_BASE+$010; Name: 'InputIOScaledValue2'; ), ( ID: IO_BASE+$011; Name: 'InputIOInvalidData2'; ), ( ID: IO_BASE+$012; Name: 'InputIOType3'; ), ( ID: IO_BASE+$013; Name: 'InputIOInputMode3'; ), ( ID: IO_BASE+$014; Name: 'InputIORawValue3'; ), ( ID: IO_BASE+$015; Name: 'InputIONormalizedValue3'; ), ( ID: IO_BASE+$016; Name: 'InputIOScaledValue3'; ), ( ID: IO_BASE+$017; Name: 'InputIOInvalidData3'; ), // output IO Map addresses ( ID: IO_BASE+$200; Name: 'OutputIOUpdateFlags0'; ), ( ID: IO_BASE+$201; Name: 'OutputIOOutputMode0'; ), ( ID: IO_BASE+$202; Name: 'OutputIOPower0'; ), ( ID: IO_BASE+$203; Name: 'OutputIOActualSpeed0'; ), ( ID: IO_BASE+$204; Name: 'OutputIOTachoCount0'; ), ( ID: IO_BASE+$205; Name: 'OutputIOTachoLimit0'; ), ( ID: IO_BASE+$206; Name: 'OutputIORunState0'; ), ( ID: IO_BASE+$207; Name: 'OutputIOTurnRatio0'; ), ( ID: IO_BASE+$208; Name: 'OutputIORegMode0'; ), ( ID: IO_BASE+$209; Name: 'OutputIOOverload0'; ), ( ID: IO_BASE+$20a; Name: 'OutputIORegPValue0'; ), ( ID: IO_BASE+$20b; Name: 'OutputIORegIValue0'; ), ( ID: IO_BASE+$20c; Name: 'OutputIORegDValue0'; ), ( ID: IO_BASE+$20d; Name: 'OutputIOBlockTachoCount0'; ), ( ID: IO_BASE+$20e; Name: 'OutputIORotationCount0'; ), ( ID: IO_BASE+$20f; Name: 'OutputIOUpdateFlags1'; ), ( ID: IO_BASE+$210; Name: 'OutputIOOutputMode1'; ), ( ID: IO_BASE+$211; Name: 'OutputIOPower1'; ), ( ID: IO_BASE+$212; Name: 'OutputIOActualSpeed1'; ), ( ID: IO_BASE+$213; Name: 'OutputIOTachoCount1'; ), ( ID: IO_BASE+$214; Name: 'OutputIOTachoLimit1'; ), ( ID: IO_BASE+$215; Name: 'OutputIORunState1'; ), ( ID: IO_BASE+$216; Name: 'OutputIOTurnRatio1'; ), ( ID: IO_BASE+$217; Name: 'OutputIORegMode1'; ), ( ID: IO_BASE+$218; Name: 'OutputIOOverload1'; ), ( ID: IO_BASE+$219; Name: 'OutputIORegPValue1'; ), ( ID: IO_BASE+$21a; Name: 'OutputIORegIValue1'; ), ( ID: IO_BASE+$21b; Name: 'OutputIORegDValue1'; ), ( ID: IO_BASE+$21c; Name: 'OutputIOBlockTachoCount1'; ), ( ID: IO_BASE+$21d; Name: 'OutputIORotationCount1'; ), ( ID: IO_BASE+$21e; Name: 'OutputIOUpdateFlags2'; ), ( ID: IO_BASE+$21f; Name: 'OutputIOOutputMode2'; ), ( ID: IO_BASE+$220; Name: 'OutputIOPower2'; ), ( ID: IO_BASE+$221; Name: 'OutputIOActualSpeed2'; ), ( ID: IO_BASE+$222; Name: 'OutputIOTachoCount2'; ), ( ID: IO_BASE+$223; Name: 'OutputIOTachoLimit2'; ), ( ID: IO_BASE+$224; Name: 'OutputIORunState2'; ), ( ID: IO_BASE+$225; Name: 'OutputIOTurnRatio2'; ), ( ID: IO_BASE+$226; Name: 'OutputIORegMode2'; ), ( ID: IO_BASE+$227; Name: 'OutputIOOverload2'; ), ( ID: IO_BASE+$228; Name: 'OutputIORegPValue2'; ), ( ID: IO_BASE+$229; Name: 'OutputIORegIValue2'; ), ( ID: IO_BASE+$22a; Name: 'OutputIORegDValue2'; ), ( ID: IO_BASE+$22b; Name: 'OutputIOBlockTachoCount2'; ), ( ID: IO_BASE+$22c; Name: 'OutputIORotationCount2'; ) ); const SysCallMethodIDsCount1x = 48; SysCallMethodIDs1x : array[0..SysCallMethodIDsCount1x-1] of IDRec = ( ( ID: 0; Name: 'FileOpenRead'; ), ( ID: 1; Name: 'FileOpenWrite'; ), ( ID: 2; Name: 'FileOpenAppend'; ), ( ID: 3; Name: 'FileRead'; ), ( ID: 4; Name: 'FileWrite'; ), ( ID: 5; Name: 'FileClose'; ), ( ID: 6; Name: 'FileResolveHandle'; ), ( ID: 7; Name: 'FileRename'; ), ( ID: 8; Name: 'FileDelete'; ), ( ID: 9; Name: 'SoundPlayFile'; ), ( ID: 10; Name: 'SoundPlayTone'; ), ( ID: 11; Name: 'SoundGetState'; ), ( ID: 12; Name: 'SoundSetState'; ), ( ID: 13; Name: 'DrawText'; ), ( ID: 14; Name: 'DrawPoint'; ), ( ID: 15; Name: 'DrawLine'; ), ( ID: 16; Name: 'DrawCircle'; ), ( ID: 17; Name: 'DrawRect'; ), ( ID: 18; Name: 'DrawGraphic'; ), ( ID: 19; Name: 'SetScreenMode'; ), ( ID: 20; Name: 'ReadButton'; ), ( ID: 21; Name: 'CommLSWrite'; ), ( ID: 22; Name: 'CommLSRead'; ), ( ID: 23; Name: 'CommLSCheckStatus'; ), ( ID: 24; Name: 'RandomNumber'; ), ( ID: 25; Name: 'GetStartTick'; ), ( ID: 26; Name: 'MessageWrite'; ), ( ID: 27; Name: 'MessageRead'; ), ( ID: 28; Name: 'CommBTCheckStatus'; ), ( ID: 29; Name: 'CommBTWrite'; ), ( ID: 30; Name: 'CommBTRead'; ), ( ID: 31; Name: 'KeepAlive'; ), ( ID: 32; Name: 'IOMapRead'; ), ( ID: 33; Name: 'IOMapWrite'; ), ( ID: 34; Name: 'IOMapReadByID'; ), ( ID: 35; Name: 'IOMapWriteByID'; ), ( ID: 36; Name: 'DisplayExecuteFunction'; ), ( ID: 37; Name: 'CommExecuteFunction'; ), ( ID: 38; Name: 'LoaderExecuteFunction'; ), ( ID: 39; Name: 'FileFindFirst'; ), ( ID: 40; Name: 'FileFindNext'; ), ( ID: 41; Name: 'FileOpenWriteLinear'; ), ( ID: 42; Name: 'FileOpenWriteNonLinear'; ), ( ID: 43; Name: 'FileOpenReadLinear'; ), ( ID: 44; Name: 'CommHSControl'; ), ( ID: 45; Name: 'CommHSCheckStatus'; ), ( ID: 46; Name: 'CommHSWrite'; ), ( ID: 47; Name: 'CommHSRead'; ) ); const SysCallMethodIDsCount2x = 100; SysCallMethodIDs2x : array[0..SysCallMethodIDsCount2x-1] of IDRec = ( ( ID: 0; Name: 'FileOpenRead'; ), ( ID: 1; Name: 'FileOpenWrite'; ), ( ID: 2; Name: 'FileOpenAppend'; ), ( ID: 3; Name: 'FileRead'; ), ( ID: 4; Name: 'FileWrite'; ), ( ID: 5; Name: 'FileClose'; ), ( ID: 6; Name: 'FileResolveHandle'; ), ( ID: 7; Name: 'FileRename'; ), ( ID: 8; Name: 'FileDelete'; ), ( ID: 9; Name: 'SoundPlayFile'; ), ( ID: 10; Name: 'SoundPlayTone'; ), ( ID: 11; Name: 'SoundGetState'; ), ( ID: 12; Name: 'SoundSetState'; ), ( ID: 13; Name: 'DrawText'; ), ( ID: 14; Name: 'DrawPoint'; ), ( ID: 15; Name: 'DrawLine'; ), ( ID: 16; Name: 'DrawCircle'; ), ( ID: 17; Name: 'DrawRect'; ), ( ID: 18; Name: 'DrawGraphic'; ), ( ID: 19; Name: 'SetScreenMode'; ), ( ID: 20; Name: 'ReadButton'; ), ( ID: 21; Name: 'CommLSWrite'; ), ( ID: 22; Name: 'CommLSRead'; ), ( ID: 23; Name: 'CommLSCheckStatus'; ), ( ID: 24; Name: 'RandomNumber'; ), ( ID: 25; Name: 'GetStartTick'; ), ( ID: 26; Name: 'MessageWrite'; ), ( ID: 27; Name: 'MessageRead'; ), ( ID: 28; Name: 'CommBTCheckStatus'; ), ( ID: 29; Name: 'CommBTWrite'; ), ( ID: 30; Name: 'CommBTRead'; ), ( ID: 31; Name: 'KeepAlive'; ), ( ID: 32; Name: 'IOMapRead'; ), ( ID: 33; Name: 'IOMapWrite'; ), ( ID: 34; Name: 'ColorSensorRead'; ), ( ID: 35; Name: 'CommBTOnOff'; ), ( ID: 36; Name: 'CommBTConnection'; ), ( ID: 37; Name: 'CommHSWrite'; ), ( ID: 38; Name: 'CommHSRead'; ), ( ID: 39; Name: 'CommHSCheckStatus'; ), ( ID: 40; Name: 'ReadSemData'; ), ( ID: 41; Name: 'WriteSemData'; ), ( ID: 42; Name: 'ComputeCalibValue'; ), ( ID: 43; Name: 'UpdateCalibCacheInfo'; ), ( ID: 44; Name: 'DatalogWrite'; ), ( ID: 45; Name: 'DatalogGetTimes'; ), ( ID: 46; Name: 'SetSleepTimeoutVal'; ), ( ID: 47; Name: 'ListFiles'; ), ( ID: 48; Name: 'syscall48'; ), ( ID: 49; Name: 'syscall49'; ), ( ID: 50; Name: 'syscall50'; ), ( ID: 51; Name: 'syscall51'; ), ( ID: 52; Name: 'syscall52'; ), ( ID: 53; Name: 'syscall53'; ), ( ID: 54; Name: 'syscall54'; ), ( ID: 55; Name: 'syscall55'; ), ( ID: 56; Name: 'syscall56'; ), ( ID: 57; Name: 'syscall57'; ), ( ID: 58; Name: 'syscall58'; ), ( ID: 59; Name: 'syscall59'; ), ( ID: 60; Name: 'syscall60'; ), ( ID: 61; Name: 'syscall61'; ), ( ID: 62; Name: 'syscall62'; ), ( ID: 63; Name: 'syscall63'; ), ( ID: 64; Name: 'syscall64'; ), ( ID: 65; Name: 'syscall65'; ), ( ID: 66; Name: 'syscall66'; ), ( ID: 67; Name: 'syscall67'; ), ( ID: 68; Name: 'syscall68'; ), ( ID: 69; Name: 'syscall69'; ), ( ID: 70; Name: 'syscall70'; ), ( ID: 71; Name: 'syscall71'; ), ( ID: 72; Name: 'syscall72'; ), ( ID: 73; Name: 'syscall73'; ), ( ID: 74; Name: 'syscall74'; ), ( ID: 75; Name: 'syscall75'; ), ( ID: 76; Name: 'syscall76'; ), ( ID: 77; Name: 'syscall77'; ), ( ID: 78; Name: 'IOMapReadByID'; ), ( ID: 79; Name: 'IOMapWriteByID'; ), ( ID: 80; Name: 'DisplayExecuteFunction'; ), ( ID: 81; Name: 'CommExecuteFunction'; ), ( ID: 82; Name: 'LoaderExecuteFunction'; ), ( ID: 83; Name: 'FileFindFirst'; ), ( ID: 84; Name: 'FileFindNext'; ), ( ID: 85; Name: 'FileOpenWriteLinear'; ), ( ID: 86; Name: 'FileOpenWriteNonLinear'; ), ( ID: 87; Name: 'FileOpenReadLinear'; ), ( ID: 88; Name: 'CommHSControl'; ), ( ID: 89; Name: 'CommLSWriteEx'; ), ( ID: 90; Name: 'FileSeek'; ), ( ID: 91; Name: 'FileResize'; ), ( ID: 92; Name: 'DrawGraphicArray'; ), ( ID: 93; Name: 'DrawPolygon'; ), ( ID: 94; Name: 'DrawEllipse'; ), ( ID: 95; Name: 'DrawFont'; ), ( ID: 96; Name: 'MemoryManager'; ), ( ID: 97; Name: 'ReadLastResponse'; ), ( ID: 98; Name: 'FileTell'; ), ( ID: 99; Name: 'syscall99'; ) ); const MSCount = 45; MSRecords : array[0..MSCount-1] of IDRec = ( ( ID: 1; Name: 'MS_1'; ), ( ID: 2; Name: 'MS_2'; ), ( ID: 3; Name: 'MS_3'; ), ( ID: 4; Name: 'MS_4'; ), ( ID: 5; Name: 'MS_5'; ), ( ID: 6; Name: 'MS_6'; ), ( ID: 7; Name: 'MS_7'; ), ( ID: 8; Name: 'MS_8'; ), ( ID: 9; Name: 'MS_9'; ), ( ID: 10; Name: 'MS_10'; ), ( ID: 20; Name: 'MS_20'; ), ( ID: 30; Name: 'MS_30'; ), ( ID: 40; Name: 'MS_40'; ), ( ID: 50; Name: 'MS_50'; ), ( ID: 60; Name: 'MS_60'; ), ( ID: 70; Name: 'MS_70'; ), ( ID: 80; Name: 'MS_80'; ), ( ID: 90; Name: 'MS_90'; ), ( ID: 100; Name: 'MS_100'; ), ( ID: 150; Name: 'MS_150'; ), ( ID: 200; Name: 'MS_200'; ), ( ID: 250; Name: 'MS_250'; ), ( ID: 300; Name: 'MS_300'; ), ( ID: 350; Name: 'MS_350'; ), ( ID: 400; Name: 'MS_400'; ), ( ID: 450; Name: 'MS_450'; ), ( ID: 500; Name: 'MS_500'; ), ( ID: 600; Name: 'MS_600'; ), ( ID: 700; Name: 'MS_700'; ), ( ID: 800; Name: 'MS_800'; ), ( ID: 900; Name: 'MS_900'; ), ( ID: 1000; Name: 'SEC_1'; ), ( ID: 2000; Name: 'SEC_2'; ), ( ID: 3000; Name: 'SEC_3'; ), ( ID: 4000; Name: 'SEC_4'; ), ( ID: 5000; Name: 'SEC_5'; ), ( ID: 6000; Name: 'SEC_6'; ), ( ID: 7000; Name: 'SEC_7'; ), ( ID: 8000; Name: 'SEC_8'; ), ( ID: 9000; Name: 'SEC_9'; ), ( ID: 10000; Name: 'SEC_10'; ), ( ID: 15000; Name: 'SEC_15'; ), ( ID: 20000; Name: 'SEC_20'; ), ( ID: 30000; Name: 'SEC_30'; ), ( ID: 60000; Name: 'MIN_1'; ) ); const ToneCount = 60; ToneRecords : array[0..ToneCount-1] of IDRec = ( ( ID: 131; Name: 'TONE_C3'; ), ( ID: 139; Name: 'TONE_CS3'; ), ( ID: 147; Name: 'TONE_D3'; ), ( ID: 156; Name: 'TONE_DS3'; ), ( ID: 165; Name: 'TONE_E3'; ), ( ID: 175; Name: 'TONE_F3'; ), ( ID: 185; Name: 'TONE_FS3'; ), ( ID: 196; Name: 'TONE_G3'; ), ( ID: 208; Name: 'TONE_GS3'; ), ( ID: 220; Name: 'TONE_A3'; ), ( ID: 233; Name: 'TONE_AS3'; ), ( ID: 247; Name: 'TONE_B3'; ), ( ID: 262; Name: 'TONE_C4'; ), ( ID: 277; Name: 'TONE_CS4'; ), ( ID: 294; Name: 'TONE_D4'; ), ( ID: 311; Name: 'TONE_DS4'; ), ( ID: 330; Name: 'TONE_E4'; ), ( ID: 349; Name: 'TONE_F4'; ), ( ID: 370; Name: 'TONE_FS4'; ), ( ID: 392; Name: 'TONE_G4'; ), ( ID: 415; Name: 'TONE_GS4'; ), ( ID: 440; Name: 'TONE_A4'; ), ( ID: 466; Name: 'TONE_AS4'; ), ( ID: 494; Name: 'TONE_B4'; ), ( ID: 523; Name: 'TONE_C5'; ), ( ID: 554; Name: 'TONE_CS5'; ), ( ID: 587; Name: 'TONE_D5'; ), ( ID: 622; Name: 'TONE_DS5'; ), ( ID: 659; Name: 'TONE_E5'; ), ( ID: 698; Name: 'TONE_F5'; ), ( ID: 740; Name: 'TONE_FS5'; ), ( ID: 784; Name: 'TONE_G5'; ), ( ID: 831; Name: 'TONE_GS5'; ), ( ID: 880; Name: 'TONE_A5'; ), ( ID: 932; Name: 'TONE_AS5'; ), ( ID: 988; Name: 'TONE_B5'; ), ( ID: 1047; Name: 'TONE_C6'; ), ( ID: 1109; Name: 'TONE_CS6'; ), ( ID: 1175; Name: 'TONE_D6'; ), ( ID: 1245; Name: 'TONE_DS6'; ), ( ID: 1319; Name: 'TONE_E6'; ), ( ID: 1397; Name: 'TONE_F6'; ), ( ID: 1480; Name: 'TONE_FS6'; ), ( ID: 1568; Name: 'TONE_G6'; ), ( ID: 1661; Name: 'TONE_GS6'; ), ( ID: 1760; Name: 'TONE_A6'; ), ( ID: 1865; Name: 'TONE_AS6'; ), ( ID: 1976; Name: 'TONE_B6'; ), ( ID: 2093; Name: 'TONE_C7'; ), ( ID: 2217; Name: 'TONE_CS7'; ), ( ID: 2349; Name: 'TONE_D7'; ), ( ID: 2489; Name: 'TONE_DS7'; ), ( ID: 2637; Name: 'TONE_E7'; ), ( ID: 2794; Name: 'TONE_F7'; ), ( ID: 2960; Name: 'TONE_FS7'; ), ( ID: 3136; Name: 'TONE_G7'; ), ( ID: 3322; Name: 'TONE_GS7'; ), ( ID: 3520; Name: 'TONE_A7'; ), ( ID: 3729; Name: 'TONE_AS7'; ), ( ID: 3951; Name: 'TONE_B7'; ) ); (* const IOMapOffsetCount = 244; IOMapOffsetRecords : array[0..IOMapOffsetCount-1] of IDRec = ( ( ID: CommandOffsetFormatString; Name: 'CommandOffsetFormatString'; ), ( ID: CommandOffsetPRCHandler; Name: 'CommandOffsetPRCHandler'; ), ( ID: CommandOffsetTick; Name: 'CommandOffsetTick'; ), ( ID: CommandOffsetOffsetDS; Name: 'CommandOffsetOffsetDS'; ), ( ID: CommandOffsetOffsetDVA; Name: 'CommandOffsetOffsetDVA'; ), ( ID: CommandOffsetProgStatus; Name: 'CommandOffsetProgStatus'; ), ( ID: CommandOffsetAwake; Name: 'CommandOffsetAwake'; ), ( ID: CommandOffsetActivateFlag; Name: 'CommandOffsetActivateFlag'; ), ( ID: CommandOffsetDeactivateFlag; Name: 'CommandOffsetDeactivateFlag'; ), ( ID: CommandOffsetFileName; Name: 'CommandOffsetFileName'; ), ( ID: CommandOffsetMemoryPool; Name: 'CommandOffsetMemoryPool'; ), ( ID: IOCtrlOffsetPowerOn; Name: 'IOCtrlOffsetPowerOn'; ), ( ID: LoaderOffsetPFunc; Name: 'LoaderOffsetPFunc'; ), ( ID: LoaderOffsetFreeUserFlash; Name: 'LoaderOffsetFreeUserFlash'; ), ( ID: SoundOffsetFreq; Name: 'SoundOffsetFreq'; ), ( ID: SoundOffsetDuration; Name: 'SoundOffsetDuration'; ), ( ID: SoundOffsetSampleRate; Name: 'SoundOffsetSampleRate'; ), ( ID: SoundOffsetSoundFilename; Name: 'SoundOffsetSoundFilename'; ), ( ID: SoundOffsetFlags; Name: 'SoundOffsetFlags'; ), ( ID: SoundOffsetState; Name: 'SoundOffsetState'; ), ( ID: SoundOffsetMode; Name: 'SoundOffsetMode'; ), ( ID: SoundOffsetVolume; Name: 'SoundOffsetVolume'; ), ( ID: ButtonOffsetPressedCnt0; Name: 'ButtonOffsetPressedCnt0'; ), ( ID: ButtonOffsetLongPressCnt0; Name: 'ButtonOffsetLongPressCnt0'; ), ( ID: ButtonOffsetShortRelCnt0; Name: 'ButtonOffsetShortRelCnt0'; ), ( ID: ButtonOffsetLongRelCnt0; Name: 'ButtonOffsetLongRelCnt0'; ), ( ID: ButtonOffsetRelCnt0; Name: 'ButtonOffsetRelCnt0'; ), ( ID: ButtonOffsetSpareOne0; Name: 'ButtonOffsetSpareOne0'; ), ( ID: ButtonOffsetSpareTwo0; Name: 'ButtonOffsetSpareTwo0'; ), ( ID: ButtonOffsetSpareThree0; Name: 'ButtonOffsetSpareThree0'; ), ( ID: ButtonOffsetPressedCnt1; Name: 'ButtonOffsetPressedCnt1'; ), ( ID: ButtonOffsetLongPressCnt1; Name: 'ButtonOffsetLongPressCnt1'; ), ( ID: ButtonOffsetShortRelCnt1; Name: 'ButtonOffsetShortRelCnt1'; ), ( ID: ButtonOffsetLongRelCnt1; Name: 'ButtonOffsetLongRelCnt1'; ), ( ID: ButtonOffsetRelCnt1; Name: 'ButtonOffsetRelCnt1'; ), ( ID: ButtonOffsetSpareOne1; Name: 'ButtonOffsetSpareOne1'; ), ( ID: ButtonOffsetSpareTwo1; Name: 'ButtonOffsetSpareTwo1'; ), ( ID: ButtonOffsetSpareThree1; Name: 'ButtonOffsetSpareThree1'; ), ( ID: ButtonOffsetPressedCnt2; Name: 'ButtonOffsetPressedCnt2'; ), ( ID: ButtonOffsetLongPressCnt2; Name: 'ButtonOffsetLongPressCnt2'; ), ( ID: ButtonOffsetShortRelCnt2; Name: 'ButtonOffsetShortRelCnt2'; ), ( ID: ButtonOffsetLongRelCnt2; Name: 'ButtonOffsetLongRelCnt2'; ), ( ID: ButtonOffsetRelCnt2; Name: 'ButtonOffsetRelCnt2'; ), ( ID: ButtonOffsetSpareOne2; Name: 'ButtonOffsetSpareOne2'; ), ( ID: ButtonOffsetSpareTwo2; Name: 'ButtonOffsetSpareTwo2'; ), ( ID: ButtonOffsetSpareThree2; Name: 'ButtonOffsetSpareThree2'; ), ( ID: ButtonOffsetPressedCnt3; Name: 'ButtonOffsetPressedCnt3'; ), ( ID: ButtonOffsetLongPressCnt3; Name: 'ButtonOffsetLongPressCnt3'; ), ( ID: ButtonOffsetShortRelCnt3; Name: 'ButtonOffsetShortRelCnt3'; ), ( ID: ButtonOffsetLongRelCnt3; Name: 'ButtonOffsetLongRelCnt3'; ), ( ID: ButtonOffsetRelCnt3; Name: 'ButtonOffsetRelCnt3'; ), ( ID: ButtonOffsetSpareOne3; Name: 'ButtonOffsetSpareOne3'; ), ( ID: ButtonOffsetSpareTwo3; Name: 'ButtonOffsetSpareTwo3'; ), ( ID: ButtonOffsetSpareThree3; Name: 'ButtonOffsetSpareThree3'; ), ( ID: ButtonOffsetState0; Name: 'ButtonOffsetState0'; ), ( ID: ButtonOffsetState1; Name: 'ButtonOffsetState1'; ), ( ID: ButtonOffsetState2; Name: 'ButtonOffsetState2'; ), ( ID: ButtonOffsetState3; Name: 'ButtonOffsetState3'; ), ( ID: UIOffsetPMenu; Name: 'UIOffsetPMenu'; ), ( ID: UIOffsetBatteryVoltage; Name: 'UIOffsetBatteryVoltage'; ), ( ID: UIOffsetLMSfilename; Name: 'UIOffsetLMSfilename'; ), ( ID: UIOffsetFlags; Name: 'UIOffsetFlags'; ), ( ID: UIOffsetState; Name: 'UIOffsetState'; ), ( ID: UIOffsetButton; Name: 'UIOffsetButton'; ), ( ID: UIOffsetRunState; Name: 'UIOffsetRunState'; ), ( ID: UIOffsetBatteryState; Name: 'UIOffsetBatteryState'; ), ( ID: UIOffsetBluetoothState; Name: 'UIOffsetBluetoothState'; ), ( ID: UIOffsetUsbState; Name: 'UIOffsetUsbState'; ), ( ID: UIOffsetSleepTimeout; Name: 'UIOffsetSleepTimeout'; ), ( ID: UIOffsetSleepTimer; Name: 'UIOffsetSleepTimer'; ), ( ID: UIOffsetRechargeable; Name: 'UIOffsetRechargeable'; ), ( ID: UIOffsetVolume; Name: 'UIOffsetVolume'; ), ( ID: UIOffsetError; Name: 'UIOffsetError'; ), ( ID: UIOffsetOBPPointer; Name: 'UIOffsetOBPPointer'; ), ( ID: UIOffsetForceOff; Name: 'UIOffsetForceOff'; ), ( ID: InputOffsetCustomZeroOffset0; Name: 'InputOffsetCustomZeroOffset0'; ), ( ID: InputOffsetADRaw0; Name: 'InputOffsetADRaw0'; ), ( ID: InputOffsetSensorRaw0; Name: 'InputOffsetSensorRaw0'; ), ( ID: InputOffsetSensorValue0; Name: 'InputOffsetSensorValue0'; ), ( ID: InputOffsetSensorType0; Name: 'InputOffsetSensorType0'; ), ( ID: InputOffsetSensorMode0; Name: 'InputOffsetSensorMode0'; ), ( ID: InputOffsetSensorBoolean0; Name: 'InputOffsetSensorBoolean0'; ), ( ID: InputOffsetDigiPinsDir0; Name: 'InputOffsetDigiPinsDir0'; ), ( ID: InputOffsetDigiPinsIn0; Name: 'InputOffsetDigiPinsIn0'; ), ( ID: InputOffsetDigiPinsOut0; Name: 'InputOffsetDigiPinsOut0'; ), ( ID: InputOffsetCustomPctFullScale0; Name: 'InputOffsetCustomPctFullScale0'; ), ( ID: InputOffsetCustomActiveStatus0; Name: 'InputOffsetCustomActiveStatus0'; ), ( ID: InputOffsetInvalidData0; Name: 'InputOffsetInvalidData0'; ), ( ID: InputOffsetSpare10; Name: 'InputOffsetSpare10'; ), ( ID: InputOffsetSpare20; Name: 'InputOffsetSpare20'; ), ( ID: InputOffsetSpare30; Name: 'InputOffsetSpare30'; ), ( ID: InputOffsetCustomZeroOffset1; Name: 'InputOffsetCustomZeroOffset1'; ), ( ID: InputOffsetADRaw1; Name: 'InputOffsetADRaw1'; ), ( ID: InputOffsetSensorRaw1; Name: 'InputOffsetSensorRaw1'; ), ( ID: InputOffsetSensorValue1; Name: 'InputOffsetSensorValue1'; ), ( ID: InputOffsetSensorType1; Name: 'InputOffsetSensorType1'; ), ( ID: InputOffsetSensorMode1; Name: 'InputOffsetSensorMode1'; ), ( ID: InputOffsetSensorBoolean1; Name: 'InputOffsetSensorBoolean1'; ), ( ID: InputOffsetDigiPinsDir1; Name: 'InputOffsetDigiPinsDir1'; ), ( ID: InputOffsetDigiPinsIn1; Name: 'InputOffsetDigiPinsIn1'; ), ( ID: InputOffsetDigiPinsOut1; Name: 'InputOffsetDigiPinsOut1'; ), ( ID: InputOffsetCustomPctFullScale1; Name: 'InputOffsetCustomPctFullScale1'; ), ( ID: InputOffsetCustomActiveStatus1; Name: 'InputOffsetCustomActiveStatus1'; ), ( ID: InputOffsetInvalidData1; Name: 'InputOffsetInvalidData1'; ), ( ID: InputOffsetSpare11; Name: 'InputOffsetSpare11'; ), ( ID: InputOffsetSpare21; Name: 'InputOffsetSpare21'; ), ( ID: InputOffsetSpare31; Name: 'InputOffsetSpare31'; ), ( ID: InputOffsetCustomZeroOffset2; Name: 'InputOffsetCustomZeroOffset2'; ), ( ID: InputOffsetADRaw2; Name: 'InputOffsetADRaw2'; ), ( ID: InputOffsetSensorRaw2; Name: 'InputOffsetSensorRaw2'; ), ( ID: InputOffsetSensorValue2; Name: 'InputOffsetSensorValue2'; ), ( ID: InputOffsetSensorType2; Name: 'InputOffsetSensorType2'; ), ( ID: InputOffsetSensorMode2; Name: 'InputOffsetSensorMode2'; ), ( ID: InputOffsetSensorBoolean2; Name: 'InputOffsetSensorBoolean2'; ), ( ID: InputOffsetDigiPinsDir2; Name: 'InputOffsetDigiPinsDir2'; ), ( ID: InputOffsetDigiPinsIn2; Name: 'InputOffsetDigiPinsIn2'; ), ( ID: InputOffsetDigiPinsOut2; Name: 'InputOffsetDigiPinsOut2'; ), ( ID: InputOffsetCustomPctFullScale2; Name: 'InputOffsetCustomPctFullScale2'; ), ( ID: InputOffsetCustomActiveStatus2; Name: 'InputOffsetCustomActiveStatus2'; ), ( ID: InputOffsetInvalidData2; Name: 'InputOffsetInvalidData2'; ), ( ID: InputOffsetSpare12; Name: 'InputOffsetSpare12'; ), ( ID: InputOffsetSpare22; Name: 'InputOffsetSpare22'; ), ( ID: InputOffsetSpare32; Name: 'InputOffsetSpare32'; ), ( ID: InputOffsetCustomZeroOffset3; Name: 'InputOffsetCustomZeroOffset3'; ), ( ID: InputOffsetADRaw3; Name: 'InputOffsetADRaw3'; ), ( ID: InputOffsetSensorRaw3; Name: 'InputOffsetSensorRaw3'; ), ( ID: InputOffsetSensorValue3; Name: 'InputOffsetSensorValue3'; ), ( ID: InputOffsetSensorType3; Name: 'InputOffsetSensorType3'; ), ( ID: InputOffsetSensorMode3; Name: 'InputOffsetSensorMode3'; ), ( ID: InputOffsetSensorBoolean3; Name: 'InputOffsetSensorBoolean3'; ), ( ID: InputOffsetDigiPinsDir3; Name: 'InputOffsetDigiPinsDir3'; ), ( ID: InputOffsetDigiPinsIn3; Name: 'InputOffsetDigiPinsIn3'; ), ( ID: InputOffsetDigiPinsOut3; Name: 'InputOffsetDigiPinsOut3'; ), ( ID: InputOffsetCustomPctFullScale3; Name: 'InputOffsetCustomPctFullScale3'; ), ( ID: InputOffsetCustomActiveStatus3; Name: 'InputOffsetCustomActiveStatus3'; ), ( ID: InputOffsetInvalidData3; Name: 'InputOffsetInvalidData3'; ), ( ID: InputOffsetSpare13; Name: 'InputOffsetSpare13'; ), ( ID: InputOffsetSpare23; Name: 'InputOffsetSpare23'; ), ( ID: InputOffsetSpare33; Name: 'InputOffsetSpare33'; ), ( ID: OutputOffsetTachoCnt0; Name: 'OutputOffsetTachoCnt0'; ), ( ID: OutputOffsetBlockTachoCount0; Name: 'OutputOffsetBlockTachoCount0'; ), ( ID: OutputOffsetRotationCount0; Name: 'OutputOffsetRotationCount0'; ), ( ID: OutputOffsetTachoLimit0; Name: 'OutputOffsetTachoLimit0'; ), ( ID: OutputOffsetMotorRPM0; Name: 'OutputOffsetMotorRPM0'; ), ( ID: OutputOffsetFlags0; Name: 'OutputOffsetFlags0'; ), ( ID: OutputOffsetMode0; Name: 'OutputOffsetMode0'; ), ( ID: OutputOffsetSpeed0; Name: 'OutputOffsetSpeed0'; ), ( ID: OutputOffsetActualSpeed0; Name: 'OutputOffsetActualSpeed0'; ), ( ID: OutputOffsetRegPParameter0; Name: 'OutputOffsetRegPParameter0'; ), ( ID: OutputOffsetRegIParameter0; Name: 'OutputOffsetRegIParameter0'; ), ( ID: OutputOffsetRegDParameter0; Name: 'OutputOffsetRegDParameter0'; ), ( ID: OutputOffsetRunState0; Name: 'OutputOffsetRunState0'; ), ( ID: OutputOffsetRegMode0; Name: 'OutputOffsetRegMode0'; ), ( ID: OutputOffsetOverloaded0; Name: 'OutputOffsetOverloaded0'; ), ( ID: OutputOffsetSyncTurnParameter0; Name: 'OutputOffsetSyncTurnParameter0'; ), ( ID: OutputOffsetSpareOne0; Name: 'OutputOffsetSpareOne0'; ), ( ID: OutputOffsetSpareTwo0; Name: 'OutputOffsetSpareTwo0'; ), ( ID: OutputOffsetSpareThree0; Name: 'OutputOffsetSpareThree0'; ), ( ID: OutputOffsetTachoCnt1; Name: 'OutputOffsetTachoCnt1'; ), ( ID: OutputOffsetBlockTachoCount1; Name: 'OutputOffsetBlockTachoCount1'; ), ( ID: OutputOffsetRotationCount1; Name: 'OutputOffsetRotationCount1'; ), ( ID: OutputOffsetTachoLimit1; Name: 'OutputOffsetTachoLimit1'; ), ( ID: OutputOffsetMotorRPM1; Name: 'OutputOffsetMotorRPM1'; ), ( ID: OutputOffsetFlags1; Name: 'OutputOffsetFlags1'; ), ( ID: OutputOffsetMode1; Name: 'OutputOffsetMode1'; ), ( ID: OutputOffsetSpeed1; Name: 'OutputOffsetSpeed1'; ), ( ID: OutputOffsetActualSpeed1; Name: 'OutputOffsetActualSpeed1'; ), ( ID: OutputOffsetRegPParameter1; Name: 'OutputOffsetRegPParameter1'; ), ( ID: OutputOffsetRegIParameter1; Name: 'OutputOffsetRegIParameter1'; ), ( ID: OutputOffsetRegDParameter1; Name: 'OutputOffsetRegDParameter1'; ), ( ID: OutputOffsetRunState1; Name: 'OutputOffsetRunState1'; ), ( ID: OutputOffsetRegMode1; Name: 'OutputOffsetRegMode1'; ), ( ID: OutputOffsetOverloaded1; Name: 'OutputOffsetOverloaded1'; ), ( ID: OutputOffsetSyncTurnParameter1; Name: 'OutputOffsetSyncTurnParameter1'; ), ( ID: OutputOffsetSpareOne1; Name: 'OutputOffsetSpareOne1'; ), ( ID: OutputOffsetSpareTwo1; Name: 'OutputOffsetSpareTwo1'; ), ( ID: OutputOffsetSpareThree1; Name: 'OutputOffsetSpareThree1'; ), ( ID: OutputOffsetTachoCnt2; Name: 'OutputOffsetTachoCnt2'; ), ( ID: OutputOffsetBlockTachoCount2; Name: 'OutputOffsetBlockTachoCount2'; ), ( ID: OutputOffsetRotationCount2; Name: 'OutputOffsetRotationCount2'; ), ( ID: OutputOffsetTachoLimit2; Name: 'OutputOffsetTachoLimit2'; ), ( ID: OutputOffsetMotorRPM2; Name: 'OutputOffsetMotorRPM2'; ), ( ID: OutputOffsetFlags2; Name: 'OutputOffsetFlags2'; ), ( ID: OutputOffsetMode2; Name: 'OutputOffsetMode2'; ), ( ID: OutputOffsetSpeed2; Name: 'OutputOffsetSpeed2'; ), ( ID: OutputOffsetActualSpeed2; Name: 'OutputOffsetActualSpeed2'; ), ( ID: OutputOffsetRegPParameter2; Name: 'OutputOffsetRegPParameter2'; ), ( ID: OutputOffsetRegIParameter2; Name: 'OutputOffsetRegIParameter2'; ), ( ID: OutputOffsetRegDParameter2; Name: 'OutputOffsetRegDParameter2'; ), ( ID: OutputOffsetRunState2; Name: 'OutputOffsetRunState2'; ), ( ID: OutputOffsetRegMode2; Name: 'OutputOffsetRegMode2'; ), ( ID: OutputOffsetOverloaded2; Name: 'OutputOffsetOverloaded2'; ), ( ID: OutputOffsetSyncTurnParameter2; Name: 'OutputOffsetSyncTurnParameter2'; ), ( ID: OutputOffsetSpareOne2; Name: 'OutputOffsetSpareOne2'; ), ( ID: OutputOffsetSpareTwo2; Name: 'OutputOffsetSpareTwo2'; ), ( ID: OutputOffsetSpareThree2; Name: 'OutputOffsetSpareThree2'; ), ( ID: OutputOffsetPwnFreq; Name: 'OutputOffsetPwnFreq'; ), ( ID: LowSpeedOffsetInBufBuf0; Name: 'LowSpeedOffsetInBufBuf0'; ), ( ID: LowSpeedOffsetInBufInPtr0; Name: 'LowSpeedOffsetInBufInPtr0'; ), ( ID: LowSpeedOffsetInBufOutPtr0; Name: 'LowSpeedOffsetInBufOutPtr0'; ), ( ID: LowSpeedOffsetInBufBytesToRx0; Name: 'LowSpeedOffsetInBufBytesToRx0'; ), ( ID: LowSpeedOffsetInBufBuf1; Name: 'LowSpeedOffsetInBufBuf1'; ), ( ID: LowSpeedOffsetInBufInPtr1; Name: 'LowSpeedOffsetInBufInPtr1'; ), ( ID: LowSpeedOffsetInBufOutPtr1; Name: 'LowSpeedOffsetInBufOutPtr1'; ), ( ID: LowSpeedOffsetInBufBytesToRx1; Name: 'LowSpeedOffsetInBufBytesToRx1'; ), ( ID: LowSpeedOffsetInBufBuf2; Name: 'LowSpeedOffsetInBufBuf2'; ), ( ID: LowSpeedOffsetInBufInPtr2; Name: 'LowSpeedOffsetInBufInPtr2'; ), ( ID: LowSpeedOffsetInBufOutPtr2; Name: 'LowSpeedOffsetInBufOutPtr2'; ), ( ID: LowSpeedOffsetInBufBytesToRx2; Name: 'LowSpeedOffsetInBufBytesToRx2'; ), ( ID: LowSpeedOffsetInBufBuf3; Name: 'LowSpeedOffsetInBufBuf3'; ), ( ID: LowSpeedOffsetInBufInPtr3; Name: 'LowSpeedOffsetInBufInPtr3'; ), ( ID: LowSpeedOffsetInBufOutPtr3; Name: 'LowSpeedOffsetInBufOutPtr3'; ), ( ID: LowSpeedOffsetInBufBytesToRx3; Name: 'LowSpeedOffsetInBufBytesToRx3'; ), ( ID: LowSpeedOffsetOutBufBuf0; Name: 'LowSpeedOffsetOutBufBuf0'; ), ( ID: LowSpeedOffsetOutBufInPtr0; Name: 'LowSpeedOffsetOutBufInPtr0'; ), ( ID: LowSpeedOffsetOutBufOutPtr0; Name: 'LowSpeedOffsetOutBufOutPtr0'; ), ( ID: LowSpeedOffsetOutBufBytesToRx0; Name: 'LowSpeedOffsetOutBufBytesToRx0'; ), ( ID: LowSpeedOffsetOutBufBuf1; Name: 'LowSpeedOffsetOutBufBuf1'; ), ( ID: LowSpeedOffsetOutBufInPtr1; Name: 'LowSpeedOffsetOutBufInPtr1'; ), ( ID: LowSpeedOffsetOutBufOutPtr1; Name: 'LowSpeedOffsetOutBufOutPtr1'; ), ( ID: LowSpeedOffsetOutBufBytesToRx1; Name: 'LowSpeedOffsetOutBufBytesToRx1'; ), ( ID: LowSpeedOffsetOutBufBuf2; Name: 'LowSpeedOffsetOutBufBuf2'; ), ( ID: LowSpeedOffsetOutBufInPtr2; Name: 'LowSpeedOffsetOutBufInPtr2'; ), ( ID: LowSpeedOffsetOutBufOutPtr2; Name: 'LowSpeedOffsetOutBufOutPtr2'; ), ( ID: LowSpeedOffsetOutBufBytesToRx2; Name: 'LowSpeedOffsetOutBufBytesToRx2'; ), ( ID: LowSpeedOffsetOutBufBuf3; Name: 'LowSpeedOffsetOutBufBuf3'; ), ( ID: LowSpeedOffsetOutBufInPtr3; Name: 'LowSpeedOffsetOutBufInPtr3'; ), ( ID: LowSpeedOffsetOutBufOutPtr3; Name: 'LowSpeedOffsetOutBufOutPtr3'; ), ( ID: LowSpeedOffsetOutBufBytesToRx3; Name: 'LowSpeedOffsetOutBufBytesToRx3'; ), ( ID: LowSpeedOffsetMode0; Name: 'LowSpeedOffsetMode0'; ), ( ID: LowSpeedOffsetMode1; Name: 'LowSpeedOffsetMode1'; ), ( ID: LowSpeedOffsetMode2; Name: 'LowSpeedOffsetMode2'; ), ( ID: LowSpeedOffsetMode3; Name: 'LowSpeedOffsetMode3'; ), ( ID: LowSpeedOffsetChannelState0; Name: 'LowSpeedOffsetChannelState0'; ), ( ID: LowSpeedOffsetChannelState1; Name: 'LowSpeedOffsetChannelState1'; ), ( ID: LowSpeedOffsetChannelState2; Name: 'LowSpeedOffsetChannelState2'; ), ( ID: LowSpeedOffsetChannelState3; Name: 'LowSpeedOffsetChannelState3'; ), ( ID: LowSpeedOffsetErrorType0; Name: 'LowSpeedOffsetErrorType0'; ), ( ID: LowSpeedOffsetErrorType1; Name: 'LowSpeedOffsetErrorType1'; ), ( ID: LowSpeedOffsetErrorType2; Name: 'LowSpeedOffsetErrorType2'; ), ( ID: LowSpeedOffsetErrorType3; Name: 'LowSpeedOffsetErrorType3'; ), ( ID: LowSpeedOffsetState; Name: 'LowSpeedOffsetState'; ), ( ID: LowSpeedOffsetSpeed; Name: 'LowSpeedOffsetSpeed'; ), ( ID: LowSpeedOffsetSpare1; Name: 'LowSpeedOffsetSpare1'; ) ); *) // miscellaneous IOMap-related constants const INPUT_DIGI0 = $1; INPUT_DIGI1 = $2; INPUT_CUSTOMINACTIVE = $00; INPUT_CUSTOM9V = $01; INPUT_CUSTOMACTIVE = $02; INPUT_INVALID_DATA = $01; BTN1 = $0; BTN2 = $1; BTN3 = $2; BTN4 = $3; NO_OF_BTNS = $4; BTNSTATE_PRESSED_EV = $01; BTNSTATE_SHORT_RELEASED_EV = $02; BTNSTATE_LONG_PRESSED_EV = $04; BTNSTATE_LONG_RELEASED_EV = $08; BTNSTATE_PRESSED_STATE = $80; SOUND_FLAGS_UPDATE = $01; SOUND_FLAGS_RUNNING = $02; SOUND_STATE_IDLE = $00; SOUND_STATE_BUSY = $02; SOUND_STATE_FREQ = $03; SOUND_STATE_STOP = $04; SOUND_MODE_ONCE = $00; SOUND_MODE_LOOP = $01; SOUND_MODE_TONE = $02; UI_FLAGS_UPDATE = $01; UI_FLAGS_DISABLE_LEFT_RIGHT_ENTER = $02; UI_FLAGS_DISABLE_EXIT = $04; UI_FLAGS_REDRAW_STATUS = $08; UI_FLAGS_RESET_SLEEP_TIMER = $10; UI_FLAGS_EXECUTE_LMS_FILE = $20; UI_FLAGS_BUSY = $40; UI_FLAGS_ENABLE_STATUS_UPDATE = $80; UI_STATE_INIT_DISPLAY = $0; UI_STATE_INIT_LOW_BATTERY = $1; UI_STATE_INIT_INTRO = $2; UI_STATE_INIT_WAIT = $3; UI_STATE_INIT_MENU = $4; UI_STATE_NEXT_MENU = $5; UI_STATE_DRAW_MENU = $6; UI_STATE_TEST_BUTTONS = $7; UI_STATE_LEFT_PRESSED = $8; UI_STATE_RIGHT_PRESSED = $9; UI_STATE_ENTER_PRESSED = $0a; UI_STATE_EXIT_PRESSED = $0b; UI_STATE_CONNECT_REQUEST = $0c; UI_STATE_EXECUTE_FILE = $0d; UI_STATE_EXECUTING_FILE = $0e; UI_STATE_LOW_BATTERY = $0f; UI_STATE_BT_ERROR = $10; UI_BUTTON_NONE = $1; UI_BUTTON_LEFT = $2; UI_BUTTON_ENTER = $3; UI_BUTTON_RIGHT = $4; UI_BUTTON_EXIT = $5; UI_BT_STATE_VISIBLE = $01; UI_BT_STATE_CONNECTED = $02; UI_BT_STATE_OFF = $04; UI_BT_ERROR_ATTENTION = $08; UI_BT_CONNECT_REQUEST = $40; UI_BT_PIN_REQUEST = $80; LS_DEVTYPE_ULTRA_SONIC = $2; LS_DEVTYPE_CUSTOM_LS_DEVICE = $3; COM_CHANNEL_NONE_ACTIVE = $00; COM_CHANNEL_ONE_ACTIVE = $01; COM_CHANNEL_TWO_ACTIVE = $02; COM_CHANNEL_THREE_ACTIVE = $04; COM_CHANNEL_FOUR_ACTIVE = $08; LOWSPEED_IDLE = $0; LOWSPEED_INIT = $1; LOWSPEED_LOAD_BUFFER = $2; LOWSPEED_COMMUNICATING = $3; LOWSPEED_ERROR = $4; LOWSPEED_DONE = $5; LOWSPEED_TRANSMITTING = $1; LOWSPEED_RECEIVING = $2; LOWSPEED_DATA_RECEIVED = $3; LOWSPEED_NO_ERROR = $0; LOWSPEED_CH_NOT_READY = $1; LOWSPEED_TX_ERROR = $2; LOWSPEED_RX_ERROR = $3; (* IOMapMiscCount = 81; IOMapMiscRecords : array[0..IOMapMiscCount-1] of IDRec = ( ( ID: INPUT_DIGI0; Name: 'INPUT_DIGI0'; ), ( ID: INPUT_DIGI1; Name: 'INPUT_DIGI1'; ), ( ID: INPUT_CUSTOMINACTIVE; Name: 'INPUT_CUSTOMINACTIVE'; ), ( ID: INPUT_CUSTOM9V; Name: 'INPUT_CUSTOM9V'; ), ( ID: INPUT_CUSTOMACTIVE; Name: 'INPUT_CUSTOMACTIVE'; ), ( ID: INPUT_INVALID_DATA; Name: 'INPUT_INVALID_DATA'; ), ( ID: BTN1 ; Name: 'BTN1'; ), ( ID: BTN2 ; Name: 'BTN2'; ), ( ID: BTN3 ; Name: 'BTN3'; ), ( ID: BTN4 ; Name: 'BTN4'; ), ( ID: NO_OF_BTNS ; Name: 'NO_OF_BTNS'; ), ( ID: BTNSTATE_PRESSED_EV ; Name: 'BTNSTATE_PRESSED_EV'; ), ( ID: BTNSTATE_SHORT_RELEASED_EV ; Name: 'BTNSTATE_SHORT_RELEASED_EV'; ), ( ID: BTNSTATE_LONG_PRESSED_EV ; Name: 'BTNSTATE_LONG_PRESSED_EV'; ), ( ID: BTNSTATE_LONG_RELEASED_EV ; Name: 'BTNSTATE_LONG_RELEASED_EV'; ), ( ID: BTNSTATE_PRESSED_STATE ; Name: 'BTNSTATE_PRESSED_STATE'; ), ( ID: SOUND_FLAGS_UPDATE ; Name: 'SOUND_FLAGS_UPDATE'; ), ( ID: SOUND_FLAGS_RUNNING ; Name: 'SOUND_FLAGS_RUNNING'; ), ( ID: SOUND_STATE_IDLE ; Name: 'SOUND_STATE_IDLE'; ), ( ID: SOUND_STATE_BUSY ; Name: 'SOUND_STATE_BUSY'; ), ( ID: SOUND_STATE_FREQ ; Name: 'SOUND_STATE_FREQ'; ), ( ID: SOUND_STATE_STOP ; Name: 'SOUND_STATE_STOP'; ), ( ID: SOUND_MODE_ONCE ; Name: 'SOUND_MODE_ONCE'; ), ( ID: SOUND_MODE_LOOP ; Name: 'SOUND_MODE_LOOP'; ), ( ID: SOUND_MODE_TONE ; Name: 'SOUND_MODE_TONE'; ), ( ID: UI_FLAGS_UPDATE ; Name: 'UI_FLAGS_UPDATE'; ), ( ID: UI_FLAGS_DISABLE_LEFT_RIGHT_ENTER ; Name: 'UI_FLAGS_DISABLE_LEFT_RIGHT_ENTER'; ), ( ID: UI_FLAGS_DISABLE_EXIT ; Name: 'UI_FLAGS_DISABLE_EXIT'; ), ( ID: UI_FLAGS_REDRAW_STATUS ; Name: 'UI_FLAGS_REDRAW_STATUS'; ), ( ID: UI_FLAGS_RESET_SLEEP_TIMER ; Name: 'UI_FLAGS_RESET_SLEEP_TIMER'; ), ( ID: UI_FLAGS_EXECUTE_LMS_FILE ; Name: 'UI_FLAGS_EXECUTE_LMS_FILE'; ), ( ID: UI_FLAGS_BUSY ; Name: 'UI_FLAGS_BUSY'; ), ( ID: UI_FLAGS_ENABLE_STATUS_UPDATE ; Name: 'UI_FLAGS_ENABLE_STATUS_UPDATE'; ), ( ID: UI_STATE_INIT_DISPLAY ; Name: 'UI_STATE_INIT_DISPLAY'; ), ( ID: UI_STATE_INIT_LOW_BATTERY ; Name: 'UI_STATE_INIT_LOW_BATTERY'; ), ( ID: UI_STATE_INIT_INTRO ; Name: 'UI_STATE_INIT_INTRO'; ), ( ID: UI_STATE_INIT_WAIT ; Name: 'UI_STATE_INIT_WAIT'; ), ( ID: UI_STATE_INIT_MENU ; Name: 'UI_STATE_INIT_MENU'; ), ( ID: UI_STATE_NEXT_MENU ; Name: 'UI_STATE_NEXT_MENU'; ), ( ID: UI_STATE_DRAW_MENU ; Name: 'UI_STATE_DRAW_MENU'; ), ( ID: UI_STATE_TEST_BUTTONS ; Name: 'UI_STATE_TEST_BUTTONS'; ), ( ID: UI_STATE_LEFT_PRESSED ; Name: 'UI_STATE_LEFT_PRESSED'; ), ( ID: UI_STATE_RIGHT_PRESSED ; Name: 'UI_STATE_RIGHT_PRESSED'; ), ( ID: UI_STATE_ENTER_PRESSED ; Name: 'UI_STATE_ENTER_PRESSED'; ), ( ID: UI_STATE_EXIT_PRESSED ; Name: 'UI_STATE_EXIT_PRESSED'; ), ( ID: UI_STATE_CONNECT_REQUEST ; Name: 'UI_STATE_CONNECT_REQUEST'; ), ( ID: UI_STATE_EXECUTE_FILE ; Name: 'UI_STATE_EXECUTE_FILE'; ), ( ID: UI_STATE_EXECUTING_FILE ; Name: 'UI_STATE_EXECUTING_FILE'; ), ( ID: UI_STATE_LOW_BATTERY ; Name: 'UI_STATE_LOW_BATTERY'; ), ( ID: UI_STATE_BT_ERROR ; Name: 'UI_STATE_BT_ERROR'; ), ( ID: UI_BUTTON_NONE ; Name: 'UI_BUTTON_NONE'; ), ( ID: UI_BUTTON_LEFT ; Name: 'UI_BUTTON_LEFT'; ), ( ID: UI_BUTTON_ENTER ; Name: 'UI_BUTTON_ENTER'; ), ( ID: UI_BUTTON_RIGHT ; Name: 'UI_BUTTON_RIGHT'; ), ( ID: UI_BUTTON_EXIT ; Name: 'UI_BUTTON_EXIT'; ), ( ID: UI_BT_STATE_VISIBLE ; Name: 'UI_BT_STATE_VISIBLE'; ), ( ID: UI_BT_STATE_CONNECTED ; Name: 'UI_BT_STATE_CONNECTED'; ), ( ID: UI_BT_STATE_OFF ; Name: 'UI_BT_STATE_OFF'; ), ( ID: UI_BT_ERROR_ATTENTION ; Name: 'UI_BT_ERROR_ATTENTION'; ), ( ID: UI_BT_CONNECT_REQUEST ; Name: 'UI_BT_CONNECT_REQUEST'; ), ( ID: UI_BT_PIN_REQUEST ; Name: 'UI_BT_PIN_REQUEST'; ), ( ID: LS_DEVTYPE_ULTRA_SONIC ; Name: 'LS_DEVTYPE_ULTRA_SONIC'; ), ( ID: LS_DEVTYPE_CUSTOM_LS_DEVICE ; Name: 'LS_DEVTYPE_CUSTOM_LS_DEVICE'; ), ( ID: COM_CHANNEL_NONE_ACTIVE ; Name: 'COM_CHANNEL_NONE_ACTIVE'; ), ( ID: COM_CHANNEL_ONE_ACTIVE ; Name: 'COM_CHANNEL_ONE_ACTIVE'; ), ( ID: COM_CHANNEL_TWO_ACTIVE ; Name: 'COM_CHANNEL_TWO_ACTIVE'; ), ( ID: COM_CHANNEL_THREE_ACTIVE ; Name: 'COM_CHANNEL_THREE_ACTIVE'; ), ( ID: COM_CHANNEL_FOUR_ACTIVE ; Name: 'COM_CHANNEL_FOUR_ACTIVE'; ), ( ID: LOWSPEED_IDLE ; Name: 'LOWSPEED_IDLE'; ), ( ID: LOWSPEED_INIT ; Name: 'LOWSPEED_INIT'; ), ( ID: LOWSPEED_LOAD_BUFFER ; Name: 'LOWSPEED_LOAD_BUFFER'; ), ( ID: LOWSPEED_COMMUNICATING ; Name: 'LOWSPEED_COMMUNICATING'; ), ( ID: LOWSPEED_ERROR ; Name: 'LOWSPEED_ERROR'; ), ( ID: LOWSPEED_DONE ; Name: 'LOWSPEED_DONE'; ), ( ID: LOWSPEED_TRANSMITTING ; Name: 'LOWSPEED_TRANSMITTING'; ), ( ID: LOWSPEED_RECEIVING ; Name: 'LOWSPEED_RECEIVING'; ), ( ID: LOWSPEED_DATA_RECEIVED ; Name: 'LOWSPEED_DATA_RECEIVED'; ), ( ID: LOWSPEED_NO_ERROR ; Name: 'LOWSPEED_NO_ERROR'; ), ( ID: LOWSPEED_CH_NOT_READY ; Name: 'LOWSPEED_CH_NOT_READY'; ), ( ID: LOWSPEED_TX_ERROR ; Name: 'LOWSPEED_TX_ERROR'; ), ( ID: LOWSPEED_RX_ERROR ; Name: 'LOWSPEED_RX_ERROR'; ) ); *) function IsAlpha(c: char): boolean; function IsCharWhiteSpace(C: Char): Boolean; function StrContains(const SubStr, Str: string): Boolean; function InlineName(const tname, name: string): string; function StripInline(const name: string): string; function InlineThreadName(const name: string): string; function IsInlined(const name: string) : boolean; function StripAllInlineDecoration(const name: string): string; function StripDecoration(const name : string) : string; function PrettyNameStrip(const name : string) : string; function ApplyDecoration(const pre, val: string; const level : integer): string; function Replace(const str : string; const src, rep : string) : string; function NBCStrToFloat(const AValue: string): Double; function NBCStrToFloatDef(const AValue: string; const aDef : Double): Double; function NBCTextToFloat(Buffer: PChar; var Value; ValueType: TFloatValue): Boolean; function NBCFormat(const FmtStr: string; const theArgs: array of const) : string; function NBCFloatToStr(const AValue: Double): string; function StripQuotes(const str : string) : string; function JCHExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer; function ValueToDataType(const value : integer) : char; function DataTypeToTypeName(const dt : char) : string; function BoolToString(aValue : boolean) : string; const TOK_SEMICOLON = ';'; TOK_OPENPAREN = '('; TOK_CLOSEPAREN = ')'; TOK_COMMA = ','; TOK_IDENTIFIER = 'x'; TOK_IF = 'i'; TOK_ELSE = 'l'; TOK_DO = 'd'; TOK_ASM = 'a'; TOK_REPEAT = 'r'; TOK_SWITCH = 's'; TOK_DEFAULT = 'D'; TOK_CASE = 'c'; TOK_WHILE = 'w'; TOK_FOR = 'f'; TOK_ENUM = 'm'; TOK_END = '}'; TOK_APISTRFUNC = 'E'; TOK_APIFUNC = 'F'; TOK_PROCEDURE = 'R'; TOK_TASK = 'K'; TOK_BEGIN = '{'; TOK_DIRECTIVE = '#'; TOK_API = 'Z'; TOK_LABEL = 'B'; TOK_TYPEDEF = 't'; TOK_STRUCT = 'T'; TOK_CONST = 'k'; TOK_INLINE = 'n'; TOK_START = 'A'; TOK_STOP = 'X'; TOK_PRIORITY = 'p'; TOK_NUM = 'N'; TOK_HEX = 'H'; TOK_UNSIGNED = 'U'; TOK_CHARDEF = 'C'; TOK_SHORTDEF = 'I'; TOK_LONGDEF = 'L'; TOK_BYTEDEF = 'b'; TOK_USHORTDEF = #06; TOK_ULONGDEF = #05; TOK_MUTEXDEF = 'M'; TOK_FLOATDEF = 'O'; TOK_STRINGDEF = 'S'; TOK_STRINGLIT = 'G'; TOK_SAFECALL = #218; TOK_USERDEFINEDTYPE = #219; TOK_ARRAYFLOAT = #220; TOK_ARRAYFLOAT4 = #223; TOK_ARRAYSTRING = #224; TOK_ARRAYSTRING4 = #227; TOK_ARRAYUDT = #228; TOK_ARRAYUDT4 = #231; TOK_ARRAYCHARDEF = #232; TOK_ARRAYCHARDEF4 = #235; TOK_ARRAYSHORTDEF = #236; TOK_ARRAYSHORTDEF4 = #239; TOK_ARRAYLONGDEF = #240; TOK_ARRAYLONGDEF4 = #243; TOK_ARRAYBYTEDEF = #244; TOK_ARRAYBYTEDEF4 = #247; TOK_ARRAYUSHORTDEF = #248; TOK_ARRAYUSHORTDEF4 = #251; TOK_ARRAYULONGDEF = #252; TOK_ARRAYULONGDEF4 = #255; TOK_BLOCK_COMMENT = #01; TOK_LINE_COMMENT = #02; const REGVARS_ARRAY : array[0..11] of string = ( '__tmpsbyte%s', '__tmpsword%s', '__tmpslong%s', '__tmplong%s', '__D0%s', '__DU0%s', '__zf%s', '__strtmpbuf%s', '__strbuf%s', '__strretval%s', '__tmpfloat%s', '__DF0%s' ); REGVARTYPES_ARRAY : array[0..11] of string = ( 'sbyte', 'sword', 'slong', 'long', 'slong', 'long', 'byte', 'byte[]', 'byte[]', 'byte[]', 'float', 'float' ); const DECOR_SEP = '_7qG2_'; var MaxStackDepth : integer; implementation uses {$IFDEF FAST_MM} FastStrings, {$ENDIF} strutils, uCommonUtils; function IsAlpha(c: char): boolean; begin Result := c in ['A'..'Z', 'a'..'z', '_']; end; function IsCharWhiteSpace(C: Char): Boolean; begin Result := C in [#9, #10, #11, #12, #13, #32]; end; function StrContains(const SubStr, Str: string): Boolean; begin Result := Pos(SubStr, Str) > 0; end; const INLINE_DECOR_SEP = '_inline_'{ + DECOR_SEP}; // INLINE_DECORATION = '__%s_inline_%s'; INLINE_DECORATION = '%1:s' + INLINE_DECOR_SEP + '%0:s'; function InlineName(const tname, name: string): string; begin Result := Format(INLINE_DECORATION, [tname, name]); // Result := name; end; function RPos(Substr: string ; S: string ): Integer; begin Result := Pos(ReverseString(Substr), ReverseString(S)); if Result <> 0 then Result := Length(S) - (Result - 1) - (Length(Substr) - 1); end; function StripInline(const name: string): string; var i : integer; begin Result := name; i := RPos(INLINE_DECOR_SEP, Result); if i > 0 then Result := Copy(Result, 1, i-1); end; function InlineThreadName(const name: string): string; var i : integer; begin Result := name; i := RPos(INLINE_DECOR_SEP, Result); if i > 0 then Result := Copy(Result, i+Length(INLINE_DECOR_SEP), MaxInt); end; function IsInlined(const name: string) : boolean; begin Result := Pos(INLINE_DECOR_SEP, name) > 0; end; function StripAllInlineDecoration(const name: string): string; var i : integer; begin Result := name; i := Pos(INLINE_DECOR_SEP, Result); if i > 0 then Result := Copy(Result, 1, i-1); end; function StripDecoration(const name : string) : string; var i : integer; varName : string; begin Result := StripInline(name); // a decorated name has this pattern: // __threadnameDECOR_SEPvariablenameDECOR_SEPNNNetc i := Pos(DECOR_SEP, Result); if i > 0 then begin System.Delete(Result, 1, i+Length(DECOR_SEP)-1); i := Pos(DECOR_SEP, Result); if i > 0 then begin varName := Copy(Result, 1, i-1); System.Delete(Result, 1, i+Length(DECOR_SEP)+2); Result := varName + Result; end; end; end; function PrettyNameStrip(const name : string) : string; var i : integer; begin Result := name; // a decorated name has this pattern: // __threadnameDECOR_SEPvariablenameDECOR_SEPNNNetc i := Pos(DECOR_SEP, Result); if i > 0 then begin System.Delete(Result, 1, 2); // drop the underscores Result := Replace(Result, DECOR_SEP, '.'); end; end; function ApplyDecoration(const pre, val: string; const level : integer): string; var p : integer; first, last : string; begin // if val contains dots then separate it into two pieces p := Pos('.', val); if p > 0 then begin first := Copy(val, 1, p-1); last := Copy(val, p, MaxInt); Result := Format('__%s%s%s%s%3.3d%s', [pre, DECOR_SEP, first, DECOR_SEP, level, last]); // Result := Format('__%s_%s_%3.3d%s', [pre, first, level, last]); end else begin Result := Format('__%s%s%s%s%3.3d', [pre, DECOR_SEP, val, DECOR_SEP, level]); // Result := Format('__%s_%s_%3.3d', [pre, val, level]); end; end; function Replace(const str : string; const src, rep : string) : string; begin {$IFDEF FAST_MM} Result := FastReplace(str, src, rep); {$ELSE} Result := StringReplace(str, src, rep, [rfReplaceAll]); {$ENDIF} end; procedure NBCFormatSettings(var aFS : TFormatSettings; const aDS : Char); begin aFS.DecimalSeparator := aDS; aFS.ThousandSeparator := ThousandSeparator; aFS.CurrencyFormat := CurrencyFormat; aFS.NegCurrFormat := NegCurrFormat; aFS.CurrencyDecimals := CurrencyDecimals; aFS.CurrencyString := CurrencyString; end; function NBCFloatToStr(const AValue: Double): string; begin Result := StripTrailingZeros(NBCFormat('%.10f', [AValue])); end; function NBCStrToFloat(const AValue: string): Double; var FS : TFormatSettings; begin FS.DecimalSeparator := DecimalSeparator; NBCFormatSettings(FS, '.'); Result := StrToFloat(AValue, FS); end; function NBCStrToFloatDef(const AValue: string; const aDef : Double): Double; var FS : TFormatSettings; begin FS.DecimalSeparator := DecimalSeparator; NBCFormatSettings(FS, '.'); Result := StrToFloatDef(AValue, aDef, FS); end; function NBCTextToFloat(Buffer: PChar; var Value; ValueType: TFloatValue): Boolean; var FS : TFormatSettings; val : Extended; begin FS.DecimalSeparator := DecimalSeparator; NBCFormatSettings(FS, '.'); Result := TextToFloat(Buffer, val, fvExtended, FS); end; function NBCFormat(const FmtStr: string; const theArgs: array of const) : string; var FS : TFormatSettings; begin FS.DecimalSeparator := DecimalSeparator; NBCFormatSettings(FS, '.'); Result := Format(FmtStr, theArgs, FS); end; function StripQuotes(const str : string) : string; begin Result := Copy(str, 2, Length(str)-2); end; {$IFDEF FPC} function JCHExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer; var Head, Tail: PChar; EOS, InQuote: Boolean; QuoteChar: Char; Item: string; begin Item := ''; Result := 0; if (Content = nil) or (Content^=#0) or (Strings = nil) then Exit; Tail := Content; InQuote := False; QuoteChar := #0; Strings.BeginUpdate; try repeat while Tail^ in WhiteSpace + [#13, #10] do inc(Tail); Head := Tail; while True do begin while (InQuote and not (Tail^ in [QuoteChar, #0])) or not (Tail^ in Separators + [#0, #13, #10, '''', '"']) do inc(Tail); if Tail^ in ['''', '"'] then begin if (QuoteChar <> #0) and (QuoteChar = Tail^) then QuoteChar := #0 else if QuoteChar = #0 then QuoteChar := Tail^; InQuote := QuoteChar <> #0; inc(Tail); end else Break; end; EOS := Tail^ = #0; if (Head <> Tail) and (Head^ <> #0) then begin if Strings <> nil then begin SetString(Item, Head, Tail - Head); Strings.Add(Item); end; Inc(Result); end; inc(Tail); until EOS; finally Strings.EndUpdate; end; end; {$ELSE} function JCHExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer; begin Result := ExtractStrings(Separators, WhiteSpace, Content, Strings); end; {$ENDIF} function ValueToDataType(const value : integer) : char; begin if value < 0 then begin Result := TOK_CHARDEF; if value < Low(Shortint) then begin Result := TOK_SHORTDEF; if value < Low(Smallint) then Result := TOK_LONGDEF; end; end else begin Result := TOK_BYTEDEF; if value > High(Byte) then begin Result := TOK_USHORTDEF; if value > High(Word) then Result := TOK_ULONGDEF; end; end; end; function DataTypeToTypeName(const dt : char) : string; begin case dt of TOK_CHARDEF : Result := 'char'; TOK_SHORTDEF : Result := 'int'; TOK_LONGDEF : Result := 'long'; TOK_BYTEDEF : Result := 'byte'; TOK_USHORTDEF : Result := 'unsigned int'; TOK_ULONGDEF : Result := 'unsigned long'; else Result := 'unexpected type'; end; end; function BoolToString(aValue : boolean) : string; begin if aValue then Result := 'TRUE' else Result := 'FALSE'; end; { TNBCExpParser } constructor TNBCExpParser.Create(AOwner: TComponent); begin inherited; fFirmwareVersion := MAX_FW_VER1X; end; procedure TNBCExpParser.InitializeCalc; var i : integer; begin ClearVariables; if StandardDefines then begin SetVariable(STR_NA, NOT_AN_ELEMENT); SetVariable(STR_FALSE, Ord(false)); SetVariable(STR_TRUE, Ord(true)); // add comparison codes for i := Low(CCEncodings) to High(CCEncodings) do SetVariable(CCEncodings[i].Mode, CCEncodings[i].Encoding); // add output field IDs for i := Low(OutputFieldIDs) to High(OutputFieldIDs) do SetVariable(OutputFieldIDs[i].Name, OutputFieldIDs[i].ID); // add input field IDs for i := Low(InputFieldIDs) to High(InputFieldIDs) do SetVariable(InputFieldIDs[i].Name, InputFieldIDs[i].ID); if FirmwareVersion > MAX_FW_VER1X then begin // add syscall method IDs for i := Low(SysCallMethodIDs2x) to High(SysCallMethodIDs2x) do SetVariable(SysCallMethodIDs2x[i].Name, SysCallMethodIDs2x[i].ID); end else begin // add syscall method IDs for i := Low(SysCallMethodIDs1x) to High(SysCallMethodIDs1x) do SetVariable(SysCallMethodIDs1x[i].Name, SysCallMethodIDs1x[i].ID); end; // add IOMap field IDs for i := Low(IOMapFieldIDs) to High(IOMapFieldIDs) do SetVariable(IOMapFieldIDs[i].Name, IOMapFieldIDs[i].ID); { // add IOMap Offset IDs for i := Low(IOMapOffsetRecords) to High(IOMapOffsetRecords) do SetVariable(IOMapOffsetRecords[i].Name, IOMapOffsetRecords[i].ID); } end; if ExtraDefines then begin SetVariable(STR_OUT_A, OUT_A); SetVariable(STR_OUT_B, OUT_B); SetVariable(STR_OUT_C, OUT_C); SetVariable(STR_IN_1, IN_1); SetVariable(STR_IN_2, IN_2); SetVariable(STR_IN_3, IN_3); SetVariable(STR_IN_4, IN_4); SetVariable(STR_IO_BASE, IO_BASE); SetVariable(STR_MOD_OUTPUT, MOD_OUTPUT); SetVariable(STR_MOD_INPUT, MOD_INPUT); SetVariable(STR_IO_IN_FPP, IO_IN_FPP); SetVariable(STR_IO_OUT_FPP, IO_OUT_FPP); // add Update Flag IDs for i := Low(UFRecords) to High(UFRecords) do SetVariable(UFRecords[i].Name, UFRecords[i].ID); // add Output Mode IDs for i := Low(OutModeRecords) to High(OutModeRecords) do SetVariable(OutModeRecords[i].Name, OutModeRecords[i].ID); // add Output RunState IDs for i := Low(OutRunStateRecords) to High(OutRunStateRecords) do SetVariable(OutRunStateRecords[i].Name, OutRunStateRecords[i].ID); // add Output RegMode IDs for i := Low(OutRegModeRecords) to High(OutRegModeRecords) do SetVariable(OutRegModeRecords[i].Name, OutRegModeRecords[i].ID); // add Input Type IDs for i := Low(InTypeRecords) to High(InTypeRecords) do SetVariable(InTypeRecords[i].Name, InTypeRecords[i].ID); // add Input Mode IDs for i := Low(InModeRecords) to High(InModeRecords) do SetVariable(InModeRecords[i].Name, InModeRecords[i].ID); // add MS_X IDs for i := Low(MSRecords) to High(MSRecords) do SetVariable(MSRecords[i].Name, MSRecords[i].ID); // add TONE_X IDs for i := Low(ToneRecords) to High(ToneRecords) do SetVariable(ToneRecords[i].Name, ToneRecords[i].ID); { // add miscellaneous IOMap constants for i := Low(IOMapMiscRecords) to High(IOMapMiscRecords) do SetVariable(IOMapMiscRecords[i].Name, IOMapMiscRecords[i].ID); } end; end; procedure TNBCExpParser.SetExtraDefs(const aValue: boolean); begin if fExtraDefs <> aValue then begin fExtraDefs := aValue; InitializeCalc; end; end; procedure TNBCExpParser.SetFirmwareVersion(const Value: word); begin fFirmwareVersion := Value; end; procedure TNBCExpParser.SetStandardDefs(const aValue: boolean); begin if fStandardDefs <> aValue then begin fStandardDefs := aValue; InitializeCalc; end; end; { TInlineFunction } constructor TInlineFunction.Create(ACollection: TCollection); begin inherited; fCode := TStringList.Create; fVariables := TVariableList.Create; fCallers := TStringList.Create; TStringList(fCallers).Sorted := True; TStringList(fCallers).Duplicates := dupError; fParams := TFunctionParameters.Create; fEmitCount := 0; end; destructor TInlineFunction.Destroy; begin FreeAndNil(fCode); FreeAndNil(fVariables); FreeAndNil(fCallers); FreeAndNil(fParams); inherited; end; procedure TInlineFunction.Emit(aStrings: TStrings); var tmpSL : TStringList; tmpCode, oldname, newname, NameInline : string; i : integer; fp : TFunctionParameter; begin inc(fEmitCount); // adjust labels tmpSL := TStringList.Create; try tmpCode := FixupLabels(fCode.Text); tmpCode := Replace(tmpCode, 'return', Format('jmp %s', [EndLabel])); // do all the variable replacing that is needed for i := 0 to Parameters.Count - 1 do begin fp := Parameters[i]; oldname := ApplyDecoration(fp.ProcName, fp.Name, 0); newname := InlineName(CurrentCaller, oldname); // is this parameter a constant? if fp.IsConstant and not fp.IsReference then tmpCode := Replace(tmpCode, oldname, fp.ConstantValue) else tmpCode := Replace(tmpCode, oldname, newname); end; for i := 0 to LocalVariables.Count - 1 do begin oldname := LocalVariables[i].Name; newname := InlineName(CurrentCaller, oldname); tmpCode := Replace(tmpCode, oldname, newname); end; // need to fix string return buffer name, string temp buffer name, // register name, and all the stack variable names. // YUCKY !!!!!!! NameInline := InlineName(CurrentCaller, Name); for i := Low(REGVARS_ARRAY) to High(REGVARS_ARRAY) do begin oldname := Format(REGVARS_ARRAY[i], [Name]); newname := Format(REGVARS_ARRAY[i], [NameInline]); tmpCode := Replace(tmpCode, oldName, newName); end; oldname := Format('__result_%s', [Name]); newname := Format('__result_%s', [NameInline]); tmpCode := Replace(tmpCode, oldName, newName); for i := 1 to MaxStackDepth do begin oldname := Format('__signed_stack_%3.3d%s', [i, Name]); newname := Format('__signed_stack_%3.3d%s', [i, NameInline]); tmpCode := Replace(tmpCode, oldName, newName); end; for i := 1 to MaxStackDepth do begin oldname := Format('__unsigned_stack_%3.3d%s', [i, Name]); newname := Format('__unsigned_stack_%3.3d%s', [i, NameInline]); tmpCode := Replace(tmpCode, oldName, newName); end; for i := 1 to MaxStackDepth do begin oldname := Format('__float_stack_%3.3d%s', [i, Name]); newname := Format('__float_stack_%3.3d%s', [i, NameInline]); tmpCode := Replace(tmpCode, oldName, newName); end; if Pos(EndLabel, tmpCode) > 0 then tmpCode := tmpCode + #13#10 + EndLabel + ':'; tmpSL.Text := tmpCode; aStrings.AddStrings(tmpSL); finally tmpSL.Free; end; end; function TInlineFunction.FixupLabels(const tmpCode: string): string; { var tmp, values : TStringList; i, j : integer; line : string; } begin // NXC-generated labels are fixed-up here Result := Replace(tmpCode, LABEL_PREFIX, Format('__%3.3d%s', [fEmitCount, LABEL_PREFIX])); // also need to fix any other user-defined labels in the code so that // emitting this code more than once will not cause duplicate label // problems { tmp := TStringList.Create; try tmp.Text := Result; for i := 0 to tmp.Count - 1 do begin line := tmp[i]; // does this line contain a label? values := TStringList.Create; try j := JCHExtractStrings([' ', #9], [], PChar(line), values); finally values.Free; end; end; finally tmp.Free; end; } end; function TInlineFunction.GetEndLabel: string; begin Result := Format(LABEL_PREFIX+'%s_inline_%s_%3.3d_end_lbl', [CurrentCaller, Name, fEmitCount]); end; procedure TInlineFunction.SetCode(const Value: TStrings); begin fCode.Assign(Value); end; procedure TInlineFunction.SetParams(const Value: TFunctionParameters); var i : integer; fp, newFP : TFunctionParameter; begin // copy into fParams the parameters in Value that are for this function fParams.Clear; for i := 0 to Value.Count - 1 do begin fp := Value[i]; if fp.ProcName = Self.Name then begin newFP := Self.Parameters.Add; newFP.Assign(fp); end; end; end; { TInlineFunctions } function TInlineFunctions.Add: TInlineFunction; begin Result := TInlineFunction(inherited Add); end; constructor TInlineFunctions.Create; begin inherited Create(TInlineFunction); end; function TInlineFunctions.GetItem(Index: Integer): TInlineFunction; begin Result := TInlineFunction(inherited GetItem(Index)); end; function TInlineFunctions.IndexOfName(const name: string): integer; var i : integer; begin Result := -1; for i := 0 to Count - 1 do begin if Items[i].Name = name then begin Result := Items[i].Index; break; end; end; end; function TInlineFunctions.Insert(Index: Integer): TInlineFunction; begin result := TInlineFunction(inherited Insert(Index)); end; procedure TInlineFunctions.SetItem(Index: Integer; const Value: TInlineFunction); begin inherited SetItem(Index, Value); end; { TFunctionParameters } function TFunctionParameters.Add: TFunctionParameter; begin Result := TFunctionParameter(inherited Add); end; constructor TFunctionParameters.Create; begin inherited Create(TFunctionParameter); end; function TFunctionParameters.GetItem(Index: Integer): TFunctionParameter; begin Result := TFunctionParameter(inherited GetItem(Index)); end; function TFunctionParameters.IndexOf(const procname: string; const idx: integer): integer; var i : integer; fp : TFunctionParameter; begin Result := -1; for i := 0 to Count - 1 do begin fp := Items[i]; if (fp.ProcName = procname) and (fp.ParamIndex = idx) then begin Result := fp.Index; break; end; end; end; function TFunctionParameters.Insert(Index: Integer): TFunctionParameter; begin result := TFunctionParameter(inherited Insert(Index)); end; function TFunctionParameters.ParamCount(const name: string): integer; var i : integer; begin Result := 0; for i := 0 to Count - 1 do begin if Items[i].ProcName = name then inc(Result); end; end; function TFunctionParameters.RequiredParamCount(const name: string): integer; var i : integer; fp : TFunctionParameter; begin Result := 0; for i := 0 to Count - 1 do begin fp := Items[i]; if (fp.ProcName = name) and not fp.HasDefault then inc(Result); end; end; procedure TFunctionParameters.SetItem(Index: Integer; const Value: TFunctionParameter); begin inherited SetItem(Index, Value); end; { TFunctionParameter } procedure TFunctionParameter.AssignTo(Dest: TPersistent); var fp : TFunctionParameter; begin if Dest is TFunctionParameter then begin fp := TFunctionParameter(Dest); fp.ProcName := ProcName; fp.Name := Name; fp.ParamType := ParamType; fp.ParamTypeName := ParamTypeName; fp.ParamIndex := ParamIndex; fp.IsArray := IsArray; fp.IsConstant := IsConstant; fp.IsReference := IsReference; fp.ArrayDimension := ArrayDimension; fp.ConstantValue := ConstantValue; fp.FuncIsInline := FuncIsInline; fp.HasDefault := HasDefault; fp.DefaultValue := DefaultValue; end else inherited; end; constructor TFunctionParameter.Create(ACollection: TCollection); begin inherited; fProcName := ''; fName := ''; fParamIndex := 0; fIsConstant := False; fIsReference := False; fIsArray := False; fDim := 0; fParamType := fptUBYTE; fFuncIsInline := False; fHasDefault := False; fDefaultValue := ''; end; function TFunctionParameter.GetConstValue: string; begin Result := fConstValue; end; function TFunctionParameter.GetIsConstReference: boolean; begin Result := IsConstant and IsReference; end; function TFunctionParameter.GetIsVarReference: boolean; begin Result := not IsConstant and IsReference; end; function TFunctionParameter.GetParamDataType: char; begin case ParamType of fptSBYTE : begin if not IsArray then Result := TOK_CHARDEF else Result := Char(Ord(TOK_ARRAYCHARDEF) + ArrayDimension-1); end; fptUBYTE : begin if not IsArray then Result := TOK_BYTEDEF else Result := Char(Ord(TOK_ARRAYBYTEDEF) + ArrayDimension-1); end; fptSWORD : begin if not IsArray then Result := TOK_SHORTDEF else Result := Char(Ord(TOK_ARRAYSHORTDEF) + ArrayDimension-1); end; fptUWORD : begin if not IsArray then Result := TOK_USHORTDEF else Result := Char(Ord(TOK_ARRAYUSHORTDEF) + ArrayDimension-1); end; fptSLONG : begin if not IsArray then Result := TOK_LONGDEF else Result := Char(Ord(TOK_ARRAYLONGDEF) + ArrayDimension-1); end; fptULONG : begin if not IsArray then Result := TOK_ULONGDEF else Result := Char(Ord(TOK_ARRAYULONGDEF) + ArrayDimension-1); end; fptString : begin if not IsArray then Result := TOK_STRINGDEF else Result := Char(Ord(TOK_ARRAYSTRING) + ArrayDimension-1); end; fptUDT : begin if not IsArray then Result := TOK_USERDEFINEDTYPE else Result := Char(Ord(TOK_ARRAYUDT) + ArrayDimension-1); end; fptMutex : Result := TOK_MUTEXDEF; fptFloat : begin if not IsArray then Result := TOK_FLOATDEF else Result := Char(Ord(TOK_ARRAYFLOAT) + ArrayDimension-1); end; else Result := TOK_BYTEDEF; end; end; procedure TFunctionParameter.SetConstValue(const Value: string); begin fConstValue := Value; end; { TVariable } procedure TVariable.AssignTo(Dest: TPersistent); var V : TVariable; begin if Dest is TVariable then begin V := TVariable(Dest); V.Name := Name; V.DataType := DataType; V.IsConstant := IsConstant; V.TypeName := TypeName; V.LenExpr := LenExpr; V.Level := Level; V.HasDefault := HasDefault; V.DefaultValue := DefaultValue; end else inherited; end; constructor TVariable.Create(ACollection: TCollection); begin inherited; fName := ''; fValue := ''; fTypeName := ''; fDataType := TOK_BYTEDEF; fIsConst := False; fLevel := 0; fHasDef := False; fDefValue := ''; end; { TVariableList } function TVariableList.Add: TVariable; begin Result := TVariable(inherited Add); end; constructor TVariableList.Create; begin inherited Create(TVariable); end; function TVariableList.GetItem(Index: Integer): TVariable; begin Result := TVariable(inherited GetItem(Index)); end; function TVariableList.IndexOfName(const name: string): integer; var i : integer; begin Result := -1; for i := 0 to Count - 1 do begin if Items[i].Name = name then begin Result := Items[i].Index; break; end; end; end; function TVariableList.Insert(Index: Integer): TVariable; begin Result := TVariable(inherited Insert(Index)); end; procedure TVariableList.SetItem(Index: Integer; const Value: TVariable); begin inherited SetItem(Index, Value); end; { TArrayHelperVar } constructor TArrayHelperVar.Create(ACollection: TCollection); begin inherited; fThreadName := 'main'; fDataType := #0; fUDType := ''; fIndex := 0; fLocked := False; end; function TArrayHelperVar.GetName: string; begin Result := Format('__ArrHelper__%s%s_%d_%d', [fThreadName, fUDType, Ord(fDataType), fIndex]); end; { TArrayHelperVars } function TArrayHelperVars.Add: TArrayHelperVar; begin Result := TArrayHelperVar(inherited Add); end; constructor TArrayHelperVars.Create; begin inherited Create(TArrayHelperVar); end; function TArrayHelperVars.GetHelper(const tname, udType: string; const dt: char): TArrayHelperVar; var i, newIdx : integer; X : TArrayHelperVar; begin Result := nil; // look for existing helper. If not found, create one. for i := 0 to Count - 1 do begin X := Items[i]; if (X.ThreadName = tname) and (X.DataType = dt) and (X.UserDefinedType = udType) and not X.Locked then begin Result := X; Break; end; end; if Result = nil then begin newIdx := 0; for i := Count - 1 downto 0 do begin X := Items[i]; if (X.ThreadName = tname) and (X.DataType = dt) and (X.UserDefinedType = udType) then begin // duplicate item newIdx := X.Index + 1; break; end; end; // create new helper Result := Add; Result.ThreadName := tname; Result.DataType := dt; Result.UserDefinedType := udType; Result.fIndex := newIdx; end; Result.fLocked := True; end; function TArrayHelperVars.GetItem(Index: Integer): TArrayHelperVar; begin Result := TArrayHelperVar(inherited GetItem(Index)); end; function TArrayHelperVars.IndexOfName(const name: string): integer; var i : integer; begin Result := -1; for i := 0 to Count - 1 do begin if Items[i].Name = name then begin Result := Items[i].Index; break; end; end; end; function TArrayHelperVars.Insert(Index: Integer): TArrayHelperVar; begin Result := TArrayHelperVar(inherited Insert(Index)); end; procedure TArrayHelperVars.ReleaseHelper(aHelper: TArrayHelperVar); begin aHelper.fLocked := False; end; procedure TArrayHelperVars.SetItem(Index: Integer; const Value: TArrayHelperVar); begin inherited SetItem(Index, Value); end; end. NXT/NBCCommon.h0000644000175000017500000055526511537752673013075 0ustar slavkoslavko/** \file NBCCommon.h * \brief Constants and macros common to both NBC and NXC * * NBCCommon.h contains declarations for the NBC and NXC NXT API functions. * * License: * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009-2010 John Hansen. * All Rights Reserved. * * ---------------------------------------------------------------------------- * * \author John Hansen (bricxcc_at_comcast.net) * \date 2011-03-13 * \version 63 */ #ifndef NBCCOMMON_H #define NBCCOMMON_H /** @addtogroup MiscConstants * @{ */ #define TRUE 1 /*!< A true value */ #define FALSE 0 /*!< A false value */ #define NA 0xFFFF /*!< The specified argument does not apply (aka unwired) */ /** @defgroup RCPropertyConstants Property constants * Use these constants for specifying the property for the GetProperty * and SetProperty direct commands. * @{ */ #define RC_PROP_BTONOFF 0x0 /*!< Set/get whether bluetooth is on or off */ #define RC_PROP_SOUND_LEVEL 0x1 /*!< Set/get the NXT sound level */ #define RC_PROP_SLEEP_TIMEOUT 0x2 /*!< Set/get the NXT sleep timeout value (times 60000) */ #define RC_PROP_DEBUGGING 0xF /*!< Set/get enhanced firmware debugging information */ /** @} */ // end of RCPropertyConstants group /** @} */ // end of MiscConstants group #ifdef __ENHANCED_FIRMWARE /** @addtogroup CommandModuleConstants * @{ */ /** @defgroup ArrayOpConstants Array operation constants * Constants for use with the NXC ArrayOp function and the NBC arrop statement. * @{ */ // array operation definitions #define OPARR_SUM 0x00 /*!< Calculate the sum of the elements in the numeric input array */ #define OPARR_MEAN 0x01 /*!< Calculate the mean value for the elements in the numeric input array */ #define OPARR_SUMSQR 0x02 /*!< Calculate the sum of the squares of the elements in the numeric input array */ #define OPARR_STD 0x03 /*!< Calculate the standard deviation of the elements in the numeric input array */ #define OPARR_MIN 0x04 /*!< Calculate the minimum value of the elements in the numeric input array */ #define OPARR_MAX 0x05 /*!< Calculate the maximum value of the elements in the numeric input array */ #define OPARR_SORT 0x06 /*!< Sort the elements in the numeric input array */ /** @} */ // end of ArrayOpConstants group /** @} */ // end of CommandModuleConstants group #endif /** @addtogroup MiscConstants * @{ */ #if __FIRMWARE_VERSION > 107 #define PI 3.141593 /*!< A constant for PI */ #define RADIANS_PER_DEGREE PI/180 /*!< Used for converting from degrees to radians */ #define DEGREES_PER_RADIAN 180/PI /*!< Used for converting from radians to degrees */ #endif /** @} */ // end of MiscConstants group #if __FIRMWARE_VERSION <= 107 /** @defgroup IOMapAddressConstants Direct IOMap data addresses * Constants for use in direct IOMap addressing (1.0x only). * @{ */ #define IO_BASE 0xC000 #define MOD_INPUT 0x0000 #define MOD_OUTPUT 0x0200 #define IO_IN_FPP 6 #define IO_OUT_FPP 15 #define InputIOType(p) (IO_BASE+MOD_INPUT+TypeField+((p)*IO_IN_FPP)) #define InputIOInputMode(p) (IO_BASE+MOD_INPUT+InputModeField+((p)*IO_IN_FPP)) #define InputIORawValue(p) (IO_BASE+MOD_INPUT+RawValueField+((p)*IO_IN_FPP)) #define InputIONormalizedValue(p) (IO_BASE+MOD_INPUT+NormalizedValueField+((p)*IO_IN_FPP)) #define InputIOScaledValue(p) (IO_BASE+MOD_INPUT+ScaledValueField+((p)*IO_IN_FPP)) #define InputIOInvalidData(p) (IO_BASE+MOD_INPUT+InvalidDataField+((p)*IO_IN_FPP)) #define OutputIOUpdateFlags(p) (IO_BASE+MOD_OUTPUT+UpdateFlagsField+((p)*IO_OUT_FPP)) #define OutputIOOutputMode(p) (IO_BASE+MOD_OUTPUT+OutputModeField+((p)*IO_OUT_FPP)) #define OutputIOPower(p) (IO_BASE+MOD_OUTPUT+PowerField+((p)*IO_OUT_FPP)) #define OutputIOActualSpeed(p) (IO_BASE+MOD_OUTPUT+ActualSpeedField+((p)*IO_OUT_FPP)) #define OutputIOTachoCount(p) (IO_BASE+MOD_OUTPUT+TachoCountField+((p)*IO_OUT_FPP)) #define OutputIOTachoLimit(p) (IO_BASE+MOD_OUTPUT+TachoLimitField+((p)*IO_OUT_FPP)) #define OutputIORunState(p) (IO_BASE+MOD_OUTPUT+RunStateField+((p)*IO_OUT_FPP)) #define OutputIOTurnRatio(p) (IO_BASE+MOD_OUTPUT+TurnRatioField+((p)*IO_OUT_FPP)) #define OutputIORegMode(p) (IO_BASE+MOD_OUTPUT+RegModeField+((p)*IO_OUT_FPP)) #define OutputIOOverload(p) (IO_BASE+MOD_OUTPUT+OverloadField+((p)*IO_OUT_FPP)) #define OutputIORegPValue(p) (IO_BASE+MOD_OUTPUT+RegPValueField+((p)*IO_OUT_FPP)) #define OutputIORegIValue(p) (IO_BASE+MOD_OUTPUT+RegIValueField+((p)*IO_OUT_FPP)) #define OutputIORegDValue(p) (IO_BASE+MOD_OUTPUT+RegDValueField+((p)*IO_OUT_FPP)) #define OutputIOBlockTachoCount(p) (IO_BASE+MOD_OUTPUT+BlockTachoCountField+((p)*IO_OUT_FPP)) #define OutputIORotationCount(p) (IO_BASE+MOD_OUTPUT+RotationCountField+((p)*IO_OUT_FPP)) #define InputIOType0 0xc000 #define InputIOInputMode0 0xc001 #define InputIORawValue0 0xc002 #define InputIONormalizedValue0 0xc003 #define InputIOScaledValue0 0xc004 #define InputIOInvalidData0 0xc005 #define InputIOType1 0xc006 #define InputIOInputMode1 0xc007 #define InputIORawValue1 0xc008 #define InputIONormalizedValue1 0xc009 #define InputIOScaledValue1 0xc00a #define InputIOInvalidData1 0xc00b #define InputIOType2 0xc00c #define InputIOInputMode2 0xc00d #define InputIORawValue2 0xc00e #define InputIONormalizedValue2 0xc00f #define InputIOScaledValue2 0xc010 #define InputIOInvalidData2 0xc011 #define InputIOType3 0xc012 #define InputIOInputMode3 0xc013 #define InputIORawValue3 0xc014 #define InputIONormalizedValue3 0xc015 #define InputIOScaledValue3 0xc016 #define InputIOInvalidData3 0xc017 // output IO Map addresses #define OutputIOUpdateFlags0 0xc200 #define OutputIOOutputMode0 0xc201 #define OutputIOPower0 0xc202 #define OutputIOActualSpeed0 0xc203 #define OutputIOTachoCount0 0xc204 #define OutputIOTachoLimit0 0xc205 #define OutputIORunState0 0xc206 #define OutputIOTurnRatio0 0xc207 #define OutputIORegMode0 0xc208 #define OutputIOOverload0 0xc209 #define OutputIORegPValue0 0xc20a #define OutputIORegIValue0 0xc20b #define OutputIORegDValue0 0xc20c #define OutputIOBlockTachoCount0 0xc20d #define OutputIORotationCount0 0xc20e #define OutputIOUpdateFlags1 0xc20f #define OutputIOOutputMode1 0xc210 #define OutputIOPower1 0xc211 #define OutputIOActualSpeed1 0xc212 #define OutputIOTachoCount1 0xc213 #define OutputIOTachoLimit1 0xc214 #define OutputIORunState1 0xc215 #define OutputIOTurnRatio1 0xc216 #define OutputIORegMode1 0xc217 #define OutputIOOverload1 0xc218 #define OutputIORegPValue1 0xc219 #define OutputIORegIValue1 0xc21a #define OutputIORegDValue1 0xc21b #define OutputIOBlockTachoCount1 0xc21c #define OutputIORotationCount1 0xc21d #define OutputIOUpdateFlags2 0xc21e #define OutputIOOutputMode2 0xc21f #define OutputIOPower2 0xc220 #define OutputIOActualSpeed2 0xc221 #define OutputIOTachoCount2 0xc222 #define OutputIOTachoLimit2 0xc223 #define OutputIORunState2 0xc224 #define OutputIOTurnRatio2 0xc225 #define OutputIORegMode2 0xc226 #define OutputIOOverload2 0xc227 #define OutputIORegPValue2 0xc228 #define OutputIORegIValue2 0xc229 #define OutputIORegDValue2 0xc22a #define OutputIOBlockTachoCount2 0xc22b #define OutputIORotationCount2 0xc22c /** @} */ // end of IOMapAddressConstants group #endif /** @addtogroup CommandModuleConstants * @{ */ /** @defgroup SysCallConstants System Call function constants * Constants for use in the SysCall() function or NBC syscall statement. * @{ */ #define FileOpenRead 0 /*!< Open a file for reading */ #define FileOpenWrite 1 /*!< Open a file for writing (creates a new file) */ #define FileOpenAppend 2 /*!< Open a file for appending to the end of the file */ #define FileRead 3 /*!< Read from the specified file */ #define FileWrite 4 /*!< Write to the specified file */ #define FileClose 5 /*!< Close the specified file */ #define FileResolveHandle 6 /*!< Get a file handle for the specified filename if it is already open */ #define FileRename 7 /*!< Rename a file */ #define FileDelete 8 /*!< Delete a file */ #define SoundPlayFile 9 /*!< Play a sound or melody file */ #define SoundPlayTone 10 /*!< Play a simple tone with the specified frequency and duration */ #define SoundGetState 11 /*!< Get the current sound module state */ #define SoundSetState 12 /*!< Set the sound module state */ #define DrawText 13 /*!< Draw text to one of 8 LCD lines */ #define DrawPoint 14 /*!< Draw a single pixel on the LCD screen */ #define DrawLine 15 /*!< Draw a line on the LCD screen */ #define DrawCircle 16 /*!< Draw a circle on the LCD screen */ #define DrawRect 17 /*!< Draw a rectangle on the LCD screen */ #define DrawGraphic 18 /*!< Draw a graphic image on the LCD screen */ #define SetScreenMode 19 /*!< Set the screen mode */ #define ReadButton 20 /*!< Read the current button state */ #define CommLSWrite 21 /*!< Write to a lowspeed (aka I2C) device */ #define CommLSRead 22 /*!< Read from a lowspeed (aka I2C) device */ #define CommLSCheckStatus 23 /*!< Check the status of a lowspeed (aka I2C) device */ #define RandomNumber 24 /*!< Generate a random number */ #define GetStartTick 25 /*!< Get the current system tick count */ #define MessageWrite 26 /*!< Write a message to a mailbox */ #define MessageRead 27 /*!< Read a message from a mailbox */ #define CommBTCheckStatus 28 /*!< Check the bluetooth status */ #define CommBTWrite 29 /*!< Write to a bluetooth connections */ #define CommBTRead 30 /*!< Read from a bluetooth connection */ #define KeepAlive 31 /*!< Reset the NXT sleep timer */ #define IOMapRead 32 /*!< Read data from one of the firmware module's IOMap structures using the module's name */ #define IOMapWrite 33 /*!< Write data to one of the firmware module's IOMap structures using the module's name */ #if __FIRMWARE_VERSION <= 107 #ifdef __ENHANCED_FIRMWARE #define IOMapReadByID 34 #define IOMapWriteByID 35 #define DisplayExecuteFunction 36 #define CommExecuteFunction 37 #define LoaderExecuteFunction 38 #define FileFindFirst 39 #define FileFindNext 40 #define FileOpenWriteLinear 41 #define FileOpenWriteNonLinear 42 #define FileOpenReadLinear 43 #define CommHSControl 44 #define CommHSCheckStatus 45 #define CommHSWrite 46 #define CommHSRead 47 #endif #else // NXT 2.0 firmwares #define ColorSensorRead 34 /*!< Read data from the NXT 2.0 color sensor */ #define CommBTOnOff 35 /*!< Turn the bluetooth radio on or off */ #define CommBTConnection 36 /*!< Connect or disconnect to a known bluetooth device */ #define CommHSWrite 37 /*!< Write data to the hi-speed port */ #define CommHSRead 38 /*!< Read data from the hi-speed port */ #define CommHSCheckStatus 39 /*!< Check the status of the hi-speed port */ #define ReadSemData 40 /*!< Read motor semaphore data */ #define WriteSemData 41 /*!< Write motor semaphore data */ #define ComputeCalibValue 42 /*!< Compute a calibration value */ #define UpdateCalibCacheInfo 43 /*!< Update sensor calibration cache information */ #define DatalogWrite 44 /*!< Write to the datalog */ #define DatalogGetTimes 45 /*!< Get datalog timing information */ #define SetSleepTimeoutVal 46 /*!< Set the NXT sleep timeout value */ #define ListFiles 47 /*!< List files that match the specified filename pattern */ #ifdef __ENHANCED_FIRMWARE #define IOMapReadByID 78 /*!< Read data from one of the firmware module's IOMap structures using the module's ID */ #define IOMapWriteByID 79 /*!< Write data to one of the firmware module's IOMap structures using the module's ID */ #define DisplayExecuteFunction 80 /*!< Execute one of the Display module's internal functions */ #define CommExecuteFunction 81 /*!< Execute one of the Comm module's internal functions */ #define LoaderExecuteFunction 82 /*!< Execute one of the Loader module's internal functions */ #define FileFindFirst 83 /*!< Start a search for a file using a filename pattern */ #define FileFindNext 84 /*!< Continue searching for a file */ #define FileOpenWriteLinear 85 /*!< Open a linear file for writing */ #define FileOpenWriteNonLinear 86 /*!< Open a non-linear file for writing */ #define FileOpenReadLinear 87 /*!< Open a linear file for reading */ #define CommHSControl 88 /*!< Control the hi-speed port */ #define CommLSWriteEx 89 /*!< Write to a lowspeed (aka I2C) device with optional restart on read */ #define FileSeek 90 /*!< Seek to a specific position in an open file */ #define FileResize 91 /*!< Resize a file (not yet implemented) */ #define DrawGraphicArray 92 /*!< Draw a graphic image from a byte array to the LCD screen */ #define DrawPolygon 93 /*!< Draw a polygon on the LCD screen */ #define DrawEllipse 94 /*!< Draw an ellipse on the LCD screen */ #define DrawFont 95 /*!< Draw text using a custom RIC-based font to the LCD screen */ #define MemoryManager 96 /*!< Read memory manager information, optionally compacting the dataspace first */ #define ReadLastResponse 97 /*!< Read the last response packet received by the NXT. Optionally clear the value after reading it. */ #define FileTell 98 /*!< Return the current file position in an open file */ #endif #endif /** @} */ // end of SysCallConstants group /** @} */ // end of CommandModuleConstants group /** @addtogroup DisplayModuleConstants * @{ */ /** @defgroup LineConstants Line number constants * Line numbers for use with DrawText system function. * \sa SysDrawText(), TextOut(), NumOut() * @{ */ #define LCD_LINE8 0 /*!< The 8th line of the LCD screen */ #define LCD_LINE7 8 /*!< The 7th line of the LCD screen */ #define LCD_LINE6 16 /*!< The 6th line of the LCD screen */ #define LCD_LINE5 24 /*!< The 5th line of the LCD screen */ #define LCD_LINE4 32 /*!< The 4th line of the LCD screen */ #define LCD_LINE3 40 /*!< The 3rd line of the LCD screen */ #define LCD_LINE2 48 /*!< The 2nd line of the LCD screen */ #define LCD_LINE1 56 /*!< The 1st line of the LCD screen */ /** @} */ // end of LineConstants group /** @} */ // end of DisplayModuleConstants group /** @addtogroup CommandModuleConstants * @{ */ /** @defgroup TimeConstants Time constants * Constants for use with the Wait() function. * \sa Wait() * @{ */ #define MS_1 1 /*!< 1 millisecond */ #define MS_2 2 /*!< 2 milliseconds */ #define MS_3 3 /*!< 3 milliseconds */ #define MS_4 4 /*!< 4 milliseconds */ #define MS_5 5 /*!< 5 milliseconds */ #define MS_6 6 /*!< 6 milliseconds */ #define MS_7 7 /*!< 7 milliseconds */ #define MS_8 8 /*!< 8 milliseconds */ #define MS_9 9 /*!< 9 milliseconds */ #define MS_10 10 /*!< 10 milliseconds */ #define MS_20 20 /*!< 20 milliseconds */ #define MS_30 30 /*!< 30 milliseconds */ #define MS_40 40 /*!< 40 milliseconds */ #define MS_50 50 /*!< 50 milliseconds */ #define MS_60 60 /*!< 60 milliseconds */ #define MS_70 70 /*!< 70 milliseconds */ #define MS_80 80 /*!< 80 milliseconds */ #define MS_90 90 /*!< 90 milliseconds */ #define MS_100 100 /*!< 100 milliseconds */ #define MS_150 150 /*!< 150 milliseconds */ #define MS_200 200 /*!< 200 milliseconds */ #define MS_250 250 /*!< 250 milliseconds */ #define MS_300 300 /*!< 300 milliseconds */ #define MS_350 350 /*!< 350 milliseconds */ #define MS_400 400 /*!< 400 milliseconds */ #define MS_450 450 /*!< 450 milliseconds */ #define MS_500 500 /*!< 500 milliseconds */ #define MS_600 600 /*!< 600 milliseconds */ #define MS_700 700 /*!< 700 milliseconds */ #define MS_800 800 /*!< 800 milliseconds */ #define MS_900 900 /*!< 900 milliseconds */ #define SEC_1 1000 /*!< 1 second */ #define SEC_2 2000 /*!< 2 seconds */ #define SEC_3 3000 /*!< 3 seconds */ #define SEC_4 4000 /*!< 4 seconds */ #define SEC_5 5000 /*!< 5 seconds */ #define SEC_6 6000 /*!< 6 seconds */ #define SEC_7 7000 /*!< 7 seconds */ #define SEC_8 8000 /*!< 8 seconds */ #define SEC_9 9000 /*!< 9 seconds */ #define SEC_10 10000 /*!< 10 seconds */ #define SEC_15 15000 /*!< 15 seconds */ #define SEC_20 20000 /*!< 20 seconds */ #define SEC_30 30000 /*!< 30 seconds */ #define MIN_1 60000 /*!< 1 minute */ /** @} */ // end of TimeConstants group /** @} */ // end of CommandModuleConstants group /** @addtogroup CommModuleConstants * @{ */ /** @defgroup MailboxConstants Mailbox constants * Mailbox number constants should be used to avoid confusing NXT-G users. * \sa SysMessageWrite(), SysMessageRead(), SendMessage(), ReceiveMessage(), * SendRemoteBool(), SendRemoteNumber(), SendRemoteString(), * SendResponseBool(), SendResponseNumber(), SendResponseString(), * ReceiveRemoteBool(), ReceiveRemoteNumber(), ReceiveRemoteString(), * ReceiveRemoteMessageEx(), RemoteMessageRead(), RemoteMessageWrite() * @{ */ #define MAILBOX1 0 /*!< Mailbox number 1 */ #define MAILBOX2 1 /*!< Mailbox number 2 */ #define MAILBOX3 2 /*!< Mailbox number 3 */ #define MAILBOX4 3 /*!< Mailbox number 4 */ #define MAILBOX5 4 /*!< Mailbox number 5 */ #define MAILBOX6 5 /*!< Mailbox number 6 */ #define MAILBOX7 6 /*!< Mailbox number 7 */ #define MAILBOX8 7 /*!< Mailbox number 8 */ #define MAILBOX9 8 /*!< Mailbox number 9 */ #define MAILBOX10 9 /*!< Mailbox number 10 */ /** @} */ // end of MailboxConstants group /** @} */ // end of CommModuleConstants group /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup ModuleNameConstants * @{ */ #define CommandModuleName "Command.mod" /*!< The command module name */ #define IOCtrlModuleName "IOCtrl.mod" /*!< The IOCtrl module name */ #define LoaderModuleName "Loader.mod" /*!< The Loader module name */ #define SoundModuleName "Sound.mod" /*!< The sound module name */ #define ButtonModuleName "Button.mod" /*!< The button module name */ #define UIModuleName "Ui.mod" /*!< The Ui module name */ #define InputModuleName "Input.mod" /*!< The input module name. */ #define OutputModuleName "Output.mod" /*!< The output module name */ #define LowSpeedModuleName "Low Speed.mod" /*!< The low speed module name */ #define DisplayModuleName "Display.mod" /*!< The display module name */ #define CommModuleName "Comm.mod" /*!< The Comm module name */ /** @} */ // end of ModuleNameConstants group /** @addtogroup ModuleIDConstants * @{ */ #define CommandModuleID 0x00010001 /*!< The command module ID */ #define IOCtrlModuleID 0x00060001 /*!< The IOCtrl module ID */ #define LoaderModuleID 0x00090001 /*!< The Loader module ID */ #define SoundModuleID 0x00080001 /*!< The sound module ID */ #define ButtonModuleID 0x00040001 /*!< The button module ID */ #define UIModuleID 0x000C0001 /*!< The Ui module ID */ #define InputModuleID 0x00030001 /*!< The input module ID */ #define OutputModuleID 0x00020001 /*!< The output module ID */ #define LowSpeedModuleID 0x000B0001 /*!< The low speed module ID */ #define DisplayModuleID 0x000A0001 /*!< The display module ID */ #define CommModuleID 0x00050001 /*!< The Comm module ID */ /** @} */ // end of ModuleIDConstants group /** @} */ // end of NXTFirmwareModules group /** @addtogroup CommandModule * @{ */ /** @addtogroup CommandModuleConstants * @{ */ //Status/error codes for the VM internal code and bytecodes #define STAT_MSG_EMPTY_MAILBOX 64 /*!< Specified mailbox contains no new messages */ #define STAT_COMM_PENDING 32 /*!< Pending setup operation in progress */ #define POOL_MAX_SIZE 32768 /*!< Maximum size of memory pool, in bytes */ /** @defgroup CommandVMState VM state constants * Constants defining possible VM states. * @{ */ #define TIMES_UP 6 /*!< VM time is up */ #define ROTATE_QUEUE 5 /*!< VM should rotate queue */ #define STOP_REQ 4 /*!< VM should stop executing program */ #define BREAKOUT_REQ 3 /*!< VM should break out of current thread */ #define CLUMP_SUSPEND 2 /*!< VM should suspend thread */ #define CLUMP_DONE 1 /*!< VM has finished executing thread */ /** @} */ // end of CommandVMState group #define NO_ERR 0 /*!< Successful execution of the specified command */ /** @defgroup CommandFatalErrors Fatal errors * Constants defining various fatal error conditions. * @{ */ #define ERR_ARG -1 /*!< 0xFF Bad arguments */ #define ERR_INSTR -2 /*!< 0xFE Illegal bytecode instruction */ #define ERR_FILE -3 /*!< 0xFD Malformed file contents */ #define ERR_VER -4 /*!< 0xFC Version mismatch between firmware and compiler */ #define ERR_MEM -5 /*!< 0xFB Insufficient memory available */ #define ERR_BAD_PTR -6 /*!< 0xFA Someone passed us a bad pointer! */ #define ERR_CLUMP_COUNT -7 /*!< 0xF9 (FileClumpCount == 0 || FileClumpCount >= NOT_A_CLUMP) */ #define ERR_NO_CODE -8 /*!< 0xF8 VarsCmd.CodespaceCount == 0 */ #define ERR_INSANE_OFFSET -9 /*!< 0xF7 CurrOffset != (DataSize - VarsCmd.CodespaceCount * 2) */ #define ERR_BAD_POOL_SIZE -10 /*!< 0xF6 VarsCmd.PoolSize > POOL_MAX_SIZE */ #define ERR_LOADER_ERR -11 /*!< 0xF5 LOADER_ERR(LStatus) != SUCCESS || pData == NULL || DataSize == 0 */ #define ERR_SPOTCHECK_FAIL -12 /*!< 0xF4 ((UBYTE*)(VarsCmd.pCodespace) < pData) (c_cmd.c 1893) */ #define ERR_NO_ACTIVE_CLUMP -13 /*!< 0xF3 VarsCmd.RunQ.Head == NOT_A_CLUMP */ #define ERR_DEFAULT_OFFSETS -14 /*!< 0xF2 (DefaultsOffset != FileOffsets.DynamicDefaults) || (DefaultsOffset + FileOffsets.DynamicDefaultsSize != FileOffsets.DSDefaultsSize) */ #define ERR_MEMMGR_FAIL -15 /*!< 0xF1 (UBYTE *)VarsCmd.MemMgr.pDopeVectorArray != VarsCmd.pDataspace + DV_ARRAY[0].Offset */ #define ERR_NON_FATAL -16 /*!< Fatal errors are greater than this value */ /** @} */ // end of CommandFatalErrors group /** @defgroup CommandGenErrors General errors * Constants defining general error conditions. * @{ */ #define ERR_INVALID_PORT -16 /*!< 0xF0 Bad input or output port specified */ #define ERR_INVALID_FIELD -17 /*!< 0xEF Attempted to access invalid field of a structure */ #define ERR_INVALID_QUEUE -18 /*!< 0xEE Illegal queue ID specified */ #define ERR_INVALID_SIZE -19 /*!< 0xED Illegal size specified */ #define ERR_NO_PROG -20 /*!< 0xEC No active program */ /** @} */ // end of CommandGenErrors group /** @defgroup CommandCommErrors Communications specific errors * Constants defining communication error conditions. * @{ */ #define ERR_COMM_CHAN_NOT_READY -32 /*!< 0xE0 Specified channel/connection not configured or busy */ #define ERR_COMM_CHAN_INVALID -33 /*!< 0xDF Specified channel/connection is not valid */ #define ERR_COMM_BUFFER_FULL -34 /*!< 0xDE No room in comm buffer */ #define ERR_COMM_BUS_ERR -35 /*!< 0xDD Something went wrong on the communications bus */ /** @} */ // end of CommandCommErrors group /** @defgroup CommandRCErrors Remote control (direct commands) errors * Constants defining errors that can occur during remote control (RC) direct * command operations. * @{ */ #define ERR_RC_ILLEGAL_VAL -64 /*!< 0xC0 Data contains out-of-range values */ #define ERR_RC_BAD_PACKET -65 /*!< 0xBF Clearly insane packet */ #define ERR_RC_UNKNOWN_CMD -66 /*!< 0xBE Unknown command opcode */ #define ERR_RC_FAILED -67 /*!< 0xBD Request failed (i.e. specified file not found) */ /** @} */ // end of CommandRCErrors group /** @defgroup CommandProgStatus Program status constants * Constants defining various states of the command module virtual machine. * @{ */ #define PROG_IDLE 0 /*!< Program state is idle */ #define PROG_OK 1 /*!< Program state is okay */ #define PROG_RUNNING 2 /*!< Program is running */ #define PROG_ERROR 3 /*!< A program error has occurred */ #define PROG_ABORT 4 /*!< Program has been aborted */ #define PROG_RESET 5 /*!< Program has been reset */ /** @} */ // end of CommandProgStatus group /** @defgroup CommandIOMAP Command module IOMAP offsets * Constant offsets into the Command module IOMAP structure. * @{ */ #define CommandOffsetFormatString 0 /*!< Offset to the format string */ #define CommandOffsetPRCHandler 16 /*!< Offset to the RC Handler function pointer */ #define CommandOffsetTick 20 /*!< Offset to the VM's current tick */ #define CommandOffsetOffsetDS 24 /*!< Offset to the running program's data space (DS) */ #define CommandOffsetOffsetDVA 26 /*!< Offset to the running program's DOPE vector address (DVA) */ #define CommandOffsetProgStatus 28 /*!< Offset to the running program's status */ #define CommandOffsetAwake 29 /*!< Offset to the VM's awake state */ #define CommandOffsetActivateFlag 30 /*!< Offset to the activate flag */ #define CommandOffsetDeactivateFlag 31 /*!< Offset to the deactivate flag */ #define CommandOffsetFileName 32 /*!< Offset to the running program's filename */ #define CommandOffsetMemoryPool 52 /*!< Offset to the VM's memory pool */ #if __FIRMWARE_VERSION > 107 #define CommandOffsetSyncTime 32820 /*!< Offset to the VM sync time */ #define CommandOffsetSyncTick 32824 /*!< Offset to the VM sync tick */ #endif /** @} */ // end of CommandIOMAP group /** @} */ // end of CommandModuleConstants group /** @} */ // end of CommandModule group /** @addtogroup IOCtrlModule * @{ */ /** @defgroup IOCtrlModuleConstants IOCtrl module constants * Constants that are part of the NXT firmware's IOCtrl module. * @{ */ /** @defgroup IOCtrlPO PowerOn constants * Use these constants to power down the NXT or boot it into SAMBA * (aka firmware download) mode. * @{ */ #define IOCTRL_POWERDOWN 0x5A00 /*!< Power down the NXT */ #define IOCTRL_BOOT 0xA55A /*!< Reboot the NXT into SAMBA mode */ /** @} */ // end of IOCtrlPO group /** @defgroup IOCtrlIOMAP IOCtrl module IOMAP offsets * Constant offsets into the IOCtrl module IOMAP structure. * @{ */ #define IOCtrlOffsetPowerOn 0 /*!< Offset to power on field */ /** @} */ // end of IOCtrlIOMAP group /** @} */ // end of IOCtrlModuleConstants group /** @} */ // end of IOCtrlModule group /** @addtogroup LoaderModule * @{ */ /** @defgroup LoaderModuleConstants Loader module constants * Constants that are part of the NXT firmware's Loader module. * @{ */ /** @defgroup LoaderIOMAP Loader module IOMAP offsets * Constant offsets into the Loader module IOMAP structure. * @{ */ #define LoaderOffsetPFunc 0 /*!< Offset to the Loader module function pointer */ #define LoaderOffsetFreeUserFlash 4 /*!< Offset to the amount of free user flash */ /** @} */ // end of LoaderIOMAP group #define EOF -1 /*!< A constant representing end of file */ #define NULL 0 /*!< A constant representing NULL */ /** @defgroup LoaderErrors Loader module error codes * Error codes returned by functions in the Loader module (file access). * @{ */ #define LDR_SUCCESS 0x0000 /*!< The function completed successfully. */ #define LDR_INPROGRESS 0x0001 /*!< The function is executing but has not yet completed. */ #define LDR_REQPIN 0x0002 /*!< A PIN exchange request is in progress. */ #define LDR_NOMOREHANDLES 0x8100 /*!< All available file handles are in use. */ #define LDR_NOSPACE 0x8200 /*!< Not enough free flash memory for the specified file size. */ #define LDR_NOMOREFILES 0x8300 /*!< The maximum number of files has been reached. */ #define LDR_EOFEXPECTED 0x8400 /*!< EOF expected. */ #define LDR_ENDOFFILE 0x8500 /*!< The end of the file has been reached. */ #define LDR_NOTLINEARFILE 0x8600 /*!< The specified file is not linear. */ #define LDR_FILENOTFOUND 0x8700 /*!< No files matched the search criteria. */ #define LDR_HANDLEALREADYCLOSED 0x8800 /*!< The file handle has already been closed. */ #define LDR_NOLINEARSPACE 0x8900 /*!< Not enough linear flash memory is available. */ #define LDR_UNDEFINEDERROR 0x8A00 /*!< An undefined error has occurred. */ #define LDR_FILEISBUSY 0x8B00 /*!< The file is already being used. */ #define LDR_NOWRITEBUFFERS 0x8C00 /*!< No more write buffers are available. */ #define LDR_APPENDNOTPOSSIBLE 0x8D00 /*!< Only datafiles can be appended to. */ #define LDR_FILEISFULL 0x8E00 /*!< The allocated file size has been filled. */ #define LDR_FILEEXISTS 0x8F00 /*!< A file with the same name already exists. */ #define LDR_MODULENOTFOUND 0x9000 /*!< No modules matched the specified search criteria. */ #define LDR_OUTOFBOUNDARY 0x9100 /*!< Specified IOMap offset is outside the bounds of the IOMap. */ #define LDR_ILLEGALFILENAME 0x9200 /*!< Filename length to long or attempted open a system file (*.rxe, *.rtm, or *.sys) for writing as a datafile. */ #define LDR_ILLEGALHANDLE 0x9300 /*!< Invalid file handle. */ #define LDR_BTBUSY 0x9400 /*!< The bluetooth system is busy. */ #define LDR_BTCONNECTFAIL 0x9500 /*!< Bluetooth connection attempt failed. */ #define LDR_BTTIMEOUT 0x9600 /*!< A timeout in the bluetooth system has occurred. */ #define LDR_FILETX_TIMEOUT 0x9700 /*!< Error transmitting file: a timeout occurred. */ #define LDR_FILETX_DSTEXISTS 0x9800 /*!< Error transmitting file: destination file exists. */ #define LDR_FILETX_SRCMISSING 0x9900 /*!< Error transmitting file: source file is missing. */ #define LDR_FILETX_STREAMERROR 0x9A00 /*!< Error transmitting file: a stream error occurred. */ #define LDR_FILETX_CLOSEERROR 0x9B00 /*!< Error transmitting file: attempt to close file failed. */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define LDR_INVALIDSEEK 0x9C00 /*!< Invalid file seek operation. */ #endif /** @} */ // end of LoaderErrors group /** @defgroup LoaderFunctionConstants Loader module function constants * Constants defining the functions provided by the Loader module. * @{ */ #define LDR_CMD_OPENREAD 0x80 /*!< Open a file for reading */ #define LDR_CMD_OPENWRITE 0x81 /*!< Open a file for writing */ #define LDR_CMD_READ 0x82 /*!< Read from a file */ #define LDR_CMD_WRITE 0x83 /*!< Write to a file */ #define LDR_CMD_CLOSE 0x84 /*!< Close a file handle */ #define LDR_CMD_DELETE 0x85 /*!< Delete a file */ #define LDR_CMD_FINDFIRST 0x86 /*!< Find the first file matching the specified pattern */ #define LDR_CMD_FINDNEXT 0x87 /*!< Find the next file matching the specified pattern */ #define LDR_CMD_VERSIONS 0x88 /*!< Read firmware version information */ #define LDR_CMD_OPENWRITELINEAR 0x89 /*!< Open a linear file for writing */ #define LDR_CMD_OPENREADLINEAR 0x8A /*!< Open a linear file for reading */ #define LDR_CMD_OPENWRITEDATA 0x8B /*!< Open a data file for writing */ #define LDR_CMD_OPENAPPENDDATA 0x8C /*!< Open a data file for appending */ #if __FIRMWARE_VERSION > 107 #define LDR_CMD_CROPDATAFILE 0x8D /*!< Crop a data file to its used space */ #endif #define LDR_CMD_FINDFIRSTMODULE 0x90 /*!< Find the first module matching the specified pattern */ #define LDR_CMD_FINDNEXTMODULE 0x91 /*!< Find the next module matching the specified pattern */ #define LDR_CMD_CLOSEMODHANDLE 0x92 /*!< Close a module handle */ #define LDR_CMD_IOMAPREAD 0x94 /*!< Read data from a module IOMAP */ #define LDR_CMD_IOMAPWRITE 0x95 /*!< Write data to a module IOMAP */ #define LDR_CMD_BOOTCMD 0x97 /*!< Reboot the NXT into SAMBA mode */ #define LDR_CMD_SETBRICKNAME 0x98 /*!< Set the NXT's brick name */ #define LDR_CMD_BTGETADR 0x9A /*!< Get the NXT's bluetooth brick address */ #define LDR_CMD_DEVICEINFO 0x9B /*!< Read device information */ #define LDR_CMD_DELETEUSERFLASH 0xA0 /*!< Delete all files from user flash memory */ #define LDR_CMD_POLLCMDLEN 0xA1 /*!< Read poll command length */ #define LDR_CMD_POLLCMD 0xA2 /*!< Poll command */ #define LDR_CMD_RENAMEFILE 0xA3 /*!< Rename a file */ #define LDR_CMD_BTFACTORYRESET 0xA4 /*!< Reset bluetooth configuration to factory defaults */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define LDR_CMD_RESIZEDATAFILE 0xD0 /*!< Resize a data file */ #define LDR_CMD_SEEKFROMSTART 0xD1 /*!< Seek from the start of the file */ #define LDR_CMD_SEEKFROMCURRENT 0xD2 /*!< Seek from the current position */ #define LDR_CMD_SEEKFROMEND 0xD3 /*!< Seek from the end of the file */ #endif /** @} */ // end of LoaderFunctionConstants group /** @} */ // end of LoaderModuleConstants group /** @} */ // end of LoaderModule group /** @addtogroup SoundModule * @{ */ /** @defgroup SoundModuleConstants Sound module constants * Constants that are part of the NXT firmware's Sound module. * @{ */ /** @defgroup SoundFlagsConstants SoundFlags constants * Constants for use with the SoundFlags() function. * \sa SoundFlags() * @{ */ #define SOUND_FLAGS_IDLE 0x00 /*!< R - Sound is idle */ #define SOUND_FLAGS_UPDATE 0x01 /*!< W - Make changes take effect */ #define SOUND_FLAGS_RUNNING 0x02 /*!< R - Currently processing a tone or file */ /** @} */ // end of SoundFlagsConstants group /** @defgroup SoundStateConstants SoundState constants * Constants for use with the SoundState() function. * \sa SoundState() * @{ */ #define SOUND_STATE_IDLE 0x00 /*!< R - Idle, ready for start sound (SOUND_UPDATE) */ #define SOUND_STATE_FILE 0x02 /*!< R - Processing a file of sound/melody data */ #define SOUND_STATE_TONE 0x03 /*!< R - Processing a play tone request */ #define SOUND_STATE_STOP 0x04 /*!< W - Stop sound immediately and close hardware */ /** @} */ // end of SoundStateConstants group /** @defgroup SoundModeConstants SoundMode constants * Constants for use with the SoundMode() function. * \sa SoundMode() * @{ */ #define SOUND_MODE_ONCE 0x00 /*!< W - Only play file once */ #define SOUND_MODE_LOOP 0x01 /*!< W - Play file until writing SOUND_STATE_STOP into SoundState */ #define SOUND_MODE_TONE 0x02 /*!< W - Play tone specified in Frequency for Duration ms */ /** @} */ // end of SoundModeConstants group /** @defgroup SoundIOMAP Sound module IOMAP offsets * Constant offsets into the Sound module IOMAP structure. * @{ */ #define SoundOffsetFreq 0 /*!< RW - Tone frequency [Hz] (2 bytes) */ #define SoundOffsetDuration 2 /*!< RW - Tone duration [mS] (2 bytes) */ #define SoundOffsetSampleRate 4 /*!< RW - Sound file sample rate [2000..16000] (2 bytes) */ #define SoundOffsetSoundFilename 6 /*!< RW - Sound/melody filename (20 bytes) */ #define SoundOffsetFlags 26 /*!< RW - Play flag - described above (1 byte) \ref SoundFlagsConstants */ #define SoundOffsetState 27 /*!< RW - Play state - described above (1 byte) \ref SoundStateConstants */ #define SoundOffsetMode 28 /*!< RW - Play mode - described above (1 byte) \ref SoundModeConstants */ #define SoundOffsetVolume 29 /*!< RW - Sound/melody volume [0..4] 0 = off (1 byte) */ /** @} */ // end of SoundIOMAP group /** @defgroup SoundMisc Sound module miscellaneous constants * Constants defining miscellaneous sound module aspects. * @{ */ #define FREQUENCY_MIN 220 /*!< Minimum frequency [Hz] */ #define FREQUENCY_MAX 14080 /*!< Maximum frequency [Hz] */ #define SAMPLERATE_MIN 2000 /*!< Min sample rate [sps] */ #define SAMPLERATE_DEFAULT 8000 /*!< Default sample rate [sps] */ #define SAMPLERATE_MAX 16000 /*!< Max sample rate [sps] */ /** @} */ // end of SoundMisc group /** @defgroup ToneConstants Tone constants * Constants for use in the SoundPlayTone() API function. * \sa SoundPlayTone() * @{ */ #define TONE_A3 220 /*!< Third octave A */ #define TONE_AS3 233 /*!< Third octave A sharp */ #define TONE_B3 247 /*!< Third octave B */ #define TONE_C4 262 /*!< Fourth octave C */ #define TONE_CS4 277 /*!< Fourth octave C sharp */ #define TONE_D4 294 /*!< Fourth octave D */ #define TONE_DS4 311 /*!< Fourth octave D sharp */ #define TONE_E4 330 /*!< Fourth octave E */ #define TONE_F4 349 /*!< Fourth octave F */ #define TONE_FS4 370 /*!< Fourth octave F sharp */ #define TONE_G4 392 /*!< Fourth octave G */ #define TONE_GS4 415 /*!< Fourth octave G sharp */ #define TONE_A4 440 /*!< Fourth octave A */ #define TONE_AS4 466 /*!< Fourth octave A sharp */ #define TONE_B4 494 /*!< Fourth octave B */ #define TONE_C5 523 /*!< Fifth octave C */ #define TONE_CS5 554 /*!< Fifth octave C sharp */ #define TONE_D5 587 /*!< Fifth octave D */ #define TONE_DS5 622 /*!< Fifth octave D sharp */ #define TONE_E5 659 /*!< Fifth octave E */ #define TONE_F5 698 /*!< Fifth octave F */ #define TONE_FS5 740 /*!< Fifth octave F sharp */ #define TONE_G5 784 /*!< Fifth octave G */ #define TONE_GS5 831 /*!< Fifth octave G sharp */ #define TONE_A5 880 /*!< Fifth octave A */ #define TONE_AS5 932 /*!< Fifth octave A sharp */ #define TONE_B5 988 /*!< Fifth octave B */ #define TONE_C6 1047 /*!< Sixth octave C */ #define TONE_CS6 1109 /*!< Sixth octave C sharp */ #define TONE_D6 1175 /*!< Sixth octave D */ #define TONE_DS6 1245 /*!< Sixth octave D sharp */ #define TONE_E6 1319 /*!< Sixth octave E */ #define TONE_F6 1397 /*!< Sixth octave F */ #define TONE_FS6 1480 /*!< Sixth octave F sharp */ #define TONE_G6 1568 /*!< Sixth octave G */ #define TONE_GS6 1661 /*!< Sixth octave G sharp */ #define TONE_A6 1760 /*!< Sixth octave A */ #define TONE_AS6 1865 /*!< Sixth octave A sharp */ #define TONE_B6 1976 /*!< Sixth octave B */ #define TONE_C7 2093 /*!< Seventh octave C */ #define TONE_CS7 2217 /*!< Seventh octave C sharp */ #define TONE_D7 2349 /*!< Seventh octave D */ #define TONE_DS7 2489 /*!< Seventh octave D sharp */ #define TONE_E7 2637 /*!< Seventh octave E */ #define TONE_F7 2794 /*!< Seventh octave F */ #define TONE_FS7 2960 /*!< Seventh octave F sharp */ #define TONE_G7 3136 /*!< Seventh octave G */ #define TONE_GS7 3322 /*!< Seventh octave G sharp */ #define TONE_A7 3520 /*!< Seventh octave A */ #define TONE_AS7 3729 /*!< Seventh octave A sharp */ #define TONE_B7 3951 /*!< Seventh octave B */ /** @} */ // end of ToneConstants group /** @} */ // end of SoundModuleConstants group /** @} */ // end of SoundModule group /** @addtogroup ButtonModule * @{ */ /** @defgroup ButtonModuleConstants Button module constants * Constants that are part of the NXT firmware's Button module. * @{ */ /** @defgroup ButtonNameConstants Button name constants * Constants to specify which button to use with button module functions. * \sa ButtonPressed(), ButtonState(), ButtonCount(), ReadButtonEx(), * SysReadButton(), ReadButtonType * @{ */ #define BTN1 0 /*!< The exit button. */ #define BTN2 1 /*!< The right button. */ #define BTN3 2 /*!< The left button. */ #define BTN4 3 /*!< The enter button. */ #define BTNEXIT BTN1 /*!< The exit button. */ #define BTNRIGHT BTN2 /*!< The right button. */ #define BTNLEFT BTN3 /*!< The left button. */ #define BTNCENTER BTN4 /*!< The enter button. */ #define NO_OF_BTNS 4 /*!< The number of NXT buttons. */ /** @} */ // end of ButtonNameConstants group /** @defgroup ButtonStateConstants ButtonState constants * Constants for use with the ButtonState() function. The _EV values can be * combined together using a bitwise OR operation. * \sa ButtonState() * @{ */ #define BTNSTATE_PRESSED_EV 0x01 /*!< Button is in the pressed state. */ #define BTNSTATE_SHORT_RELEASED_EV 0x02 /*!< Button is in the short released state. */ #define BTNSTATE_LONG_PRESSED_EV 0x04 /*!< Button is in the long pressed state. */ #define BTNSTATE_LONG_RELEASED_EV 0x08 /*!< Button is in the long released state. */ #define BTNSTATE_PRESSED_STATE 0x80 /*!< A bitmask for the button pressed state */ #define BTNSTATE_NONE 0x10 /*!< The default button state. */ /** @} */ // end of ButtonStateConstants group /** @defgroup ButtonIOMAP Button module IOMAP offsets * Constant offsets into the Button module IOMAP structure. * @{ */ #define ButtonOffsetPressedCnt(b) (((b)*8)+0) /*!< Offset to the PressedCnt field. This field stores the press count. */ #define ButtonOffsetLongPressCnt(b) (((b)*8)+1) /*!< Offset to the LongPressCnt field. This field stores the long press count.*/ #define ButtonOffsetShortRelCnt(b) (((b)*8)+2) /*!< Offset to the ShortRelCnt field. This field stores the short release count. */ #define ButtonOffsetLongRelCnt(b) (((b)*8)+3) /*!< Offset to the LongRelCnt field. This field stores the long release count. */ #define ButtonOffsetRelCnt(b) (((b)*8)+4) /*!< Offset to the RelCnt field. This field stores the release count. */ #define ButtonOffsetState(b) ((b)+32) /*!< Offset to the State field. This field stores the current button state. */ /** @} */ // end of ButtonIOMAP group /** @} */ // end of ButtonModuleConstants group /** @} */ // end of ButtonModule group /** @addtogroup UiModule * @{ */ /** @defgroup UiModuleConstants Ui module constants * Constants that are part of the NXT firmware's Ui module. * @{ */ /** @defgroup UiFlagsConstants CommandFlags constants * Constants for use with the CommandFlags() function. * \sa CommandFlags() * @{ */ #define UI_FLAGS_UPDATE 0x01 /*!< W - Make changes take effect */ #define UI_FLAGS_DISABLE_LEFT_RIGHT_ENTER 0x02 /*!< RW - Disable left, right and enter button */ #define UI_FLAGS_DISABLE_EXIT 0x04 /*!< RW - Disable exit button */ #define UI_FLAGS_REDRAW_STATUS 0x08 /*!< W - Redraw entire status line */ #define UI_FLAGS_RESET_SLEEP_TIMER 0x10 /*!< W - Reset sleep timeout timer */ #define UI_FLAGS_EXECUTE_LMS_FILE 0x20 /*!< W - Execute LMS file in "LMSfilename" (Try It) */ #define UI_FLAGS_BUSY 0x40 /*!< R - UI busy running or datalogging (popup disabled) */ #define UI_FLAGS_ENABLE_STATUS_UPDATE 0x80 /*!< W - Enable status line to be updated */ /** @} */ // end of UiFlagsConstants group /** @defgroup UiStateConstants UIState constants * Constants for use with the UIState() function. * \sa UIState() * @{ */ #define UI_STATE_INIT_DISPLAY 0 /*!< RW - Init display and load font, menu etc. */ #define UI_STATE_INIT_LOW_BATTERY 1 /*!< R - Low battery voltage at power on */ #define UI_STATE_INIT_INTRO 2 /*!< R - Display intro */ #define UI_STATE_INIT_WAIT 3 /*!< RW - Wait for initialization end */ #define UI_STATE_INIT_MENU 4 /*!< RW - Init menu system */ #define UI_STATE_NEXT_MENU 5 /*!< RW - Next menu icons ready for drawing */ #define UI_STATE_DRAW_MENU 6 /*!< RW - Execute function and draw menu icons */ #define UI_STATE_TEST_BUTTONS 7 /*!< RW - Wait for buttons to be pressed */ #define UI_STATE_LEFT_PRESSED 8 /*!< RW - Load selected function and next menu id */ #define UI_STATE_RIGHT_PRESSED 9 /*!< RW - Load selected function and next menu id */ #define UI_STATE_ENTER_PRESSED 10 /*!< RW - Load selected function and next menu id */ #define UI_STATE_EXIT_PRESSED 11 /*!< RW - Load selected function and next menu id */ #define UI_STATE_CONNECT_REQUEST 12 /*!< RW - Request for connection accept */ #define UI_STATE_EXECUTE_FILE 13 /*!< RW - Execute file in "LMSfilename" */ #define UI_STATE_EXECUTING_FILE 14 /*!< R - Executing file in "LMSfilename" */ #define UI_STATE_LOW_BATTERY 15 /*!< R - Low battery at runtime */ #define UI_STATE_BT_ERROR 16 /*!< R - BT error */ /** @} */ // end of UiStateConstants group /** @defgroup UiButtonConstants UIButton constants * Constants for use with the UIButton() function. * \sa UIButton() * @{ */ #define UI_BUTTON_NONE 0 /*!< R - Button inserted are executed */ #define UI_BUTTON_LEFT 1 /*!< W - Insert left arrow button */ #define UI_BUTTON_ENTER 2 /*!< W - Insert enter button */ #define UI_BUTTON_RIGHT 3 /*!< W - Insert right arrow button */ #define UI_BUTTON_EXIT 4 /*!< W - Insert exit button */ /** @} */ // end of UiButtonConstants group /** @defgroup UiBluetoothStateConstants BluetoothState constants * Constants for use with the BluetoothState() function. * \sa BluetoothState() * @{ */ #define UI_BT_STATE_VISIBLE 0x01 /*!< RW - BT visible */ #define UI_BT_STATE_CONNECTED 0x02 /*!< RW - BT connected to something */ #define UI_BT_STATE_OFF 0x04 /*!< RW - BT power off */ #define UI_BT_ERROR_ATTENTION 0x08 /*!< W - BT error attention */ #define UI_BT_CONNECT_REQUEST 0x40 /*!< RW - BT get connect accept in progress */ #define UI_BT_PIN_REQUEST 0x80 /*!< RW - BT get pin code */ /** @} */ // end of UiBluetoothStateConstants group /** @defgroup UiVMRunStateConstants VM run state constants * Constants for use with the VMRunState() function. * \sa VMRunState() * @{ */ #define UI_VM_IDLE 0 /*!< VM_IDLE: Just sitting around. Request to run program will lead to ONE of the VM_RUN* states. */ #define UI_VM_RUN_FREE 1 /*!< VM_RUN_FREE: Attempt to run as many instructions as possible within our timeslice */ #define UI_VM_RUN_SINGLE 2 /*!< VM_RUN_SINGLE: Run exactly one instruction per timeslice */ #define UI_VM_RUN_PAUSE 3 /*!< VM_RUN_PAUSE: Program still "active", but someone has asked us to pause */ #define UI_VM_RESET1 4 /*!< VM_RESET1: Initialize state variables and some I/O devices -- executed when programs end */ #define UI_VM_RESET2 5 /*!< VM_RESET2: Final clean up and return to IDLE */ /** @} */ // end of UiVMRunStateConstants group /** @defgroup UiIOMAP Ui module IOMAP offsets * Constant offsets into the Ui module IOMAP structure. * @{ */ #define UIOffsetPMenu 0 /*!< W - Pointer to menu file (4 bytes) */ #define UIOffsetBatteryVoltage 4 /*!< R - Battery voltage in millivolts (2 bytes) */ #define UIOffsetLMSfilename 6 /*!< W - LMS filename to execute (Try It) (20 bytes) */ #define UIOffsetFlags 26 /*!< RW - Update command flags (flags enumerated above) (1 byte) */ #define UIOffsetState 27 /*!< RW - UI state (states enumerated above) (1 byte) */ #define UIOffsetButton 28 /*!< RW - Insert button (buttons enumerated above) (1 byte) */ #define UIOffsetRunState 29 /*!< W - VM Run state (0 = stopped, 1 = running) (1 byte) */ #define UIOffsetBatteryState 30 /*!< W - Battery state (0..4 capacity) (1 byte) */ #define UIOffsetBluetoothState 31 /*!< W - Bluetooth state (0=on, 1=visible, 2=conn, 3=conn.visible, 4=off, 5=dfu) (1 byte) */ #define UIOffsetUsbState 32 /*!< W - Usb state (0=disconnected, 1=connected, 2=working) (1 byte) */ #define UIOffsetSleepTimeout 33 /*!< RW - Sleep timeout time (min) (1 byte) */ #define UIOffsetSleepTimer 34 /*!< RW - Sleep timer (min) (1 byte) */ #define UIOffsetRechargeable 35 /*!< R - Rechargeable battery (0 = no, 1 = yes) (1 byte) */ #define UIOffsetVolume 36 /*!< RW - Volume used in UI (0 - 4) (1 byte) */ #define UIOffsetError 37 /*!< W - Error code (1 byte) */ #define UIOffsetOBPPointer 38 /*!< W - Actual OBP step (0 - 4) (1 byte) */ #define UIOffsetForceOff 39 /*!< W - Force off (> 0 = off) (1 byte) */ #define UIOffsetAbortFlag 40 /*!< RW - Long Abort (true == use long press to abort) (1 byte) */ /** @} */ // end of UiIOMAP group /** @} */ // end of UiModuleConstants group /** @} */ // end of UiModule group /** @addtogroup InputModule * @{ */ /** @addtogroup InputModuleConstants * @{ */ /** @defgroup NBCInputPortConstants NBC Input port constants * Input port constants are used when calling sensor control API functions. * These constants are intended for use in NBC. * \sa SetSensorType(), SetSensorMode(), S1, S2, S3, S4 * @{ */ #define IN_1 0x00 /*!< Input port 1 */ #define IN_2 0x01 /*!< Input port 2 */ #define IN_3 0x02 /*!< Input port 3 */ #define IN_4 0x03 /*!< Input port 4 */ /** @} */ // end of InputPortConstants group /** @addtogroup InputModuleTypesAndModes * @{ */ /** @defgroup NBCSensorTypeConstants NBC sensor type constants * Use sensor type constants to configure an input port for a specific type * of sensor. These constants are intended for use in NBC. * \sa SetSensorType() * @{ */ #define IN_TYPE_NO_SENSOR 0x00 /*!< No sensor configured */ #define IN_TYPE_SWITCH 0x01 /*!< NXT or RCX touch sensor */ #define IN_TYPE_TEMPERATURE 0x02 /*!< RCX temperature sensor */ #define IN_TYPE_REFLECTION 0x03 /*!< RCX light sensor */ #define IN_TYPE_ANGLE 0x04 /*!< RCX rotation sensor */ #define IN_TYPE_LIGHT_ACTIVE 0x05 /*!< NXT light sensor with light */ #define IN_TYPE_LIGHT_INACTIVE 0x06 /*!< NXT light sensor without light */ #define IN_TYPE_SOUND_DB 0x07 /*!< NXT sound sensor with dB scaling */ #define IN_TYPE_SOUND_DBA 0x08 /*!< NXT sound sensor with dBA scaling */ #define IN_TYPE_CUSTOM 0x09 /*!< NXT custom sensor */ #define IN_TYPE_LOWSPEED 0x0A /*!< NXT I2C digital sensor */ #define IN_TYPE_LOWSPEED_9V 0x0B /*!< NXT I2C digital sensor with 9V power */ #define IN_TYPE_HISPEED 0x0C /*!< NXT Hi-speed port (only S4) */ #if __FIRMWARE_VERSION > 107 #define IN_TYPE_COLORFULL 0x0D /*!< NXT 2.0 color sensor in full color mode */ #define IN_TYPE_COLORRED 0x0E /*!< NXT 2.0 color sensor with red light */ #define IN_TYPE_COLORGREEN 0x0F /*!< NXT 2.0 color sensor with green light */ #define IN_TYPE_COLORBLUE 0x10 /*!< NXT 2.0 color sensor with blue light */ #define IN_TYPE_COLORNONE 0x11 /*!< NXT 2.0 color sensor with no light */ #define IN_TYPE_COLOREXIT 0x12 /*!< NXT 2.0 color sensor internal state */ #endif /** @} */ // end of NBCSensorTypeConstants group /** @defgroup NBCSensorModeConstants NBC sensor mode constants * Use sensor mode constants to configure an input port for the desired * sensor mode. The constants are intended for use in NBC. * \sa SetSensorMode() * @{ */ #define IN_MODE_RAW 0x00 /*!< Raw value from 0 to 1023 */ #define IN_MODE_BOOLEAN 0x20 /*!< Boolean value (0 or 1) */ #define IN_MODE_TRANSITIONCNT 0x40 /*!< Counts the number of boolean transitions */ #define IN_MODE_PERIODCOUNTER 0x60 /*!< Counts the number of boolean periods */ #define IN_MODE_PCTFULLSCALE 0x80 /*!< Scaled value from 0 to 100 */ #define IN_MODE_CELSIUS 0xA0 /*!< RCX temperature sensor value in degrees celcius */ #define IN_MODE_FAHRENHEIT 0xC0 /*!< RCX temperature sensor value in degrees fahrenheit */ #define IN_MODE_ANGLESTEP 0xE0 /*!< RCX rotation sensor (16 ticks per revolution) */ #define IN_MODE_SLOPEMASK 0x1F /*!< Mask for slope parameter added to mode */ #define IN_MODE_MODEMASK 0xE0 /*!< Mask for the mode without any slope value */ /** @} */ // end of NBCSensorModeConstants group /** @} */ // end of InputModuleTypesAndModes group /** @defgroup InputFieldConstants Input field constants * Constants for use with SetInput() and GetInput(). * Each sensor has six fields that are used to define its state. * @{ */ #define TypeField 0 /*!< Type field. Contains one of the sensor type constants. Read/write. */ #define InputModeField 1 /*!< Input mode field. Contains one of the sensor mode constants. Read/write. */ #define RawValueField 2 /*!< Raw value field. Contains the current raw analog sensor value. Read only. */ #define NormalizedValueField 3 /*!< Normalized value field. Contains the current normalized analog sensor value. Read only. */ #define ScaledValueField 4 /*!< Scaled value field. Contains the current scaled analog sensor value. Read/write. */ #define InvalidDataField 5 /*!< Invalid data field. Contains a boolean value indicating whether the sensor data is valid or not. Read/write. */ /** @} */ // end of InputFieldConstants group /** @defgroup InputDigiPinConstants Input port digital pin constants * Constants for use when directly controlling or reading a port's digital pin * state. * @{ */ #define INPUT_DIGI0 0x01 /*!< Digital pin 0 */ #define INPUT_DIGI1 0x02 /*!< Digital pin 1*/ /** @} */ // end of InputDigiPinConstants group #define INPUT_CUSTOMINACTIVE 0x00 /*!< Custom sensor inactive */ #define INPUT_CUSTOM9V 0x01 /*!< Custom sensor 9V */ #define INPUT_CUSTOMACTIVE 0x02 /*!< Custom sensor active */ #define INPUT_INVALID_DATA 0x01 /*!< Invalid data flag */ #if __FIRMWARE_VERSION > 107 /** @defgroup InputColorIdxConstants Color sensor array indices * Constants for use with color sensor value arrays to index RGB and blank * return values. * \sa ReadSensorColorEx(), ReadSensorColorRaw(), SysColorSensorRead(), * ColorSensorReadType * @{ */ #define INPUT_RED 0 /*!< Access the red value from color sensor value arrays */ #define INPUT_GREEN 1 /*!< Access the green value from color sensor value arrays */ #define INPUT_BLUE 2 /*!< Access the blue value from color sensor value arrays */ #define INPUT_BLANK 3 /*!< Access the blank value from color sensor value arrays */ #define INPUT_NO_OF_COLORS 4 /*!< The number of entries in the color sensor value arrays */ /** @} */ // end of InputColorIdxConstants group /** @defgroup InputColorValueConstants Color values * Constants for use with the ColorValue returned by the color sensor in full * color mode. * \sa SensorValue(), SysColorSensorRead(), ColorSensorReadType * @{ */ #define INPUT_BLACKCOLOR 1 /*!< The color value is black */ #define INPUT_BLUECOLOR 2 /*!< The color value is blue */ #define INPUT_GREENCOLOR 3 /*!< The color value is green */ #define INPUT_YELLOWCOLOR 4 /*!< The color value is yellow */ #define INPUT_REDCOLOR 5 /*!< The color value is red */ #define INPUT_WHITECOLOR 6 /*!< The color value is white */ /** @} */ // end of InputColorIdxConstants group /** @defgroup InputColorCalibrationStateConstants Color calibration state constants * Constants for use with the color calibration state function. * \sa ColorCalibrationState() * @{ */ #define INPUT_SENSORCAL 0x01 /*!< The state returned while the color sensor is calibrating */ #define INPUT_SENSOROFF 0x02 /*!< The state returned once calibration has completed */ #define INPUT_RUNNINGCAL 0x20 /*!< Unused calibration state constant */ #define INPUT_STARTCAL 0x40 /*!< Unused calibration state constant */ #define INPUT_RESETCAL 0x80 /*!< Unused calibration state constant */ /** @} */ // end of InputColorCalibrationStateConstants group /** @defgroup InputColorCalibrationConstants Color calibration constants * Constants for use with the color calibration functions. * \sa ColorCalibration(), ColorCalLimits() * @{ */ #define INPUT_CAL_POINT_0 0 /*!< Calibration point 0 */ #define INPUT_CAL_POINT_1 1 /*!< Calibration point 1 */ #define INPUT_CAL_POINT_2 2 /*!< Calibration point 2 */ #define INPUT_NO_OF_POINTS 3 /*!< The number of calibration points */ /** @} */ // end of InputColorCalibrationConstants group #endif /** @defgroup InputIOMAP Input module IOMAP offsets * Constant offsets into the Input module IOMAP structure. * @{ */ #define InputOffsetCustomZeroOffset(p) (((p)*20)+0) /*!< Read/write the zero offset of a custom sensor (2 bytes) uword */ #define InputOffsetADRaw(p) (((p)*20)+2) /*!< Read the AD raw sensor value (2 bytes) uword */ #define InputOffsetSensorRaw(p) (((p)*20)+4) /*!< Read the raw sensor value (2 bytes) uword */ #define InputOffsetSensorValue(p) (((p)*20)+6) /*!< Read/write the scaled sensor value (2 bytes) sword */ #define InputOffsetSensorType(p) (((p)*20)+8) /*!< Read/write the sensor type */ #define InputOffsetSensorMode(p) (((p)*20)+9) /*!< Read/write the sensor mode */ #define InputOffsetSensorBoolean(p) (((p)*20)+10) /*!< Read the sensor boolean value */ #define InputOffsetDigiPinsDir(p) (((p)*20)+11) /*!< Read/write the direction of the Digital pins (1 is output, 0 is input) */ #define InputOffsetDigiPinsIn(p) (((p)*20)+12) /*!< Read/write the status of the digital pins */ #define InputOffsetDigiPinsOut(p) (((p)*20)+13) /*!< Read/write the output level of the digital pins */ #define InputOffsetCustomPctFullScale(p) (((p)*20)+14) /*!< Read/write the Pct full scale of the custom sensor */ #define InputOffsetCustomActiveStatus(p) (((p)*20)+15) /*!< Read/write the active or inactive state of the custom sensor */ #define InputOffsetInvalidData(p) (((p)*20)+16) /*!< Indicates whether data is invalid (1) or valid (0) */ #if __FIRMWARE_VERSION > 107 #define InputOffsetColorCalibration(p, np, nc) (80+((p)*84)+0+((np)*16)+((nc)*4)) /*!< Read/write color calibration point values */ #define InputOffsetColorCalLimits(p, np) (80+((p)*84)+48+((np)*2)) /*!< Read/write color calibration limits */ #define InputOffsetColorADRaw(p, nc) (80+((p)*84)+52+((nc)*2)) /*!< Read AD raw color sensor values */ #define InputOffsetColorSensorRaw(p, nc) (80+((p)*84)+60+((nc)*2)) /*!< Read raw color sensor values */ #define InputOffsetColorSensorValue(p, nc) (80+((p)*84)+68+((nc)*2)) /*!< Read scaled color sensor values */ #define InputOffsetColorBoolean(p, nc) (80+((p)*84)+76+((nc)*2)) /*!< Read color sensor boolean values */ #define InputOffsetColorCalibrationState(p) (80+((p)*84)+80) /*!< Read color sensor calibration state */ #endif /** @} */ // end of InputIOMap group /** @} */ // end of InputModuleConstants group /** @} */ // end of InputModule group /** @addtogroup OutputModule * @{ */ /** @addtogroup OutputModuleConstants * @{ */ /** @defgroup OutputPortConstants Output port constants * Output port constants are used when calling motor control API functions. * @{ */ #define OUT_A 0x00 /*!< Output port A */ #define OUT_B 0x01 /*!< Output port B */ #define OUT_C 0x02 /*!< Output port C */ #define OUT_AB 0x03 /*!< Output ports A and B */ #define OUT_AC 0x04 /*!< Output ports A and C */ #define OUT_BC 0x05 /*!< Output ports B and C */ #define OUT_ABC 0x06 /*!< Output ports A, B, and C */ /** @} */ // end of OutputPortConstants group /** @defgroup PIDConstants PID constants * PID constants are for adjusting the Proportional, Integral, and Derivative * motor controller parameters. * \sa RotateMotorExPID(), RotateMotorPID(), OnFwdExPID(), OnRevExPID(), * \sa OnFwdRegExPID(), OnRevRegExPID(), OnFwdRegPID(), OnRevRegPID(), * \sa OnFwdSyncExPID(), OnRevSyncExPID(), OnFwdSyncPID(), OnRevSyncPID() * @{ */ #define PID_0 0 /*!< PID zero */ #define PID_1 32 /*!< PID one */ #define PID_2 64 /*!< PID two */ #define PID_3 96 /*!< PID three */ #define PID_4 128 /*!< PID four */ #define PID_5 160 /*!< PID five */ #define PID_6 192 /*!< PID six */ #define PID_7 224 /*!< PID seven */ /** @} */ // end of PIDConstants group /** @defgroup OutUFConstants Output port update flag constants * Use these constants to specify which motor values need to be updated. * Update flag constants can be combined with bitwise OR. * \sa SetOutput() * @{ */ #define UF_UPDATE_MODE 0x01 /*!< Commits changes to the \ref OutputModeField output property */ #define UF_UPDATE_SPEED 0x02 /*!< Commits changes to the \ref PowerField output property */ #define UF_UPDATE_TACHO_LIMIT 0x04 /*!< Commits changes to the \ref TachoLimitField output property */ #define UF_UPDATE_RESET_COUNT 0x08 /*!< Resets all rotation counters, cancels the current goal, and resets the rotation error-correction system */ #define UF_UPDATE_PID_VALUES 0x10 /*!< Commits changes to the PID motor regulation properties */ #define UF_UPDATE_RESET_BLOCK_COUNT 0x20 /*!< Resets the NXT-G block-relative rotation counter */ #define UF_UPDATE_RESET_ROTATION_COUNT 0x40 /*!< Resets the program-relative (user) rotation counter */ #define UF_PENDING_UPDATES 0x80 /*!< Are there any pending motor updates? */ /** @} */ // end of OutUFConstants group /** @defgroup TachoResetConstants Tachometer counter reset flags * Use these constants to specify which of the three tachometer counters * should be reset. Reset constants can be combined with bitwise OR. * \sa OnFwdEx(), OnRevEx(), etc... * @{ */ #define RESET_NONE 0x00 /*!< No counters will be reset */ #define RESET_COUNT 0x08 /*!< Reset the internal tachometer counter */ #define RESET_BLOCK_COUNT 0x20 /*!< Reset the NXT-G block tachometer counter */ #define RESET_ROTATION_COUNT 0x40 /*!< Reset the rotation counter */ #define RESET_BLOCKANDTACHO 0x28 /*!< Reset both the internal counter and the NXT-G block counter */ #define RESET_ALL 0x68 /*!< Reset all three tachometer counters */ /** @} */ // end of TachoResetConstants group /** @defgroup OutModeConstants Output port mode constants * Use these constants to configure the desired mode for the * specified motor(s): coast, motoron, brake, or regulated. Mode constants * can be combined with bitwise OR. * \sa SetOutput() * @{ */ #define OUT_MODE_COAST 0x00 /*!< No power and no braking so motors rotate freely. */ #define OUT_MODE_MOTORON 0x01 /*!< Enables PWM power to the outputs given the power setting */ #define OUT_MODE_BRAKE 0x02 /*!< Uses electronic braking to outputs */ #define OUT_MODE_REGULATED 0x04 /*!< Enables active power regulation using the regulation mode value */ #define OUT_MODE_REGMETHOD 0xF0 /*!< Mask for unimplemented regulation mode */ /** @} */ // end of OutModeConstants group #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** @defgroup OutOptionConstants Output port option constants * Use these constants to configure the desired options for the * specified motor(s): hold at limit and ramp down to limit. Option constants * can be combined with bitwise OR. * \sa SetOutput() * @{ */ #define OUT_OPTION_HOLDATLIMIT 0x10 /*!< Option to have the firmware hold the motor when it reaches the tachometer limit */ #define OUT_OPTION_RAMPDOWNTOLIMIT 0x20 /*!< Option to have the firmware rampdown the motor power as it approaches the tachometer limit */ /** @} */ // end of OutOptionConstants group /** @defgroup OutRegOptionConstants Output regulation option constants * Use these constants to configure the desired options for * position regulation. * @{ */ #define OUT_REGOPTION_NO_SATURATION 0x01 /*!< Do not limit intermediary regulation results */ /** @} */ // end of OutRegOptionConstants group #endif /** @defgroup OutRunStateConstants Output port run state constants * Use these constants to configure the desired run state for the * specified motor(s): idle, rampup, running, rampdown, or hold. * \sa SetOutput() * @{ */ #define OUT_RUNSTATE_IDLE 0x00 /*!< Disable all power to motors. */ #define OUT_RUNSTATE_RAMPUP 0x10 /*!< Enable ramping up from a current power to a new (higher) power over a specified \ref TachoLimitField goal. */ #define OUT_RUNSTATE_RUNNING 0x20 /*!< Enable power to motors at the specified power level. */ #define OUT_RUNSTATE_RAMPDOWN 0x40 /*!< Enable ramping down from a current power to a new (lower) power over a specified \ref TachoLimitField goal. */ #define OUT_RUNSTATE_HOLD 0x60 /*!< Set motor run state to hold at the current position. */ /** @} */ // end of OutRunStateConstants group /** @defgroup OutRegModeConstants Output port regulation mode constants * Use these constants to configure the desired regulation mode for the * specified motor(s): none, speed regulation, multi-motor synchronization, * or position regulation (requires the enhanced NBC/NXC firmware version 1.31+). * \sa SetOutput() * @{ */ #define OUT_REGMODE_IDLE 0 /*!< No motor regulation. */ #define OUT_REGMODE_SPEED 1 /*!< Regulate a motor's speed (aka power). */ #define OUT_REGMODE_SYNC 2 /*!< Synchronize the rotation of two motors. */ #define OUT_REGMODE_POS 4 /*!< Regulate a motor's position. */ /** @} */ // end of OutRegModeConstants group /** @defgroup OutputFieldConstants Output field constants * Constants for use with SetOutput() and GetOutput(). * \sa SetOutput(), GetOutput() * @{ */ /** Update flags field. Contains a combination of the update flag constants. Read/write. * Use \ref UF_UPDATE_MODE, \ref UF_UPDATE_SPEED, \ref UF_UPDATE_TACHO_LIMIT, and \ref UF_UPDATE_PID_VALUES * along with other fields to commit changes to the state of outputs. Set the appropriate * flags after setting one or more of the output fields in order for the changes to actually * go into affect. */ #define UpdateFlagsField 0 /** Mode field. Contains a combination of the output mode constants. Read/write. * The \ref OUT_MODE_MOTORON bit must be set in order for power to be applied to the motors. * Add \ref OUT_MODE_BRAKE to enable electronic braking. Braking means that the output voltage * is not allowed to float between active PWM pulses. It improves the accuracy of motor * output but uses more battery power. * To use motor regulation include \ref OUT_MODE_REGULATED in the \ref OutputModeField value. Use * \ref UF_UPDATE_MODE with \ref UpdateFlagsField to commit changes to this field. */ #define OutputModeField 1 /** Power field. Contains the desired power level (-100 to 100). Read/write. * Specify the power level of the output. The absolute value of PowerField is a percentage of the * full power of the motor. The sign of PowerField controls the rotation direction. Positive values * tell the firmware to turn the motor forward, while negative values turn the motor backward. * Use \ref UF_UPDATE_SPEED with \ref UpdateFlagsField to commit changes to this field. */ #define PowerField 2 /** Actual speed field. Contains the actual power level (-100 to 100). Read only. * Return the percent of full power the firmware is applying to the output. This may vary from the * PowerField value when auto-regulation code in the firmware responds to a load on the output. */ #define ActualSpeedField 3 /** Internal tachometer count field. Contains the current internal tachometer count. Read only. * Return the internal position counter value for the specified output. The internal count is reset * automatically when a new goal is set using the \ref TachoLimitField and the \ref UF_UPDATE_TACHO_LIMIT flag. * Set the \ref UF_UPDATE_RESET_COUNT flag in \ref UpdateFlagsField to reset TachoCountField and cancel any \ref TachoLimitField. * The sign of TachoCountField indicates the motor rotation direction. */ #define TachoCountField 4 /** Tachometer limit field. Contains the current tachometer limit. Read/write. * Specify the number of degrees the motor should rotate. * Use \ref UF_UPDATE_TACHO_LIMIT with the \ref UpdateFlagsField field to commit changes to the TachoLimitField. * The value of this field is a relative distance from the current motor position at the moment when * the \ref UF_UPDATE_TACHO_LIMIT flag is processed. */ #define TachoLimitField 5 /** Run state field. Contains one of the run state constants. Read/write. * Use this field to specify the running state of an output. Set the RunStateField to \ref OUT_RUNSTATE_RUNNING * to enable power to any output. Use \ref OUT_RUNSTATE_RAMPUP to enable automatic ramping to a new \ref PowerField * level greater than the current \ref PowerField level. Use \ref OUT_RUNSTATE_RAMPDOWN to enable automatic ramping * to a new \ref PowerField level less than the current \ref PowerField level. * Both the rampup and rampdown bits must be used in conjunction with appropriate \ref TachoLimitField and \ref PowerField * values. In this case the firmware smoothly increases or decreases the actual power to the new \ref PowerField * level over the total number of degrees of rotation specified in \ref TachoLimitField. */ #define RunStateField 6 /** Turn ratio field. Contains the current turn ratio. Only applicable when synchronizing multiple motors. Read/write. * Use this field to specify a proportional turning ratio. This field must be used in conjunction with other * field values: \ref OutputModeField must include \ref OUT_MODE_MOTORON and \ref OUT_MODE_REGULATED, \ref RegModeField must be set to * \ref OUT_REGMODE_SYNC, \ref RunStateField must not be \ref OUT_RUNSTATE_IDLE, and \ref PowerField must be non-zero. * There are only three valid combinations of left and right motors for use with TurnRatioField: \ref OUT_AB, \ref OUT_BC, * and \ref OUT_AC. In each of these three options the first motor listed is considered to be the left motor and * the second motor is the right motor, regardless of the physical configuration of the robot. * Negative turn ratio values shift power toward the left motor while positive values shift power toward the * right motor. An absolute value of 50 usually results in one motor stopping. An absolute value of 100 usually * results in two motors turning in opposite directions at equal power. */ #define TurnRatioField 7 /** Regulation mode field. Contains one of the regulation mode constants. Read/write. * This field specifies the regulation mode to use with the specified port(s). It is ignored if * the \ref OUT_MODE_REGULATED bit is not set in the \ref OutputModeField field. Unlike \ref OutputModeField, RegModeField is * not a bitfield. Only one regulation mode value can be set at a time. * Speed regulation means that the firmware tries to maintain a certain speed based on the \ref PowerField setting. The * firmware adjusts the PWM duty cycle if the motor is affected by a physical load. This adjustment is * reflected by the value of the \ref ActualSpeedField property. When using speed regulation, do not set \ref PowerField to its * maximum value since the firmware cannot adjust to higher power levels in that situation. * Synchronization means the firmware tries to keep two motors in sync regardless of physical loads. Use * this mode to maintain a straight path for a mobile robot automatically. Also use this mode with the * \ref TurnRatioField property to provide proportional turning. * Set \ref OUT_REGMODE_SYNC on at least two motor ports in order for synchronization to function. Setting * \ref OUT_REGMODE_SYNC on all three motor ports will result in only the first two (\ref OUT_A and \ref OUT_B) being * synchronized. */ #define RegModeField 8 /** Overload field. Contains a boolean value which is TRUE if the motor is overloaded. Read only. * This field will have a value of 1 (true) if the firmware speed regulation cannot overcome a physical * load on the motor. In other words, the motor is turning more slowly than expected. * If the motor speed can be maintained in spite of loading then this field value is zero (false). * In order to use this field the motor must have a non-idle \ref RunStateField, an \ref OutputModeField which includes * \ref OUT_MODE_MOTORON and \ref OUT_MODE_REGULATED, and its \ref RegModeField must be set to \ref OUT_REGMODE_SPEED. */ #define OverloadField 9 /** Proportional field. Contains the proportional constant for the PID motor controller. Read/write. * This field specifies the proportional term used in the internal proportional-integral-derivative * (PID) control algorithm. * Set \ref UF_UPDATE_PID_VALUES to commit changes to RegPValue, RegIValue, and RegDValue simultaneously. */ #define RegPValueField 10 /** Integral field. Contains the integral constant for the PID motor controller. Read/write. * This field specifies the integral term used in the internal proportional-integral-derivative * (PID) control algorithm. * Set \ref UF_UPDATE_PID_VALUES to commit changes to RegPValue, RegIValue, and RegDValue simultaneously. */ #define RegIValueField 11 /** Derivative field. Contains the derivative constant for the PID motor controller. Read/write. * This field specifies the derivative term used in the internal proportional-integral-derivative * (PID) control algorithm. * Set \ref UF_UPDATE_PID_VALUES to commit changes to RegPValue, RegIValue, and RegDValue simultaneously. */ #define RegDValueField 12 /** NXT-G block tachometer count field. Contains the current NXT-G block tachometer count. Read only. * Return the block-relative position counter value for the specified port. * Refer to the \ref UpdateFlagsField description for information about how to use block-relative * position counts. * Set the \ref UF_UPDATE_RESET_BLOCK_COUNT flag in \ref UpdateFlagsField to request that the firmware * reset the BlockTachoCountField. * The sign of BlockTachoCountField indicates the direction of rotation. Positive values indicate * forward rotation and negative values indicate reverse rotation. Forward and reverse depend on * the orientation of the motor. */ #define BlockTachoCountField 13 /** Rotation counter field. Contains the current rotation count. Read only. * Return the program-relative position counter value for the specified port. * Refer to the \ref UpdateFlagsField description for information about how to use program-relative * position counts. * Set the \ref UF_UPDATE_RESET_ROTATION_COUNT flag in \ref UpdateFlagsField to request that the firmware reset * the RotationCountField. * The sign of RotationCountField indicates the direction of rotation. Positive values indicate forward * rotation and negative values indicate reverse rotation. Forward and reverse depend on the * orientation of the motor. */ #define RotationCountField 14 #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** Options field. Contains a combination of the output options constants. Read/write. * Set options for how the output module will act when a tachometer limit is reached. Option * constants can be combined with bitwise OR. Use OUT_OPTION_HOLDATLIMIT to have the output * module hold the motor when it reaches the tachometer limit. Use OUT_OPTION_RAMPDOWNTOLIMIT * to have the output module ramp down the motor power as it approaches the tachometer limit. */ #define OutputOptionsField 15 /** MaxSpeed field. Contains the current max speed value. Read/write. * Set the maximum speed to be used during position regulation. */ #define MaxSpeedField 16 /** MaxAcceleration field. Contains the current max acceleration value. Read/write. * Set the maximum acceleration to be used during position regulation. */ #define MaxAccelerationField 17 #endif /** @} */ // end of OutputFieldConstants group /** @defgroup OutputIOMAP Output module IOMAP offsets * Constant offsets into the Output module IOMAP structure. * @{ */ #define OutputOffsetTachoCount(p) (((p)*32)+0) /*!< R - Holds current number of counts, since last reset, updated every 1 mS (4 bytes) slong */ #define OutputOffsetBlockTachoCount(p) (((p)*32)+4) /*!< R - Holds current number of counts for the current output block (4 bytes) slong */ #define OutputOffsetRotationCount(p) (((p)*32)+8) /*!< R - Holds current number of counts for the rotation counter to the output (4 bytes) slong */ #define OutputOffsetTachoLimit(p) (((p)*32)+12) /*!< RW - Holds number of counts to travel, 0 => Run forever (4 bytes) ulong */ #define OutputOffsetMotorRPM(p) (((p)*32)+16) /*!< Not updated, will be removed later !! (2 bytes) sword */ #define OutputOffsetFlags(p) (((p)*32)+18) /*!< RW - Holds flags for which data should be updated (1 byte) ubyte */ #define OutputOffsetMode(p) (((p)*32)+19) /*!< RW - Holds motor mode: Run, Break, regulated, ... (1 byte) ubyte */ #define OutputOffsetSpeed(p) (((p)*32)+20) /*!< RW - Holds the wanted speed (1 byte) sbyte */ #define OutputOffsetActualSpeed(p) (((p)*32)+21) /*!< R - Holds the current motor speed (1 byte) sbyte */ #define OutputOffsetRegPParameter(p) (((p)*32)+22) /*!< RW - Holds the P-constant used in the regulation (1 byte) ubyte */ #define OutputOffsetRegIParameter(p) (((p)*32)+23) /*!< RW - Holds the I-constant used in the regulation (1 byte) ubyte */ #define OutputOffsetRegDParameter(p) (((p)*32)+24) /*!< RW - Holds the D-constant used in the regulation (1 byte) ubyte */ #define OutputOffsetRunState(p) (((p)*32)+25) /*!< RW - Holds the current motor run state in the output module (1 byte) ubyte */ #define OutputOffsetRegMode(p) (((p)*32)+26) /*!< RW - Tells which regulation mode should be used (1 byte) ubyte */ #define OutputOffsetOverloaded(p) (((p)*32)+27) /*!< R - True if the motor has been overloaded within speed control regulation (1 byte) ubyte */ #define OutputOffsetSyncTurnParameter(p) (((p)*32)+28) /*!< RW - Holds the turning parameter need within MoveBlock (1 byte) sbyte */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define OutputOffsetOptions(p) (((p)*32)+29) /*!< RW - holds extra motor options related to the tachometer limit (1 byte) ubyte (NBC/NXC) */ #define OutputOffsetMaxSpeed(p) (((p)*32)+30) /*!< RW - holds the maximum speed for position regulation (1 byte) sbyte (NBC/NXC) */ #define OutputOffsetMaxAccel(p) (((p)*32)+31) /*!< RW - holds the maximum acceleration for position regulation (1 byte) sbyte (NBC/NXC) */ #endif #define OutputOffsetRegulationTime 96 /*!< use for frequency of checking regulation mode (1 byte) ubyte (NBC/NXC) */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define OutputOffsetRegulationOptions 97 /*!< use for position regulation options (1 byte) ubyte (NBC/NXC) */ #endif /** @} */ // end of OutputIOMAP group /** @} */ // end of OutputModuleConstants group /** @} */ // end of OutputModule group /** @addtogroup LowSpeedModule * @{ */ /** @defgroup LowSpeedModuleConstants LowSpeed module constants * Constants that are part of the NXT firmware's LowSpeed module. * @{ */ /** @defgroup LowSpeedStateConstants LSState constants * Constants for the low speed module LSState function. These values are * combined together using a bitwise OR operation. * \sa LSState() * @{ */ #define COM_CHANNEL_NONE_ACTIVE 0x00 /*!< None of the low speed channels are active */ #define COM_CHANNEL_ONE_ACTIVE 0x01 /*!< Low speed channel 1 is active */ #define COM_CHANNEL_TWO_ACTIVE 0x02 /*!< Low speed channel 2 is active */ #define COM_CHANNEL_THREE_ACTIVE 0x04 /*!< Low speed channel 3 is active */ #define COM_CHANNEL_FOUR_ACTIVE 0x08 /*!< Low speed channel 4 is active */ /** @} */ // end of LowSpeedStateConstants group /** @defgroup LowSpeedChannelStateConstants LSChannelState constants * Constants for the low speed module LSChannelState function. * \sa LSChannelState() * @{ */ #define LOWSPEED_IDLE 0 /*!< Channel is idle */ #define LOWSPEED_INIT 1 /*!< Channel is being initialized */ #define LOWSPEED_LOAD_BUFFER 2 /*!< Channel buffer is loading */ #define LOWSPEED_COMMUNICATING 3 /*!< Channel is actively communicating */ #define LOWSPEED_ERROR 4 /*!< Channel is in an error state */ #define LOWSPEED_DONE 5 /*!< Channel is done communicating */ /** @} */ // end of LowSpeedChannelStateConstants group /** @defgroup LowSpeedModeConstants LSMode constants * Constants for the low speed module LSMode function. * \sa LSMode() * @{ */ #define LOWSPEED_TRANSMITTING 1 /*!< Lowspeed port is in transmitting mode */ #define LOWSPEED_RECEIVING 2 /*!< Lowspeed port is in receiving mode */ #define LOWSPEED_DATA_RECEIVED 3 /*!< Lowspeed port is in data received mode */ /** @} */ // end of LowSpeedModeConstants group /** @defgroup LowSpeedErrorTypeConstants LSErrorType constants * Constants for the low speed module LSErrorType function. * \sa LSErrorType() * @{ */ #define LOWSPEED_NO_ERROR 0 /*!< Lowspeed port has no error */ #define LOWSPEED_CH_NOT_READY 1 /*!< Lowspeed port is not ready */ #define LOWSPEED_TX_ERROR 2 /*!< Lowspeed port encountered an error while transmitting data */ #define LOWSPEED_RX_ERROR 3 /*!< Lowspeed port encountered an error while receiving data */ /** @} */ // end of LowSpeedErrorTypeConstants group /** @defgroup LowSpeedIOMAP Low speed module IOMAP offsets * Constant offsets into the low speed module IOMAP structure. * @{ */ #define LowSpeedOffsetInBufBuf(p) (((p)*19)+0) /*!< RW - Input buffer data buffer field offset (16 bytes) */ #define LowSpeedOffsetInBufInPtr(p) (((p)*19)+16) /*!< RW - Input buffer in pointer field offset (1 byte) */ #define LowSpeedOffsetInBufOutPtr(p) (((p)*19)+17) /*!< RW - Input buffer out pointer field offset (1 byte) */ #define LowSpeedOffsetInBufBytesToRx(p) (((p)*19)+18) /*!< RW - Input buffer bytes to receive field offset (1 byte) */ #define LowSpeedOffsetOutBufBuf(p) (((p)*19)+76) /*!< RW - Output buffer data buffer field offset (16 bytes) */ #define LowSpeedOffsetOutBufInPtr(p) (((p)*19)+92) /*!< RW - Output buffer in pointer field offset (1 byte) */ #define LowSpeedOffsetOutBufOutPtr(p) (((p)*19)+93) /*!< RW - Output buffer out pointer field offset (1 byte) */ #define LowSpeedOffsetOutBufBytesToRx(p) (((p)*19)+94) /*!< RW - Output buffer bytes to receive field offset (1 byte) */ #define LowSpeedOffsetMode(p) ((p)+152) /*!< R - Lowspeed port mode (1 byte) */ #define LowSpeedOffsetChannelState(p) ((p)+156) /*!< R - Lowspeed channgel state (1 byte) */ #define LowSpeedOffsetErrorType(p) ((p)+160) /*!< R - Lowspeed port error type (1 byte) */ #define LowSpeedOffsetState 164 /*!< R - Lowspeed state (all channels) */ #define LowSpeedOffsetSpeed 165 /*!< R - Lowspeed speed (unused) */ #ifdef __ENHANCED_FIRMWARE #define LowSpeedOffsetNoRestartOnRead 166 /*!< RW - Lowspeed option for no restart on read (all channels) (NBC/NXC) */ #endif /** @} */ // end of LowSpeedIOMAP group /** @defgroup LowSpeedNoRestartConstants LSNoRestartOnRead constants * Constants for the low speed module LSNoRestartOnRead and * SetLSNoRestartOnRead functions. These values are combined with a bitwise * OR operation. * \sa LSNoRestartOnRead(), SetLSNoRestartOnRead() * @{ */ #ifdef __ENHANCED_FIRMWARE #define LSREAD_RESTART_ALL 0x00 /*!< Restart on read for all channels (default) */ #define LSREAD_NO_RESTART_1 0x01 /*!< No restart on read for channel 1 */ #define LSREAD_NO_RESTART_2 0x02 /*!< No restart on read for channel 2 */ #define LSREAD_NO_RESTART_3 0x04 /*!< No restart on read for channel 3 */ #define LSREAD_NO_RESTART_4 0x08 /*!< No restart on read for channel 4 */ #define LSREAD_RESTART_NONE 0x0F /*!< No restart on read for all channels */ #define LSREAD_NO_RESTART_MASK 0x10 /*!< No restart mask */ #endif /** @} */ // end of LowSpeedNoRestartConstants group /** @defgroup GenericI2CConstants Standard I2C constants * Constants for use with standard I2C devices. * @{ */ #define I2C_ADDR_DEFAULT 0x02 /*!< Standard NXT I2C device address */ #define I2C_REG_VERSION 0x00 /*!< Standard NXT I2C version register */ #define I2C_REG_VENDOR_ID 0x08 /*!< Standard NXT I2C vendor ID register */ #define I2C_REG_DEVICE_ID 0x10 /*!< Standard NXT I2C device ID register */ #define I2C_REG_CMD 0x41 /*!< Standard NXT I2C device command register */ /** @} */ // end of GenericI2CConstants group /** @defgroup LEGOI2CAddressConstants LEGO I2C address constants * Constants for LEGO I2C device addresses. * @{ */ #define LEGO_ADDR_US 0x02 /*!< The LEGO ultrasonic sensor's I2C address */ #define LEGO_ADDR_TEMP 0x98 /*!< The LEGO temperature sensor's I2C address */ #define LEGO_ADDR_EMETER 0x04 /*!< The LEGO e-meter sensor's I2C address */ /** @} */ // end of LEGOI2CAddressConstants group /** @defgroup USI2CConstants Ultrasonic sensor constants * Constants for use with the ultrasonic sensor. * @{ */ #define US_CMD_OFF 0x00 /*!< Command to turn off the ultrasonic sensor */ #define US_CMD_SINGLESHOT 0x01 /*!< Command to put the ultrasonic sensor into single shot mode */ #define US_CMD_CONTINUOUS 0x02 /*!< Command to put the ultrasonic sensor into continuous polling mode (default) */ #define US_CMD_EVENTCAPTURE 0x03 /*!< Command to put the ultrasonic sensor into event capture mode */ #define US_CMD_WARMRESET 0x04 /*!< Command to warm reset the ultrasonic sensor */ #define US_REG_CM_INTERVAL 0x40 /*!< The register address used to store the CM interval */ #define US_REG_ACTUAL_ZERO 0x50 /*!< The register address used to store the actual zero value */ #define US_REG_SCALE_FACTOR 0x51 /*!< The register address used to store the scale factor value */ #define US_REG_SCALE_DIVISOR 0x52 /*!< The register address used to store the scale divisor value */ #define US_REG_FACTORY_ACTUAL_ZERO 0x11 /*!< The register address containing the factory setting for the actual zero value */ #define US_REG_FACTORY_SCALE_FACTOR 0x12 /*!< The register address containing the factory setting for the scale factor value */ #define US_REG_FACTORY_SCALE_DIVISOR 0x13 /*!< The register address containing the factory setting for the scale divisor value */ #define US_REG_MEASUREMENT_UNITS 0x14 /*!< The register address containing the measurement units (degrees C or F) */ /** @} */ // end of USI2CConstants group /** @defgroup TempI2CConstants LEGO temperature sensor constants * Constants for use with the LEGO temperature sensor. * @{ */ // R1/R0 #define TEMP_RES_9BIT 0x00 /*!< Set the temperature conversion resolution to 9 bit */ #define TEMP_RES_10BIT 0x20 /*!< Set the temperature conversion resolution to 10 bit */ #define TEMP_RES_11BIT 0x40 /*!< Set the temperature conversion resolution to 11 bit */ #define TEMP_RES_12BIT 0x60 /*!< Set the temperature conversion resolution to 12 bit */ // SD (shutdown mode) #define TEMP_SD_CONTINUOUS 0x00 /*!< Set the sensor mode to continuous */ #define TEMP_SD_SHUTDOWN 0x01 /*!< Set the sensor mode to shutdown. The device will shut down after the current conversion is completed. */ // TM (thermostat mode) #define TEMP_TM_COMPARATOR 0x00 /*!< Set the thermostat mode to comparator */ #define TEMP_TM_INTERRUPT 0x02 /*!< Set the thermostat mode to interrupt */ // OS (one shot) #define TEMP_OS_ONESHOT 0x80 /*!< Set the sensor into oneshot mode. When the device is in shutdown mode this will start a single temperature conversion. The device returns to shutdown mode when it completes. */ // F1/F0 (fault queue) #define TEMP_FQ_1 0x00 /*!< Set fault queue to 1 fault before alert */ #define TEMP_FQ_2 0x08 /*!< Set fault queue to 2 faults before alert */ #define TEMP_FQ_4 0x10 /*!< Set fault queue to 4 faults before alert */ #define TEMP_FQ_6 0x18 /*!< Set fault queue to 6 faults before alert */ // POL (polarity) #define TEMP_POL_LOW 0x00 /*!< Set polarity of ALERT pin to be active LOW */ #define TEMP_POL_HIGH 0x04 /*!< Set polarity of ALERT pin to be active HIGH */ #define TEMP_REG_TEMP 0x00 /*!< The register where temperature values can be read */ #define TEMP_REG_CONFIG 0x01 /*!< The register for reading/writing sensor configuration values */ #define TEMP_REG_TLOW 0x02 /*!< The register for reading/writing a user-defined low temperature limit */ #define TEMP_REG_THIGH 0x03 /*!< The register for reading/writing a user-defined high temperature limit */ /** @} */ // end of TempI2CConstants group /** @defgroup EMeterI2CConstants E-Meter sensor constants * Constants for use with the e-meter sensor. * @{ */ #define EMETER_REG_VIN 0x0a /*!< The register address for voltage in */ #define EMETER_REG_AIN 0x0c /*!< The register address for amps in */ #define EMETER_REG_VOUT 0x0e /*!< The register address for voltage out */ #define EMETER_REG_AOUT 0x10 /*!< The register address for amps out */ #define EMETER_REG_JOULES 0x12 /*!< The register address for joules */ #define EMETER_REG_WIN 0x14 /*!< The register address for watts in */ #define EMETER_REG_WOUT 0x16 /*!< The register address for watts out */ /** @} */ // end of EMeterI2CConstants group /** @} */ // end of LowSpeedModuleConstants group /** @} */ // end of LowSpeedModule group /** @addtogroup DisplayModule * @{ */ /** @defgroup DisplayModuleConstants Display module constants * Constants that are part of the NXT firmware's Display module. * @{ */ /** @defgroup DisplayExecuteFunctionConstants DisplayExecuteFunction constants * Constants that are for use with the DisplayExecuteFunction system call. * @{ */ #define DISPLAY_ERASE_ALL 0x00 /*!< W - erase entire screen (CMD,x,x,x,x,x) */ #define DISPLAY_PIXEL 0x01 /*!< W - set pixel (on/off) (CMD,TRUE/FALSE,X,Y,x,x) */ #define DISPLAY_HORIZONTAL_LINE 0x02 /*!< W - draw horizontal line (CMD,TRUE/FALSE,X1,Y1,X2,x) */ #define DISPLAY_VERTICAL_LINE 0x03 /*!< W - draw vertical line (CMD,TRUE/FALSE,X1,Y1,x,Y2) */ #define DISPLAY_CHAR 0x04 /*!< W - draw char (actual font) (CMD,TRUE,X1,Y1,Char,x) */ #define DISPLAY_ERASE_LINE 0x05 /*!< W - erase a single line (CMD,x,LINE,x,x,x) */ #define DISPLAY_FILL_REGION 0x06 /*!< W - fill screen region (CMD,TRUE/FALSE,X1,Y1,X2,Y2) */ #define DISPLAY_FRAME 0x07 /*!< W - draw a frame (on/off) (CMD,TRUE/FALSE,X1,Y1,X2,Y2) */ /** @} */ // end of DisplayExecuteFunctionConstants group /** @defgroup DisplayDrawOptionConstants Drawing option constants * Constants that are for specifying drawing options in several display module API functions. * Bits 0 & 1 (values 0,1,2,3) control screen clearing behaviour (Not within RIC files). * Bit 2 (value 4) controls the NOT operation, i.e. draw in white or invert text/graphics. * Bits 3 & 4 (values 0,8,16,24) control pixel logical combinations (COPY/AND/OR/XOR). * Bit 5 (value 32) controls shape filling, or overrides text/graphic bitmaps with set pixels. * These may be ORed together for the full instruction * (e.g., DRAW_OPT_NORMAL|DRAW_OPT_LOGICAL_XOR) * These operations are resolved into the separate, common parameters * defined in 'c_display.iom' before any drawing function is called. * Note that when drawing a RIC file, the initial 'DrawingOptions' parameter * supplied in the drawing instruction controls screen clearing, but nothing else. * The 'CopyOptions' parameter from each instruction in the RIC file then controls * graphic operations, but the screen-clearing bits are ignored. * \sa TextOut(), NumOut(), PointOut(), LineOut(), CircleOut(), RectOut(), * PolyOut(), EllipseOut(), FontTextOut(), FontNumOut(), GraphicOut(), * GraphicArrayOut() * @{ */ #define DRAW_OPT_NORMAL (0x0000) /*!< Normal drawing */ #define DRAW_OPT_CLEAR_WHOLE_SCREEN (0x0001) /*!< Clear the entire screen before drawing */ #define DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN (0x0002) /*!< Clear the screen except for the status line before drawing */ #define DRAW_OPT_CLEAR_PIXELS (0x0004) /*!< Clear pixels while drawing (aka draw in white) */ #define DRAW_OPT_CLEAR (0x0004) /*!< Clear pixels while drawing (aka draw in white) */ #define DRAW_OPT_INVERT (0x0004) /*!< Invert text or graphics */ #define DRAW_OPT_LOGICAL_COPY (0x0000) /*!< Draw pixels using a logical copy operation */ #define DRAW_OPT_LOGICAL_AND (0x0008) /*!< Draw pixels using a logical AND operation */ #define DRAW_OPT_LOGICAL_OR (0x0010) /*!< Draw pixels using a logical OR operation */ #define DRAW_OPT_LOGICAL_XOR (0x0018) /*!< Draw pixels using a logical XOR operation */ #define DRAW_OPT_FILL_SHAPE (0x0020) /*!< Fill the shape while drawing (rectangle, circle, ellipses, and polygon) */ #define DRAW_OPT_CLEAR_SCREEN_MODES (0x0003) /*!< Bit mask for the clear screen modes */ #define DRAW_OPT_LOGICAL_OPERATIONS (0x0018) /*!< Bit mask for the logical drawing operations */ #define DRAW_OPT_POLYGON_POLYLINE (0x0400) /*!< When drawing polygons, do not close (i.e., draw a polyline instead) */ /** @defgroup DisplayFontDrawOptionConstants Font drawing option constants * These addition drawing option constants are only for use when drawing * text and numbers on the LCD using an RIC-based font. * \sa FontTextOut(), FontNumOut() * @{ */ #define DRAW_OPT_FONT_DIRECTIONS (0x01C0) /*!< Bit mask for the font direction bits */ #define DRAW_OPT_FONT_WRAP (0x0200) /*!< Option to have text wrap in \ref FontNumOut and \ref FontTextOut calls */ #define DRAW_OPT_FONT_DIR_L2RB (0x0000) /*!< Font left to right bottom align */ #define DRAW_OPT_FONT_DIR_L2RT (0x0040) /*!< Font left to right top align */ #define DRAW_OPT_FONT_DIR_R2LB (0x0080) /*!< Font right to left bottom align */ #define DRAW_OPT_FONT_DIR_R2LT (0x00C0) /*!< Font right to left top align */ #define DRAW_OPT_FONT_DIR_B2TL (0x0100) /*!< Font bottom to top left align */ #define DRAW_OPT_FONT_DIR_B2TR (0x0140) /*!< Font bottom to top right align */ #define DRAW_OPT_FONT_DIR_T2BL (0x0180) /*!< Font top to bottom left align */ #define DRAW_OPT_FONT_DIR_T2BR (0x01C0) /*!< Font top to bottom right align */ /** @} */ // end of DisplayFontDrawOptionConstants group /** @} */ // end of DisplayDrawOptionConstants group /** @defgroup DisplayFlagsGroup Display flags * Constants that are for use with the display flags functions. * \sa SetDisplayFlags(), DisplayFlags() * @{ */ #define DISPLAY_ON 0x01 /*!< W - Display on */ #define DISPLAY_REFRESH 0x02 /*!< W - Enable refresh */ #define DISPLAY_POPUP 0x08 /*!< W - Use popup display memory */ #define DISPLAY_REFRESH_DISABLED 0x40 /*!< R - Refresh disabled */ #define DISPLAY_BUSY 0x80 /*!< R - Refresh in progress */ /** @} */ // end of DisplayFlagsGroup group #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** @defgroup DisplayContrastConstants Display contrast constants * Constants that are for use with the display contrast API functions. * \sa SetDisplayContrast(), DisplayContrast() * @{ */ #define DISPLAY_CONTRAST_DEFAULT 0x5A /*!< Default display contrast value */ #define DISPLAY_CONTRAST_MAX 0x7F /*!< Maximum display contrast value */ /** @} */ // end of DisplayContrastConstants group #endif #define SCREEN_MODE_RESTORE 0x00 /*!< Restore the screen \sa SetScreenMode() */ #define SCREEN_MODE_CLEAR 0x01 /*!< Clear the screen \sa SetScreenMode() */ #define DISPLAY_HEIGHT 64 /*!< The height of the LCD screen in pixels */ #define DISPLAY_WIDTH 100 /*!< The width of the LCD screen in pixels */ #define DISPLAY_MENUICONS_Y 40 /*!< */ #define DISPLAY_MENUICONS_X_OFFS 7 /*!< */ #define DISPLAY_MENUICONS_X_DIFF 31 /*!< */ /** @defgroup DisplayTextLineConstants Text line constants * Constants that are for use with getting/setting display data. * \sa SetDisplayNormal(), GetDisplayNormal(), SetDisplayPopup(), GetDisplayPopup() * @{ */ #define TEXTLINE_1 0 /*!< Text line 1 */ #define TEXTLINE_2 1 /*!< Text line 2 */ #define TEXTLINE_3 2 /*!< Text line 3 */ #define TEXTLINE_4 3 /*!< Text line 4 */ #define TEXTLINE_5 4 /*!< Text line 5 */ #define TEXTLINE_6 5 /*!< Text line 6 */ #define TEXTLINE_7 6 /*!< Text line 7 */ #define TEXTLINE_8 7 /*!< Text line 8 */ #define TEXTLINES 8 /*!< The number of text lines on the LCD */ /** @} */ // end of DisplayTextLineConstants group // Used in macro "MENUICON_BIT" #define MENUICON_LEFT 0 /*!< Left icon */ #define MENUICON_CENTER 1 /*!< Center icon */ #define MENUICON_RIGHT 2 /*!< Right icon */ #define MENUICONS 3 /*!< The number of menu icons */ // Used in macro "SPECIAL_BIT" #define FRAME_SELECT 0 /*!< Center icon select frame */ #define STATUSTEXT 1 /*!< Status text (BT name) */ #define MENUTEXT 2 /*!< Center icon text */ #define STEPLINE 3 /*!< Step collection lines */ #define TOPLINE 4 /*!< Top status underline */ #define SPECIALS 5 /*!< The number of special bit values */ // Used in macro "STATUSICON_BIT" #define STATUSICON_BLUETOOTH 0 /*!< BlueTooth status icon collection */ #define STATUSICON_USB 1 /*!< USB status icon collection */ #define STATUSICON_VM 2 /*!< VM status icon collection */ #define STATUSICON_BATTERY 3 /*!< Battery status icon collection */ #define STATUSICONS 4 /*!< The number of status icons */ // Used in macro "SCREEN_BIT" #define SCREEN_BACKGROUND 0 /*!< Entire screen */ #define SCREEN_LARGE 1 /*!< Entire screen except status line */ #define SCREEN_SMALL 2 /*!< Screen between menu icons and status line */ #define SCREENS 3 /*!< The number of screen bits */ // Used in macro "BITMAP_BIT" #define BITMAP_1 0 /*!< Bitmap 1 */ #define BITMAP_2 1 /*!< Bitmap 2 */ #define BITMAP_3 2 /*!< Bitmap 3 */ #define BITMAP_4 3 /*!< Bitmap 4 */ #define BITMAPS 4 /*!< The number of bitmap bits */ // Used in macro "STEPICON_BIT" #define STEPICON_1 0 /*!< Left most step icon */ #define STEPICON_2 1 /*!< */ #define STEPICON_3 2 /*!< */ #define STEPICON_4 3 /*!< */ #define STEPICON_5 4 /*!< Right most step icon */ #define STEPICONS 5 /*!< */ /** @defgroup DisplayIOMAP Display module IOMAP offsets * Constant offsets into the display module IOMAP structure. * @{ */ #define DisplayOffsetPFunc 0 /*!< Simple draw entry */ #define DisplayOffsetEraseMask 4 /*!< Section erase mask (executed first) */ #define DisplayOffsetUpdateMask 8 /*!< Section update mask (executed next) */ #define DisplayOffsetPFont 12 /*!< Pointer to font file */ #define DisplayOffsetPTextLines(p) (((p)*4)+16) /*!< Pointer to text strings */ #define DisplayOffsetPStatusText 48 /*!< Pointer to status text string */ #define DisplayOffsetPStatusIcons 52 /*!< Pointer to status icon collection file */ #define DisplayOffsetPScreens(p) (((p)*4)+56) /*!< Pointer to screen bitmap file */ #define DisplayOffsetPBitmaps(p) (((p)*4)+68) /*!< Pointer to free bitmap files */ #define DisplayOffsetPMenuText 84 /*!< Pointer to menu icon text (NULL == none) */ #define DisplayOffsetPMenuIcons(p) (((p)*4)+88) /*!< Pointer to menu icon images (NULL == none) */ #define DisplayOffsetPStepIcons 100 /*!< Pointer to step icon collection file */ #define DisplayOffsetDisplay 104 /*!< Display content copied to physical display every 17 mS */ #define DisplayOffsetStatusIcons(p) ((p)+108) /*!< Index in status icon collection file (index = 0 -> none) */ #define DisplayOffsetStepIcons(p) ((p)+112) /*!< Index in step icon collection file (index = 0 -> none) */ #define DisplayOffsetFlags 117 /*!< Update flags enumerated above */ #define DisplayOffsetTextLinesCenterFlags 118 /*!< Mask to center TextLines */ #define DisplayOffsetNormal(l,w) (((l)*100)+(w)+119) /*!< Raw display memory for normal screen */ #define DisplayOffsetPopup(l,w) (((l)*100)+(w)+919) /*!< Raw display memory for popup screen */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define DisplayOffsetContrast 1719 /*!< Adjust the display contrast with this field */ #endif /** @} */ // end of DisplayIOMAP group /** @} */ // end of DisplayModuleConstants group /** @} */ // end of DisplayModule group /** @addtogroup CommModule * @{ */ /** @defgroup CommModuleConstants Comm module constants * Constants that are part of the NXT firmware's Comm module. * @{ */ /** @defgroup CommMiscConstants Miscellaneous Comm module constants * Miscellaneous constants related to the Comm module. * @{ */ #define SIZE_OF_USBBUF 64 /*!< Size of USB Buffer in bytes */ #define USB_PROTOCOL_OVERHEAD 2 /*!< Size of USB Overhead in bytes -- Command type byte + Command*/ #define SIZE_OF_USBDATA 62 /*!< Size of USB Buffer available for data */ #define SIZE_OF_HSBUF 128 /*!< Size of High Speed Port 4 buffer */ #define SIZE_OF_BTBUF 128 /*!< Size of Bluetooth buffer*/ #define BT_CMD_BYTE 1 /*!< Size of Bluetooth command*/ #define SIZE_OF_BT_DEVICE_TABLE 30 /*!< Size of Bluetooth device table */ #define SIZE_OF_BT_CONNECT_TABLE 4 /*!< Size of Bluetooth connection table -- Index 0 is always incoming connection */ #define SIZE_OF_BT_NAME 16 /*!< Size of Bluetooth name */ #define SIZE_OF_BRICK_NAME 8 /*!< Size of NXT Brick name */ #define SIZE_OF_CLASS_OF_DEVICE 4 /*!< Size of class of device */ #define SIZE_OF_BT_PINCODE 16 /*!< Size of Bluetooth PIN */ #define SIZE_OF_BDADDR 7 /*!< Size of Bluetooth Address*/ #define MAX_BT_MSG_SIZE 60000 /*!< Max Bluetooth Message Size */ #define BT_DEFAULT_INQUIRY_MAX 0 /*!< Bluetooth default inquiry Max (0 == unlimited)*/ #define BT_DEFAULT_INQUIRY_TIMEOUT_LO 15 /*!< Bluetooth inquiry timeout (15*1.28 sec = 19.2 sec) */ /** @} */ // end of CommMiscConstants group /** @defgroup CommBtStateConstants Bluetooth State constants * Constants related to the bluetooth state. * @{ */ #define BT_ARM_OFF 0 /*!< BtState constant bluetooth off */ #define BT_ARM_CMD_MODE 1 /*!< BtState constant bluetooth command mode */ #define BT_ARM_DATA_MODE 2 /*!< BtState constant bluetooth data mode */ /** @} */ // end of CommBtStateConstants group /** @defgroup CommDataModeConstants Data mode constants * Constants related to the bluetooth and hi-speed data modes. * @{ */ #define DATA_MODE_NXT 0x00 /*!< Use NXT data mode */ #define DATA_MODE_GPS 0x01 /*!< Use GPS data mode */ #define DATA_MODE_RAW 0x02 /*!< Use RAW data mode */ #define DATA_MODE_MASK 0x07 /*!< A mask for the data mode bits. */ #define DATA_MODE_UPDATE 0x08 /*!< Indicates that the data mode has been changed. */ /** @} */ // end of CommDataModeConstants group /** @defgroup CommBtStateStatusConstants Bluetooth state status constants * Constants related to the bluetooth state status. * @{ */ #define BT_BRICK_VISIBILITY 0x01 /*!< BtStateStatus brick visibility bit */ #define BT_BRICK_PORT_OPEN 0x02 /*!< BtStateStatus port open bit */ #define BT_CONNECTION_0_ENABLE 0x10 /*!< BtStateStatus connection 0 enable/disable bit */ #define BT_CONNECTION_1_ENABLE 0x20 /*!< BtStateStatus connection 1 enable/disable bit */ #define BT_CONNECTION_2_ENABLE 0x40 /*!< BtStateStatus connection 2 enable/disable bit */ #define BT_CONNECTION_3_ENABLE 0x80 /*!< BtStateStatus connection 3 enable/disable bit */ /** @} */ // end of CommBtStateStatusConstants group /** @defgroup CommConnectionConstants Remote connection constants * Constants for specifying remote connection slots. * @{ */ #define CONN_BT0 0x0 /*!< Bluetooth connection 0 */ #define CONN_BT1 0x1 /*!< Bluetooth connection 1 */ #define CONN_BT2 0x2 /*!< Bluetooth connection 2 */ #define CONN_BT3 0x3 /*!< Bluetooth connection 3 */ #define CONN_HS4 0x4 /*!< RS485 (hi-speed) connection (port 4, all devices) */ #define CONN_HS_ALL 0x4 /*!< RS485 (hi-speed) connection (port 4, all devices) */ #define CONN_HS_1 0x5 /*!< RS485 (hi-speed) connection (port 4, device address 1) */ #define CONN_HS_2 0x6 /*!< RS485 (hi-speed) connection (port 4, device address 2) */ #define CONN_HS_3 0x7 /*!< RS485 (hi-speed) connection (port 4, device address 3) */ #define CONN_HS_4 0x8 /*!< RS485 (hi-speed) connection (port 4, device address 4) */ #define CONN_HS_5 0x9 /*!< RS485 (hi-speed) connection (port 4, device address 5) */ #define CONN_HS_6 0xa /*!< RS485 (hi-speed) connection (port 4, device address 6) */ #define CONN_HS_7 0xb /*!< RS485 (hi-speed) connection (port 4, device address 7) */ #define CONN_HS_8 0xc /*!< RS485 (hi-speed) connection (port 4, device address 8) */ /** @} */ // end of CommConnectionConstants group /** @defgroup CommBtHwStatusConstants Bluetooth hardware status constants * Constants related to the bluetooth hardware status. * @{ */ #define BT_ENABLE 0x00 /*!< BtHwStatus bluetooth enable */ #define BT_DISABLE 0x01 /*!< BtHwStatus bluetooth disable */ /** @} */ // end of CommBtHwStatusConstants group /** @defgroup CommHiSpeedConstants Hi-speed port constants * Constants related to the hi-speed port. * @{ */ /** @defgroup CommHiSpeedFlagsConstants Hi-speed port flags constants * Constants related to the hi-speed port flags. * @{ */ #define HS_UPDATE 1 /*!< HsFlags high speed update required */ /** @} */ // end of CommHiSpeedFlagsConstants group /** @defgroup CommHiSpeedStateConstants Hi-speed port state constants * Constants related to the hi-speed port state. * @{ */ #define HS_INITIALISE 1 /*!< HsState initialize */ #define HS_INIT_RECEIVER 2 /*!< HsState initialize receiver */ #define HS_SEND_DATA 3 /*!< HsState send data */ #define HS_DISABLE 4 /*!< HsState disable */ #define HS_ENABLE 5 /*!< HsState enable */ /** @} */ // end of CommHiSpeedStateConstants group #ifdef __ENHANCED_FIRMWARE /** @defgroup CommHiSpeedCtrlConstants Hi-speed port SysCommHSControl constants * Constants for use with the SysCommHSControl API function. * \sa SysCommHSControl() * @{ */ #define HS_CTRL_INIT 0 /*!< Enable the high speed port */ #define HS_CTRL_UART 1 /*!< Setup the high speed port UART configuration */ #define HS_CTRL_EXIT 2 /*!< Ddisable the high speed port */ /** @} */ // end of CommHiSpeedCtrlConstants group #if __FIRMWARE_VERSION > 107 /** @defgroup CommHiSpeedBaudConstants Hi-speed port baud rate constants * Constants for configuring the hi-speed port baud rate (HsSpeed). * @{ */ #define HS_BAUD_1200 0 /*!< HsSpeed 1200 Baud */ #define HS_BAUD_2400 1 /*!< HsSpeed 2400 Baud */ #define HS_BAUD_3600 2 /*!< HsSpeed 3600 Baud */ #define HS_BAUD_4800 3 /*!< HsSpeed 4800 Baud */ #define HS_BAUD_7200 4 /*!< HsSpeed 7200 Baud */ #define HS_BAUD_9600 5 /*!< HsSpeed 9600 Baud */ #define HS_BAUD_14400 6 /*!< HsSpeed 14400 Baud */ #define HS_BAUD_19200 7 /*!< HsSpeed 19200 Baud */ #define HS_BAUD_28800 8 /*!< HsSpeed 28800 Baud */ #define HS_BAUD_38400 9 /*!< HsSpeed 38400 Baud */ #define HS_BAUD_57600 10 /*!< HsSpeed 57600 Baud */ #define HS_BAUD_76800 11 /*!< HsSpeed 76800 Baud */ #define HS_BAUD_115200 12 /*!< HsSpeed 115200 Baud */ #define HS_BAUD_230400 13 /*!< HsSpeed 230400 Baud */ #define HS_BAUD_460800 14 /*!< HsSpeed 460800 Baud */ #define HS_BAUD_921600 15 /*!< HsSpeed 921600 Baud */ #define HS_BAUD_DEFAULT 15 /*!< HsSpeed default Baud (921600) */ /** @} */ // end of CommHiSpeedBaudConstants group /** @defgroup CommHiSpeedModeConstants Hi-speed port UART mode constants * Constants referring to HsMode UART configuration settings * @{ */ #define HS_MODE_DEFAULT HS_MODE_8N1 /*!< HsMode default mode (8 data bits, no parity, 1 stop bit) */ /** @defgroup CommHiSpeedDataBitsConstants Hi-speed port data bits constants * Constants referring to HsMode (number of data bits) * @{ */ #define HS_MODE_5_DATA 0x0000 /*!< HsMode 5 data bits */ #define HS_MODE_6_DATA 0x0040 /*!< HsMode 6 data bits */ #define HS_MODE_7_DATA 0x0080 /*!< HsMode 7 data bits */ #define HS_MODE_8_DATA 0x00C0 /*!< HsMode 8 data bits */ /** @} */ // end of CommHiSpeedDataBitsConstants group /** @defgroup CommHiSpeedStopBitsConstants Hi-speed port stop bits constants * Constants referring to HsMode (number of stop bits) * @{ */ #define HS_MODE_10_STOP 0x0000 /*!< HsMode 1 stop bit */ #define HS_MODE_15_STOP 0x1000 /*!< HsMode 1.5 stop bits */ #define HS_MODE_20_STOP 0x2000 /*!< HsMode 2 stop bits */ /** @} */ // end of CommHiSpeedStopBitsConstants group /** @defgroup CommHiSpeedParityConstants Hi-speed port parity constants * Constants referring to HsMode (parity) * @{ */ #define HS_MODE_E_PARITY 0x0000 /*!< HsMode Even parity */ #define HS_MODE_O_PARITY 0x0200 /*!< HsMode Odd parity */ #define HS_MODE_S_PARITY 0x0400 /*!< HsMode Space parity */ #define HS_MODE_M_PARITY 0x0600 /*!< HsMode Mark parity */ #define HS_MODE_N_PARITY 0x0800 /*!< HsMode No parity */ /** @} */ // end of CommHiSpeedParityConstants group /** @defgroup CommHiSpeedCombinedConstants Hi-speed port combined UART constants * Constants that combine data bits, parity, and stop bits into a single value. * @{ */ #define HS_MODE_8N1 (HS_MODE_8_DATA|HS_MODE_N_PARITY|HS_MODE_10_STOP) /*!< HsMode 8 data bits, no parity, 1 stop bit */ #define HS_MODE_7E1 (HS_MODE_7_DATA|HS_MODE_E_PARITY|HS_MODE_10_STOP) /*!< HsMode 7 data bits, even parity, 1 stop bit */ /** @} */ // end of CommHiSpeedCombinedConstants group /** @} */ // end of CommHiSpeedModeConstants group /** @defgroup CommHiSpeedAddressConstants Hi-speed port address constants * Constants that are used to specify the Hi-speed (RS-485) port device address. * @{ */ #define HS_ADDRESS_ALL 0 /*!< HsAddress all devices */ #define HS_ADDRESS_1 1 /*!< HsAddress device address 1 */ #define HS_ADDRESS_2 2 /*!< HsAddress device address 2 */ #define HS_ADDRESS_3 3 /*!< HsAddress device address 3 */ #define HS_ADDRESS_4 4 /*!< HsAddress device address 4 */ #define HS_ADDRESS_5 5 /*!< HsAddress device address 5 */ #define HS_ADDRESS_6 6 /*!< HsAddress device address 6 */ #define HS_ADDRESS_7 7 /*!< HsAddress device address 7 */ #define HS_ADDRESS_8 8 /*!< HsAddress device address 8 */ /** @} */ // end of CommHiSpeedAddressConstants group #endif #endif /** @} */ // end of CommHiSpeedConstants group /** @defgroup CommDeviceStatusConstants Device status constants * Constants refering to DeviceStatus within DeviceTable * @{ */ #define BT_DEVICE_EMPTY 0x00 /*!< Bluetooth device table empty */ #define BT_DEVICE_UNKNOWN 0x01 /*!< Bluetooth device unknown */ #define BT_DEVICE_KNOWN 0x02 /*!< Bluetooth device known */ #define BT_DEVICE_NAME 0x40 /*!< Bluetooth device name */ #define BT_DEVICE_AWAY 0x80 /*!< Bluetooth device away */ /** @} */ // end of CommDeviceStatusConstants group /** @defgroup CommInterfaceConstants Comm module interface function constants * Constants for all the Comm module interface functions executable via SysCommExecuteFunction. * \sa SysCommExecuteFunction() * @{ */ #define INTF_SENDFILE 0 /*!< Send a file via bluetooth to another device */ #define INTF_SEARCH 1 /*!< Search for bluetooth devices */ #define INTF_STOPSEARCH 2 /*!< Stop searching for bluetooth devices */ #define INTF_CONNECT 3 /*!< Connect to one of the known devices */ #define INTF_DISCONNECT 4 /*!< Disconnect from one of the connected devices */ #define INTF_DISCONNECTALL 5 /*!< Disconnect all devices */ #define INTF_REMOVEDEVICE 6 /*!< Remove a device from the known devices table */ #define INTF_VISIBILITY 7 /*!< Set the bluetooth visibility on or off */ #define INTF_SETCMDMODE 8 /*!< Set bluetooth into command mode */ #define INTF_OPENSTREAM 9 /*!< Open a bluetooth stream */ #define INTF_SENDDATA 10 /*!< Send data over a bluetooth connection */ #define INTF_FACTORYRESET 11 /*!< Reset bluetooth settings to factory values */ #define INTF_BTON 12 /*!< Turn on the bluetooth radio */ #define INTF_BTOFF 13 /*!< Turn off the bluetooth radio */ #define INTF_SETBTNAME 14 /*!< Set the bluetooth name */ #define INTF_EXTREAD 15 /*!< External read request */ #define INTF_PINREQ 16 /*!< Bluetooth PIN request */ #define INTF_CONNECTREQ 17 /*!< Connection request from another device */ #if __FIRMWARE_VERSION > 107 #define INTF_CONNECTBYNAME 18 /*!< Connect to a bluetooth device by name */ #endif /** @} */ // end of CommInterfaceConstants group /** @defgroup CommStatusCodesConstants Comm module status code constants * Constants for Comm module status codes. * @{ */ #define LR_SUCCESS 0x50 /*!< Bluetooth list result success */ #define LR_COULD_NOT_SAVE 0x51 /*!< Bluetooth list result could not save */ #define LR_STORE_IS_FULL 0x52 /*!< Bluetooth list result store is full */ #define LR_ENTRY_REMOVED 0x53 /*!< Bluetooth list result entry removed */ #define LR_UNKNOWN_ADDR 0x54 /*!< Bluetooth list result unknown address */ #define USB_CMD_READY 0x01 /*!< A constant representing usb direct command */ #define BT_CMD_READY 0x02 /*!< A constant representing bluetooth direct command */ #define HS_CMD_READY 0x04 /*!< A constant representing high speed direct command */ /** @} */ // end of CommStatusCodesConstants group /** @defgroup CommIOMAP Comm module IOMAP offsets * Constant offsets into the Comm module IOMAP structure. * @{ */ #define CommOffsetPFunc 0 /*!< Offset to the Comm module first function pointer (4 bytes) */ #define CommOffsetPFuncTwo 4 /*!< Offset to the Comm module second function pointer (4 bytes) */ // BtDeviceTable[30] (930 bytes) #define CommOffsetBtDeviceTableName(p) (((p)*31)+8) /*!< Offset to BT device table name (16 bytes) */ #define CommOffsetBtDeviceTableClassOfDevice(p) (((p)*31)+24) /*!< Offset to Bluetooth device table device class (4 bytes) */ #define CommOffsetBtDeviceTableBdAddr(p) (((p)*31)+28) /*!< Offset to Bluetooth device table address (7 bytes) */ #define CommOffsetBtDeviceTableDeviceStatus(p) (((p)*31)+35) /*!< Offset to Bluetooth device table status (1 byte) */ // BDCONNECTTABLE BtConnectTable[4]; (188 bytes) #define CommOffsetBtConnectTableName(p) (((p)*47)+938) /*!< Offset to Bluetooth connect table name (16 bytes) */ #define CommOffsetBtConnectTableClassOfDevice(p) (((p)*47)+954) /*!< Offset to Bluetooth connect table device class (4 bytes) */ #define CommOffsetBtConnectTablePinCode(p) (((p)*47)+958) /*!< Offset to Bluetooth connect table pin code (16 bytes) */ #define CommOffsetBtConnectTableBdAddr(p) (((p)*47)+974) /*!< Offset to Bluetooth connect table address (7 bytes) */ #define CommOffsetBtConnectTableHandleNr(p) (((p)*47)+981) /*!< Offset to Bluetooth connect table handle (1 byte) */ #define CommOffsetBtConnectTableStreamStatus(p) (((p)*47)+982) /*!< Offset to Bluetooth connect table stream status (1 byte) */ #define CommOffsetBtConnectTableLinkQuality(p) (((p)*47)+983) /*!< Offset to Bluetooth connect table link quality (1 byte) */ //General brick data // BRICKDATA BrickData; (31 bytes) #define CommOffsetBrickDataName 1126 /*!< Offset to brick name (16 bytes) */ #define CommOffsetBrickDataBluecoreVersion 1142 /*!< Offset to Bluecore version (2 bytes) */ #define CommOffsetBrickDataBdAddr 1144 /*!< Offset to Bluetooth address (7 bytes) */ #define CommOffsetBrickDataBtStateStatus 1151 /*!< Offset to BtStateStatus (1 byte) */ #define CommOffsetBrickDataBtHwStatus 1152 /*!< Offset to BtHwStatus (1 byte) */ #define CommOffsetBrickDataTimeOutValue 1153 /*!< Offset to data timeout value (1 byte) */ // BTBUF BtInBuf; (132 bytes) #define CommOffsetBtInBufBuf 1157 /*!< Offset to Bluetooth input buffer data (128 bytes) */ #define CommOffsetBtInBufInPtr 1285 /*!< Offset to Bluetooth input buffer front pointer (1 byte) */ #define CommOffsetBtInBufOutPtr 1286 /*!< Offset to Bluetooth output buffer back pointer (1 byte) */ // BTBUF BtOutBuf; (132 bytes) #define CommOffsetBtOutBufBuf 1289 /*!< Offset to Bluetooth output buffer offset data (128 bytes) */ #define CommOffsetBtOutBufInPtr 1417 /*!< Offset to Bluetooth output buffer front pointer (1 byte) */ #define CommOffsetBtOutBufOutPtr 1418 /*!< Offset to Bluetooth output buffer back pointer (1 byte) */ // HI Speed related entries // HSBUF HsInBuf; (132 bytes) #define CommOffsetHsInBufBuf 1421 /*!< Offset to High Speed input buffer data (128 bytes) */ #define CommOffsetHsInBufInPtr 1549 /*!< Offset to High Speed input buffer front pointer (1 byte) */ #define CommOffsetHsInBufOutPtr 1550 /*!< Offset to High Speed input buffer back pointer (1 byte) */ // HSBUF HsOutBuf; (132 bytes) #define CommOffsetHsOutBufBuf 1553 /*!< Offset to High Speed output buffer data (128 bytes) */ #define CommOffsetHsOutBufInPtr 1681 /*!< Offset to High Speed output buffer front pointer (1 byte) */ #define CommOffsetHsOutBufOutPtr 1682 /*!< Offset to High Speed output buffer back pointer (1 byte) */ // USB related entries // USBBUF UsbInBuf; (68 bytes) #define CommOffsetUsbInBufBuf 1685 /*!< Offset to Usb input buffer data (64 bytes) */ #define CommOffsetUsbInBufInPtr 1749 /*!< Offset to Usb input buffer front pointer (1 byte) */ #define CommOffsetUsbInBufOutPtr 1750 /*!< Offset to Usb input buffer back pointer (1 byte) */ // USBBUF UsbOutBuf; (68 bytes) #define CommOffsetUsbOutBufBuf 1753 /*!< Offset to Usb output buffer data (64 bytes) */ #define CommOffsetUsbOutBufInPtr 1817 /*!< Offset to Usb output buffer front pointer (1 byte) */ #define CommOffsetUsbOutBufOutPtr 1818 /*!< Offset to Usb output buffer back pointer (1 byte) */ // USBBUF UsbPollBuf; (68 bytes) #define CommOffsetUsbPollBufBuf 1821 /*!< Offset to Usb Poll buffer data (64 bytes) */ #define CommOffsetUsbPollBufInPtr 1885 /*!< Offset to Usb Poll buffer front pointer (1 byte) */ #define CommOffsetUsbPollBufOutPtr 1886 /*!< Offset to Usb Poll buffer back pointer (1 byte) */ #define CommOffsetBtDeviceCnt 1889 /*!< Offset to Bluetooth device count (1 byte) */ #define CommOffsetBtDeviceNameCnt 1890 /*!< Offset to Bluetooth device name count (1 byte) */ #define CommOffsetHsFlags 1891 /*!< Offset to High Speed flags (1 byte) */ #define CommOffsetHsSpeed 1892 /*!< Offset to High Speed speed (1 byte) */ #define CommOffsetHsState 1893 /*!< Offset to High Speed state (1 byte) */ #define CommOffsetUsbState 1894 /*!< Offset to Usb State (1 byte) */ #ifdef __ENHANCED_FIRMWARE #define CommOffsetHsMode 1896 /*!< Offset to High Speed mode (2 bytes) */ #define CommOffsetBtDataMode 1898 /*!< Offset to Bluetooth data mode (1 byte) */ #define CommOffsetHsDataMode 1899 /*!< Offset to High Speed data mode (1 byte) */ #endif /** @} */ // end of CommIOMAP group /** @} */ // end of CommModuleConstants group /** @} */ // end of CommModule group /** @addtogroup ThirdPartyDevices * @{ */ /** @defgroup RCXAPIConstants RCX constants * Constants that are for use with devices that communicate with the RCX or * Scout programmable bricks via IR such as the HiTechnic IRLink or the * MindSensors nRLink. * @{ */ /** @defgroup RCXOutputConstants RCX output constants * Constants for use when choosing RCX outputs. * @{ */ #define RCX_OUT_A 0x01 /*!< RCX Output A */ #define RCX_OUT_B 0x02 /*!< RCX Output B */ #define RCX_OUT_C 0x04 /*!< RCX Output C */ #define RCX_OUT_AB 0x03 /*!< RCX Outputs A and B */ #define RCX_OUT_AC 0x05 /*!< RCX Outputs A and C */ #define RCX_OUT_BC 0x06 /*!< RCX Outputs B and C */ #define RCX_OUT_ABC 0x07 /*!< RCX Outputs A, B, and C */ /** @} */ // end of RCXOutputConstants group /** @defgroup RCXOutputMode RCX output mode constants * Constants for use when configuring RCX output mode. * @{ */ #define RCX_OUT_FLOAT 0 /*!< Set RCX output to float */ #define RCX_OUT_OFF 0x40 /*!< Set RCX output to off */ #define RCX_OUT_ON 0x80 /*!< Set RCX output to on */ /** @} */ // end of RCXOutputMode group /** @defgroup RCXOutputDirection RCX output direction constants * Constants for use when configuring RCX output direction. * @{ */ #define RCX_OUT_REV 0 /*!< Set RCX output direction to reverse */ #define RCX_OUT_TOGGLE 0x40 /*!< Set RCX output direction to toggle */ #define RCX_OUT_FWD 0x80 /*!< Set RCX output direction to forward */ /** @} */ // end of RCXOutputConstants group /** @defgroup RCXOutputPower RCX output power constants * Constants for use when configuring RCX output power. * @{ */ #define RCX_OUT_LOW 0 /*!< Set RCX output power level to low */ #define RCX_OUT_HALF 3 /*!< Set RCX output power level to half */ #define RCX_OUT_FULL 7 /*!< Set RCX output power level to full */ /** @} */ // end of RCXOutputPower group /** @defgroup RCXRemoteConstants RCX IR remote constants * Constants for use when simulating RCX IR remote messages. * @{ */ #define RCX_RemoteKeysReleased 0x0000 /*!< All remote keys have been released */ #define RCX_RemotePBMessage1 0x0100 /*!< Send PB message 1 */ #define RCX_RemotePBMessage2 0x0200 /*!< Send PB message 2 */ #define RCX_RemotePBMessage3 0x0400 /*!< Send PB message 3 */ #define RCX_RemoteOutAForward 0x0800 /*!< Set output A forward */ #define RCX_RemoteOutBForward 0x1000 /*!< Set output B forward */ #define RCX_RemoteOutCForward 0x2000 /*!< Set output C forward */ #define RCX_RemoteOutABackward 0x4000 /*!< Set output A backward */ #define RCX_RemoteOutBBackward 0x8000 /*!< Set output B backward */ #define RCX_RemoteOutCBackward 0x0001 /*!< Set output C backward */ #define RCX_RemoteSelProgram1 0x0002 /*!< Select program 1 */ #define RCX_RemoteSelProgram2 0x0004 /*!< Select program 2 */ #define RCX_RemoteSelProgram3 0x0008 /*!< Select program 3 */ #define RCX_RemoteSelProgram4 0x0010 /*!< Select program 4 */ #define RCX_RemoteSelProgram5 0x0020 /*!< Select program 5 */ #define RCX_RemoteStopOutOff 0x0040 /*!< Stop and turn off outputs */ #define RCX_RemotePlayASound 0x0080 /*!< Play a sound */ /** @} */ // end of RCXRemoteConstants group /** @defgroup RCXSoundConstants RCX and Scout sound constants * Constants for use when playing standard RCX and Scout sounds. * @{ */ #define SOUND_CLICK 0 /*!< Play the standard key click sound */ #define SOUND_DOUBLE_BEEP 1 /*!< Play the standard double beep sound */ #define SOUND_DOWN 2 /*!< Play the standard sweep down sound */ #define SOUND_UP 3 /*!< Play the standard sweep up sound */ #define SOUND_LOW_BEEP 4 /*!< Play the standard low beep sound */ #define SOUND_FAST_UP 5 /*!< Play the standard fast up sound */ /** @} */ // end of RCXSoundConstants group /** @defgroup ScoutConstants Scout constants * Constants for use when controlling the Scout brick. * @{ */ /** @defgroup ScoutLightConstants Scout light constants * Constants for use when controlling the Scout light settings. * @{ */ #define SCOUT_LIGHT_ON 0x80 /*!< Turn on the scout light */ #define SCOUT_LIGHT_OFF 0 /*!< Turn off the scout light */ /** @} */ // end of ScoutLightConstants group /** @defgroup ScoutSoundConstants Scout sound constants * Constants for use when playing standard Scout sounds. * @{ */ #define SCOUT_SOUND_REMOTE 6 /*!< Play the Scout remote sound */ #define SCOUT_SOUND_ENTERSA 7 /*!< Play the Scout enter standalone sound */ #define SCOUT_SOUND_KEYERROR 8 /*!< Play the Scout key error sound */ #define SCOUT_SOUND_NONE 9 /*!< Play the Scout none sound */ #define SCOUT_SOUND_TOUCH1_PRES 10 /*!< Play the Scout touch 1 pressed sound */ #define SCOUT_SOUND_TOUCH1_REL 11 /*!< Play the Scout touch 1 released sound */ #define SCOUT_SOUND_TOUCH2_PRES 12 /*!< Play the Scout touch 2 pressed sound */ #define SCOUT_SOUND_TOUCH2_REL 13 /*!< Play the Scout touch 2 released sound */ #define SCOUT_SOUND_ENTER_BRIGHT 14 /*!< Play the Scout enter bright sound */ #define SCOUT_SOUND_ENTER_NORMAL 15 /*!< Play the Scout enter normal sound */ #define SCOUT_SOUND_ENTER_DARK 16 /*!< Play the Scout enter dark sound */ #define SCOUT_SOUND_1_BLINK 17 /*!< Play the Scout 1 blink sound */ #define SCOUT_SOUND_2_BLINK 18 /*!< Play the Scout 2 blink sound */ #define SCOUT_SOUND_COUNTER1 19 /*!< Play the Scout counter 1 sound */ #define SCOUT_SOUND_COUNTER2 20 /*!< Play the Scout counter 2 sound */ #define SCOUT_SOUND_TIMER1 21 /*!< Play the Scout timer 1 sound */ #define SCOUT_SOUND_TIMER2 22 /*!< Play the Scout timer 2 sound */ #define SCOUT_SOUND_TIMER3 23 /*!< Play the Scout timer 3 sound */ #define SCOUT_SOUND_MAIL_RECEIVED 24 /*!< Play the Scout mail received sound */ #define SCOUT_SOUND_SPECIAL1 25 /*!< Play the Scout special 1 sound */ #define SCOUT_SOUND_SPECIAL2 26 /*!< Play the Scout special 2 sound */ #define SCOUT_SOUND_SPECIAL3 27 /*!< Play the Scout special 3 sound */ /** @} */ // end of ScoutSoundConstants group /** @defgroup ScoutSndSetConstants Scout sound set constants * Constants for use when choosing standard Scout sound sets. * @{ */ #define SCOUT_SNDSET_NONE 0 /*!< Set sound set to none */ #define SCOUT_SNDSET_BASIC 1 /*!< Set sound set to basic */ #define SCOUT_SNDSET_BUG 2 /*!< Set sound set to bug */ #define SCOUT_SNDSET_ALARM 3 /*!< Set sound set to alarm */ #define SCOUT_SNDSET_RANDOM 4 /*!< Set sound set to random */ #define SCOUT_SNDSET_SCIENCE 5 /*!< Set sound set to science */ /** @} */ // end of ScoutSndSetConstants group /** @defgroup ScoutModeConstants Scout mode constants * Constants for use when setting the scout mode. * @{ */ #define SCOUT_MODE_STANDALONE 0 /*!< Enter stand alone mode */ #define SCOUT_MODE_POWER 1 /*!< Enter power mode */ /** @} */ // end of ScoutModeConstants group /** @defgroup ScoutMotionRuleConstants Scout motion rule constants * Constants for use when setting the scout motion rule. * @{ */ #define SCOUT_MR_NO_MOTION 0 /*!< Motion rule none */ #define SCOUT_MR_FORWARD 1 /*!< Motion rule forward */ #define SCOUT_MR_ZIGZAG 2 /*!< Motion rule zigzag */ #define SCOUT_MR_CIRCLE_RIGHT 3 /*!< Motion rule circle right */ #define SCOUT_MR_CIRCLE_LEFT 4 /*!< Motion rule circle left */ #define SCOUT_MR_LOOP_A 5 /*!< Motion rule loop A */ #define SCOUT_MR_LOOP_B 6 /*!< Motion rule loop B */ #define SCOUT_MR_LOOP_AB 7 /*!< Motion rule loop A then B */ /** @} */ // end of ScoutMotionRuleConstants group /** @defgroup ScoutTouchRuleConstants Scout touch rule constants * Constants for use when setting the scout touch rule. * @{ */ #define SCOUT_TR_IGNORE 0 /*!< Touch rule ignore */ #define SCOUT_TR_REVERSE 1 /*!< Touch rule reverse */ #define SCOUT_TR_AVOID 2 /*!< Touch rule avoid */ #define SCOUT_TR_WAIT_FOR 3 /*!< Touch rule wait for */ #define SCOUT_TR_OFF_WHEN 4 /*!< Touch rule off when */ /** @} */ // end of ScoutTouchRuleConstants group /** @defgroup ScoutLightRuleConstants Scout light rule constants * Constants for use when setting the scout light rule. * @{ */ #define SCOUT_LR_IGNORE 0 /*!< Light rule ignore */ #define SCOUT_LR_SEEK_LIGHT 1 /*!< Light rule seek light */ #define SCOUT_LR_SEEK_DARK 2 /*!< Light rule seek dark */ #define SCOUT_LR_AVOID 3 /*!< Light rule avoid */ #define SCOUT_LR_WAIT_FOR 4 /*!< Light rule wait for */ #define SCOUT_LR_OFF_WHEN 5 /*!< Light rule off when */ /** @} */ // end of ScoutLightRuleConstants group /** @defgroup ScoutTransmitRuleConstants Scout transmit rule constants * Constants for use when setting the scout transmit rule. * @{ */ #define SCOUT_TGS_SHORT 0 /*!< Transmit level short */ #define SCOUT_TGS_MEDIUM 1 /*!< Transmit level medium */ #define SCOUT_TGS_LONG 2 /*!< Transmit level long */ /** @} */ // end of ScoutTransmitRuleConstants group /** @defgroup ScoutSpecialEffectConstants Scout special effect constants * Constants for use when setting the scout special effect. * @{ */ #define SCOUT_FXR_NONE 0 /*!< No special effects */ #define SCOUT_FXR_BUG 1 /*!< Bug special effects */ #define SCOUT_FXR_ALARM 2 /*!< Alarm special effects */ #define SCOUT_FXR_RANDOM 3 /*!< Random special effects */ #define SCOUT_FXR_SCIENCE 4 /*!< Science special effects */ /** @} */ // end of ScoutSpecialEffectConstants group /** @} */ // end of ScoutConstants group /** @defgroup RCXSourceConstants RCX and Scout source constants * Constants for use when specifying RCX and Scout sources. * @{ */ #define RCX_VariableSrc 0 /*!< The RCX variable source */ #define RCX_TimerSrc 1 /*!< The RCX timer source */ #define RCX_ConstantSrc 2 /*!< The RCX constant value source */ #define RCX_OutputStatusSrc 3 /*!< The RCX output status source */ #define RCX_RandomSrc 4 /*!< The RCX random number source */ #define RCX_ProgramSlotSrc 8 /*!< The RCX program slot source */ #define RCX_InputValueSrc 9 /*!< The RCX input value source */ #define RCX_InputTypeSrc 10 /*!< The RCX input type source */ #define RCX_InputModeSrc 11 /*!< The RCX input mode source */ #define RCX_InputRawSrc 12 /*!< The RCX input raw source */ #define RCX_InputBooleanSrc 13 /*!< The RCX input boolean source */ #define RCX_WatchSrc 14 /*!< The RCX watch source */ #define RCX_MessageSrc 15 /*!< The RCX message source */ #define RCX_GlobalMotorStatusSrc 17 /*!< The RCX global motor status source */ #define RCX_ScoutRulesSrc 18 /*!< The Scout rules source */ #define RCX_ScoutLightParamsSrc 19 /*!< The Scout light parameters source */ #define RCX_ScoutTimerLimitSrc 20 /*!< The Scout timer limit source */ #define RCX_CounterSrc 21 /*!< The RCX counter source */ #define RCX_ScoutCounterLimitSrc 22 /*!< The Scout counter limit source */ #define RCX_TaskEventsSrc 23 /*!< The RCX task events source */ #define RCX_ScoutEventFBSrc 24 /*!< The Scout event feedback source */ #define RCX_EventStateSrc 25 /*!< The RCX event static source */ #define RCX_TenMSTimerSrc 26 /*!< The RCX 10ms timer source */ #define RCX_ClickCounterSrc 27 /*!< The RCX event click counter source */ #define RCX_UpperThresholdSrc 28 /*!< The RCX event upper threshold source */ #define RCX_LowerThresholdSrc 29 /*!< The RCX event lower threshold source */ #define RCX_HysteresisSrc 30 /*!< The RCX event hysteresis source */ #define RCX_DurationSrc 31 /*!< The RCX event duration source */ #define RCX_UARTSetupSrc 33 /*!< The RCX UART setup source */ #define RCX_BatteryLevelSrc 34 /*!< The RCX battery level source */ #define RCX_FirmwareVersionSrc 35 /*!< The RCX firmware version source */ #define RCX_IndirectVarSrc 36 /*!< The RCX indirect variable source */ #define RCX_DatalogSrcIndirectSrc 37 /*!< The RCX indirect datalog source source */ #define RCX_DatalogSrcDirectSrc 38 /*!< The RCX direct datalog source source */ #define RCX_DatalogValueIndirectSrc 39 /*!< The RCX indirect datalog value source */ #define RCX_DatalogValueDirectSrc 40 /*!< The RCX direct datalog value source */ #define RCX_DatalogRawIndirectSrc 41 /*!< The RCX indirect datalog raw source */ #define RCX_DatalogRawDirectSrc 42 /*!< The RCX direct datalog raw source */ /** @} */ // end of RCXSourceConstants group /** @defgroup RCXOpcodeConstants RCX and Scout opcode constants * Constants for use when specifying RCX and Scout opcodes. * @{ */ #define RCX_PingOp 0x10 /*!< Ping the brick */ #define RCX_BatteryLevelOp 0x30 /*!< Read the battery level */ #define RCX_DeleteTasksOp 0x40 /*!< Delete tasks */ #define RCX_StopAllTasksOp 0x50 /*!< Stop all tasks */ #define RCX_PBTurnOffOp 0x60 /*!< Turn off the brick */ #define RCX_DeleteSubsOp 0x70 /*!< Delete subroutines */ #define RCX_ClearSoundOp 0x80 /*!< Clear sound */ #define RCX_ClearMsgOp 0x90 /*!< Clear message */ #define RCX_LSCalibrateOp 0xc0 /*!< Calibrate the light sensor */ #define RCX_MuteSoundOp 0xd0 /*!< Mute sound */ #define RCX_UnmuteSoundOp 0xe0 /*!< Unmute sound */ #define RCX_ClearAllEventsOp 0x06 /*!< Clear all events */ #define RCX_OnOffFloatOp 0x21 /*!< Control motor state - on, off, float */ #define RCX_IRModeOp 0x31 /*!< Set the IR transmit mode */ #define RCX_PlaySoundOp 0x51 /*!< Play a sound */ #define RCX_DeleteTaskOp 0x61 /*!< Delete a task */ #define RCX_StartTaskOp 0x71 /*!< Start a task */ #define RCX_StopTaskOp 0x81 /*!< Stop a task */ #define RCX_SelectProgramOp 0x91 /*!< Select a program slot */ #define RCX_ClearTimerOp 0xa1 /*!< Clear a timer */ #define RCX_AutoOffOp 0xb1 /*!< Set auto off timer */ #define RCX_DeleteSubOp 0xc1 /*!< Delete a subroutine */ #define RCX_ClearSensorOp 0xd1 /*!< Clear a sensor */ #define RCX_OutputDirOp 0xe1 /*!< Set the motor direction */ #define RCX_PlayToneVarOp 0x02 /*!< Play a tone using a variable */ #define RCX_PollOp 0x12 /*!< Poll a source/value combination */ #define RCX_SetWatchOp 0x22 /*!< Set the watch source/value */ #define RCX_InputTypeOp 0x32 /*!< Set the input type */ #define RCX_InputModeOp 0x42 /*!< Set the input mode */ #define RCX_SetDatalogOp 0x52 /*!< Set the datalog size */ #define RCX_DatalogOp 0x62 /*!< Datalog the specified source/value*/ #define RCX_SendUARTDataOp 0xc2 /*!< Send data via IR using UART settings */ #define RCX_RemoteOp 0xd2 /*!< Execute simulated remote control buttons */ #define RCX_VLLOp 0xe2 /*!< Send visual light link (VLL) data */ #define RCX_DirectEventOp 0x03 /*!< Fire an event */ #define RCX_OutputPowerOp 0x13 /*!< Set the motor power level */ #define RCX_PlayToneOp 0x23 /*!< Play a tone */ #define RCX_DisplayOp 0x33 /*!< Set LCD display value */ #define RCX_PollMemoryOp 0x63 /*!< Poll a memory location */ #define RCX_SetFeedbackOp 0x83 /*!< Set Scout feedback */ #define RCX_SetEventOp 0x93 /*!< Set an event */ #define RCX_GOutputPowerOp 0xa3 /*!< Set global motor power levels */ #define RCX_LSUpperThreshOp 0xb3 /*!< Set the light sensor upper threshold */ #define RCX_LSLowerThreshOp 0xc3 /*!< Set the light sensor lower threshold */ #define RCX_LSHysteresisOp 0xd3 /*!< Set the light sensor hysteresis */ #define RCX_LSBlinkTimeOp 0xe3 /*!< Set the light sensor blink time */ #define RCX_CalibrateEventOp 0x04 /*!< Calibrate event */ #define RCX_SetVarOp 0x14 /*!< Set function */ #define RCX_SumVarOp 0x24 /*!< Sum function */ #define RCX_SubVarOp 0x34 /*!< Subtract function */ #define RCX_DivVarOp 0x44 /*!< Divide function */ #define RCX_MulVarOp 0x54 /*!< Multiply function */ #define RCX_SgnVarOp 0x64 /*!< Sign function */ #define RCX_AbsVarOp 0x74 /*!< Absolute value function */ #define RCX_AndVarOp 0x84 /*!< AND function */ #define RCX_OrVarOp 0x94 /*!< OR function */ #define RCX_UploadDatalogOp 0xa4 /*!< Upload datalog contents */ #define RCX_SetTimerLimitOp 0xc4 /*!< Set timer limit */ #define RCX_SetCounterOp 0xd4 /*!< Set counter value */ #define RCX_SetSourceValueOp 0x05 /*!< Set a source/value*/ #define RCX_UnlockOp 0x15 /*!< Unlock the brick */ #define RCX_BootModeOp 0x65 /*!< Set into book mode */ #define RCX_UnlockFirmOp 0xa5 /*!< Unlock the firmware */ #define RCX_ScoutRulesOp 0xd5 /*!< Set Scout rules */ #define RCX_ViewSourceValOp 0xe5 /*!< View a source/value */ #define RCX_ScoutOp 0x47 /*!< Scout opcode */ #define RCX_SoundOp 0x57 /*!< Sound opcode */ #define RCX_GOutputModeOp 0x67 /*!< Set global motor mode */ #define RCX_GOutputDirOp 0x77 /*!< Set global motor direction */ #define RCX_LightOp 0x87 /*!< Light opcode */ #define RCX_IncCounterOp 0x97 /*!< Increment a counter */ #define RCX_DecCounterOp 0xa7 /*!< Decrement a counter */ #define RCX_ClearCounterOp 0xb7 /*!< Clear a counter */ #define RCX_SetPriorityOp 0xd7 /*!< Set task priority */ #define RCX_MessageOp 0xf7 /*!< Set message */ /** @} */ // end of RCXOpcodeConstants group /** @} */ // end of RCXAPIConstants group /** @defgroup HTIRLinkPFConstants HiTechnic/mindsensors Power Function/IR Train constants * Constants that are for use with the HiTechnic IRLink or mindsensors nRLink * in Power Function or IR Train mode. * @{ */ /** @defgroup PFCmdConstants Power Function command constants * Constants that are for sending Power Function commands. * @{ */ #define PF_CMD_STOP 0 /*!< Power function command stop */ #define PF_CMD_FLOAT 0 /*!< Power function command float (same as stop) */ #define PF_CMD_FWD 1 /*!< Power function command forward */ #define PF_CMD_REV 2 /*!< Power function command reverse */ #define PF_CMD_BRAKE 3 /*!< Power function command brake */ /** @} */ // end of PFCmdConstants group /** @defgroup PFChannelConstants Power Function channel constants * Constants that are for specifying Power Function channels. * @{ */ #define PF_CHANNEL_1 0 /*!< Power function channel 1 */ #define PF_CHANNEL_2 1 /*!< Power function channel 2 */ #define PF_CHANNEL_3 2 /*!< Power function channel 3 */ #define PF_CHANNEL_4 3 /*!< Power function channel 4 */ /** @} */ // end of PFChannelConstants group /** @defgroup PFModeConstants Power Function mode constants * Constants that are for choosing Power Function modes. * @{ */ #define PF_MODE_TRAIN 0 /*!< Power function mode IR Train */ #define PF_MODE_COMBO_DIRECT 1 /*!< Power function mode combo direct */ #define PF_MODE_SINGLE_PIN_CONT 2 /*!< Power function mode single pin continuous */ #define PF_MODE_SINGLE_PIN_TIME 3 /*!< Power function mode single pin timed */ #define PF_MODE_COMBO_PWM 4 /*!< Power function mode combo pulse width modulation (PWM) */ #define PF_MODE_SINGLE_OUTPUT_PWM 4 /*!< Power function mode single output pulse width modulation (PWM) */ #define PF_MODE_SINGLE_OUTPUT_CST 6 /*!< Power function mode single output clear, set, toggle (CST) */ /** @} */ // end of PFModeConstants group /** @defgroup IRTrainFuncs PF/IR Train function constants * Constants that are for sending PF/IR Train functions. * @{ */ #define TRAIN_FUNC_STOP 0 /*!< PF/IR Train function stop */ #define TRAIN_FUNC_INCR_SPEED 1 /*!< PF/IR Train function increment speed */ #define TRAIN_FUNC_DECR_SPEED 2 /*!< PF/IR Train function decrement speed */ #define TRAIN_FUNC_TOGGLE_LIGHT 4 /*!< PF/IR Train function toggle light */ /** @} */ // end of IRTrainFuncs group /** @defgroup IRTrainChannels IR Train channel constants * Constants that are for specifying IR Train channels. * @{ */ #define TRAIN_CHANNEL_1 0 /*!< IR Train channel 1 */ #define TRAIN_CHANNEL_2 1 /*!< IR Train channel 2 */ #define TRAIN_CHANNEL_3 2 /*!< IR Train channel 3 */ #define TRAIN_CHANNEL_ALL 3 /*!< IR Train channel all */ /** @} */ // end of IRTrainChannels group /** @defgroup PFOutputs Power Function output constants * Constants that are for choosing a Power Function output. * @{ */ #define PF_OUT_A 0 /*!< Power function output A */ #define PF_OUT_B 1 /*!< Power function output B */ /** @} */ // end of PFOutputs group /** @defgroup PFPinConstants Power Function pin constants * Constants that are for choosing a Power Function pin. * @{ */ #define PF_PIN_C1 0 /*!< Power function pin C1 */ #define PF_PIN_C2 1 /*!< Power function pin C2 */ /** @} */ // end of PFOutputs group /** @defgroup PFPinFuncs Power Function single pin function constants * Constants that are for sending Power Function single pin functions. * @{ */ #define PF_FUNC_NOCHANGE 0 /*!< Power function single pin - no change */ #define PF_FUNC_CLEAR 1 /*!< Power function single pin - clear */ #define PF_FUNC_SET 2 /*!< Power function single pin - set */ #define PF_FUNC_TOGGLE 3 /*!< Power function single pin - toggle */ /** @} */ // end of PFCSTFuncs group /** @defgroup PFCSTOptions Power Function CST options constants * Constants that are for specifying Power Function CST options. * @{ */ #define PF_CST_CLEAR1_CLEAR2 0 /*!< Power function CST clear 1 and clear 2 */ #define PF_CST_SET1_CLEAR2 1 /*!< Power function CST set 1 and clear 2*/ #define PF_CST_CLEAR1_SET2 2 /*!< Power function CST clear 1 and set 2 */ #define PF_CST_SET1_SET2 3 /*!< Power function CST set 1 and set 2 */ #define PF_CST_INCREMENT_PWM 4 /*!< Power function CST increment PWM */ #define PF_CST_DECREMENT_PWM 5 /*!< Power function CST decrement PWM */ #define PF_CST_FULL_FWD 6 /*!< Power function CST full forward */ #define PF_CST_FULL_REV 7 /*!< Power function CST full reverse */ #define PF_CST_TOGGLE_DIR 8 /*!< Power function CST toggle direction*/ /** @} */ // end of PFCSTOptions group /** @defgroup PFPWMOptions Power Function PWM option constants * Constants that are for specifying Power Function PWM options. * @{ */ #define PF_PWM_FLOAT 0 /*!< Power function PWM float */ #define PF_PWM_FWD1 1 /*!< Power function PWM foward level 1 */ #define PF_PWM_FWD2 2 /*!< Power function PWM foward level 2 */ #define PF_PWM_FWD3 3 /*!< Power function PWM foward level 3 */ #define PF_PWM_FWD4 4 /*!< Power function PWM foward level 4 */ #define PF_PWM_FWD5 5 /*!< Power function PWM foward level 5 */ #define PF_PWM_FWD6 6 /*!< Power function PWM foward level 6 */ #define PF_PWM_FWD7 7 /*!< Power function PWM foward level 7 */ #define PF_PWM_BRAKE 8 /*!< Power function PWM brake */ #define PF_PWM_REV7 9 /*!< Power function PWM reverse level 7 */ #define PF_PWM_REV6 10 /*!< Power function PWM reverse level 6 */ #define PF_PWM_REV5 11 /*!< Power function PWM reverse level 5 */ #define PF_PWM_REV4 12 /*!< Power function PWM reverse level 4 */ #define PF_PWM_REV3 13 /*!< Power function PWM reverse level 3 */ #define PF_PWM_REV2 14 /*!< Power function PWM reverse level 2 */ #define PF_PWM_REV1 15 /*!< Power function PWM reverse level 1 */ /** @} */ // end of PFPWMOptions group /** @} */ // end of HTIRLinkPFConstants group /** @addtogroup HiTechnicAPI * @{ */ /** @defgroup HiTechnicConstants HiTechnic device constants * Constants that are for use with HiTechnic devices. * @{ */ #define HT_ADDR_IRSEEKER 0x02 /*!< HiTechnic IRSeeker I2C address */ #define HT_ADDR_IRSEEKER2 0x10 /*!< HiTechnic IRSeeker2 I2C address */ #define HT_ADDR_IRRECEIVER 0x02 /*!< HiTechnic IRReceiver I2C address */ #define HT_ADDR_COMPASS 0x02 /*!< HiTechnic Compass I2C address */ #define HT_ADDR_ACCEL 0x02 /*!< HiTechnic Accel I2C address */ #define HT_ADDR_COLOR 0x02 /*!< HiTechnic Color I2C address */ #define HT_ADDR_COLOR2 0x02 /*!< HiTechnic Color2 I2C address */ #define HT_ADDR_IRLINK 0x02 /*!< HiTechnic IRLink I2C address */ #define HT_ADDR_ANGLE 0x02 /*!< HiTechnic Angle I2C address */ /** @defgroup HTIRSeeker2Constants HiTechnic IRSeeker2 constants * Constants that are for use with the HiTechnic IRSeeker2 device. * @{ */ #define HTIR2_MODE_1200 0 /*!< Set IRSeeker2 to 1200 mode */ #define HTIR2_MODE_600 1 /*!< Set IRSeeker2 to 600 mode */ #define HTIR2_REG_MODE 0x41 /*!< IRSeeker2 mode register */ #define HTIR2_REG_DCDIR 0x42 /*!< IRSeeker2 DC direction register */ #define HTIR2_REG_DC01 0x43 /*!< IRSeeker2 DC 01 register */ #define HTIR2_REG_DC02 0x44 /*!< IRSeeker2 DC 02 register */ #define HTIR2_REG_DC03 0x45 /*!< IRSeeker2 DC 03 register */ #define HTIR2_REG_DC04 0x46 /*!< IRSeeker2 DC 04 register */ #define HTIR2_REG_DC05 0x47 /*!< IRSeeker2 DC 05 register */ #define HTIR2_REG_DCAVG 0x48 /*!< IRSeeker2 DC average register */ #define HTIR2_REG_ACDIR 0x49 /*!< IRSeeker2 AC direction register */ #define HTIR2_REG_AC01 0x4A /*!< IRSeeker2 AC 01 register */ #define HTIR2_REG_AC02 0x4B /*!< IRSeeker2 AC 02 register */ #define HTIR2_REG_AC03 0x4C /*!< IRSeeker2 AC 03 register */ #define HTIR2_REG_AC04 0x4D /*!< IRSeeker2 AC 04 register */ #define HTIR2_REG_AC05 0x4E /*!< IRSeeker2 AC 05 register */ /** @} */ // end of HTIRSeeker2Constants group /** @defgroup HTIRReceiverConstants HiTechnic IRReceiver constants * Constants that are for use with the HiTechnic IRReceiver device. * @{ */ #define HT_CH1_A 0 /*!< Use IRReceiver channel 1 output A */ #define HT_CH1_B 1 /*!< Use IRReceiver channel 1 output B */ #define HT_CH2_A 2 /*!< Use IRReceiver channel 2 output A */ #define HT_CH2_B 3 /*!< Use IRReceiver channel 2 output B */ #define HT_CH3_A 4 /*!< Use IRReceiver channel 3 output A */ #define HT_CH3_B 5 /*!< Use IRReceiver channel 3 output B */ #define HT_CH4_A 6 /*!< Use IRReceiver channel 4 output A */ #define HT_CH4_B 7 /*!< Use IRReceiver channel 4 output B */ /** @} */ // end of HTIRSeeker2Constants group /** @defgroup HTColor2Constants HiTechnic Color2 constants * Constants that are for use with the HiTechnic Color2 device. * @{ */ #define HT_CMD_COLOR2_ACTIVE 0x00 /*!< Set the Color2 sensor to active mode */ #define HT_CMD_COLOR2_PASSIVE 0x01 /*!< Set the Color2 sensor to passive mode */ #define HT_CMD_COLOR2_RAW 0x03 /*!< Set the Color2 sensor to raw mode */ #define HT_CMD_COLOR2_50HZ 0x35 /*!< Set the Color2 sensor to 50Hz mode */ #define HT_CMD_COLOR2_60HZ 0x36 /*!< Set the Color2 sensor to 60Hz mode */ #define HT_CMD_COLOR2_BLCAL 0x42 /*!< Set the Color2 sensor to black level calibration mode */ #define HT_CMD_COLOR2_WBCAL 0x43 /*!< Set the Color2 sensor to white level calibration mode */ #define HT_CMD_COLOR2_FAR 0x46 /*!< Set the Color2 sensor to far mode */ #define HT_CMD_COLOR2_LED_HI 0x48 /*!< Set the Color2 sensor to LED high mode */ #define HT_CMD_COLOR2_LED_LOW 0x4C /*!< Set the Color2 sensor to LED low mode */ #define HT_CMD_COLOR2_NEAR 0x4E /*!< Set the Color2 sensor to near mode */ /** @} */ // end of HTColor2Constants group /** @defgroup HTAngleConstants HiTechnic Angle sensor constants * Constants that are for use with the HiTechnic Angle sensor device. * @{ */ #define HTANGLE_MODE_NORMAL 0x00 /*!< Normal angle measurement mode */ #define HTANGLE_MODE_CALIBRATE 0x43 /*!< Resets 0 degree position to current shaft angle */ #define HTANGLE_MODE_RESET 0x52 /*!< Resets the accumulated angle */ #define HTANGLE_REG_MODE 0x41 /*!< Angle mode register */ #define HTANGLE_REG_DCDIR 0x42 /*!< Angle current angle (2 degree increments) register */ #define HTANGLE_REG_DC01 0x43 /*!< Angle current angle (1 degree adder) register */ #define HTANGLE_REG_DC02 0x44 /*!< Angle 32 bit accumulated angle, high byte register */ #define HTANGLE_REG_DC03 0x45 /*!< Angle 32 bit accumulated angle, mid byte register */ #define HTANGLE_REG_DC04 0x46 /*!< Angle 32 bit accumulated angle, mid byte register */ #define HTANGLE_REG_DC05 0x47 /*!< Angle 32 bit accumulated angle, low byte register */ #define HTANGLE_REG_DCAVG 0x48 /*!< Angle 16 bit revolutions per minute, high byte register */ #define HTANGLE_REG_ACDIR 0x49 /*!< Angle 16 bit revolutions per minute, low byte register */ /** @} */ // end of HTAngleConstants group /** @} */ // end of HiTechnicConstants group /** @} */ // end of HiTechnicAPI group /** @addtogroup MindSensorsAPI * @{ */ /** @defgroup MindSensorsConstants MindSensors device constants * Constants that are for use with MindSensors devices. * @{ */ // MindSensors constants #define MS_CMD_ENERGIZED 0x45 /*!< Energize the MindSensors device */ #define MS_CMD_DEENERGIZED 0x44 /*!< De-energize the MindSensors device */ #define MS_CMD_ADPA_ON 0x4E /*!< Turn MindSensors ADPA mode on */ #define MS_CMD_ADPA_OFF 0x4F /*!< Turn MindSensors ADPA mode off */ #define MS_ADDR_RTCLOCK 0xD0 /*!< MindSensors RTClock I2C address */ #define MS_ADDR_DISTNX 0x02 /*!< MindSensors DIST-Nx I2C address */ #define MS_ADDR_NRLINK 0x02 /*!< MindSensors NRLink I2C address */ #define MS_ADDR_ACCLNX 0x02 /*!< MindSensors ACCL-Nx I2C address */ #define MS_ADDR_CMPSNX 0x02 /*!< MindSensors CMPS-Nx I2C address */ #define MS_ADDR_PSPNX 0x02 /*!< MindSensors PSP-Nx I2C address */ #define MS_ADDR_LINELDR 0x02 /*!< MindSensors LineLdr I2C address */ #define MS_ADDR_NXTCAM 0x02 /*!< MindSensors NXTCam I2C address */ #define MS_ADDR_NXTHID 0x04 /*!< MindSensors NXTHID I2C address */ #define MS_ADDR_NXTSERVO 0xB0 /*!< MindSensors NXTServo I2C address */ #define MS_ADDR_NXTSERVO_EM 0x40 /*!< MindSensors NXTServo in edit macro mode I2C address */ #define MS_ADDR_PFMATE 0x48 /*!< MindSensors PFMate I2C address */ #define MS_ADDR_MTRMUX 0xB4 /*!< MindSensors MTRMux I2C address */ #define MS_ADDR_NXTMMX 0x06 /*!< MindSensors NXTMMX I2C address */ #define MS_ADDR_IVSENS 0x12 /*!< MindSensors IVSens (NXTPowerMeter) I2C address */ #define MS_ADDR_RXMUX 0x7E /*!< MindSensors RXMux I2C address */ /** @defgroup MSDistNX MindSensors DIST-Nx constants * Constants that are for use with the MindSensors DIST-Nx device. * @{ */ // DIST-Nx Commands #define DIST_CMD_GP2D12 0x31 /*!< Set the DIST-Nx to GP2D12 mode */ #define DIST_CMD_GP2D120 0x32 /*!< Set the DIST-Nx to GP2D120 mode */ #define DIST_CMD_GP2YA21 0x33 /*!< Set the DIST-Nx to GP2YA21 mode */ #define DIST_CMD_GP2YA02 0x34 /*!< Set the DIST-Nx to GP2YA02 mode */ #define DIST_CMD_CUSTOM 0x35 /*!< Set the DIST-Nx to a custom mode */ // DIST-Nx Registers #define DIST_REG_DIST 0x42 /*!< The DIST-Nx distance register */ #define DIST_REG_VOLT 0x44 /*!< The DIST-Nx voltage register */ #define DIST_REG_MODULE_TYPE 0x50 /*!< The DIST-Nx module type register */ #define DIST_REG_NUM_POINTS 0x51 /*!< The DIST-Nx number of data points in Custom curve register */ #define DIST_REG_DIST_MIN 0x52 /*!< The DIST-Nx minimum distance register */ #define DIST_REG_DIST_MAX 0x54 /*!< The DIST-Nx maximum distance register */ #define DIST_REG_VOLT1 0x56 /*!< The DIST-Nx voltage 1 register */ #define DIST_REG_DIST1 0x58 /*!< The DIST-Nx distance 1 register */ /** @} */ // end of MSDistNX group /** @defgroup MSPSPNX MindSensors PSP-Nx constants * Constants that are for use with the MindSensors PSP-Nx device. * @{ */ // PSP-Nx commands #define PSP_CMD_DIGITAL 0x41 /*!< Set the PSP-Nx to digital mode */ #define PSP_CMD_ANALOG 0x73 /*!< Set the PSP-Nx to analog mode */ // PSP-Nx registers #define PSP_REG_BTNSET1 0x42 /*!< The PSP-Nx button set 1 register */ #define PSP_REG_BTNSET2 0x43 /*!< The PSP-Nx button set 2 register */ #define PSP_REG_XLEFT 0x44 /*!< The PSP-Nx X left register */ #define PSP_REG_YLEFT 0x45 /*!< The PSP-Nx Y left register */ #define PSP_REG_XRIGHT 0x46 /*!< The PSP-Nx X right register */ #define PSP_REG_YRIGHT 0x47 /*!< The PSP-Nx Y right register */ /** @defgroup MSPSPNXBtnSet1 MindSensors PSP-Nx button set 1 constants * Constants that are for interpretting MindSensors PSP-Nx button set 1 values. * @{ */ #define PSP_BTNSET1_LEFT 0x01 /*!< The PSP-Nx button set 1 left arrow */ #define PSP_BTNSET1_DOWN 0x02 /*!< The PSP-Nx button set 1 down arrow */ #define PSP_BTNSET1_RIGHT 0x04 /*!< The PSP-Nx button set 1 right arrow */ #define PSP_BTNSET1_UP 0x08 /*!< The PSP-Nx button set 1 up arrow */ #define PSP_BTNSET1_R3 0x20 /*!< The PSP-Nx button set 1 R3 */ #define PSP_BTNSET1_L3 0x40 /*!< The PSP-Nx button set 1 L3 */ /** @} */ // end of MSPSPNXBtnSet1 group /** @defgroup MSPSPNXBtnSet2 MindSensors PSP-Nx button set 2 constants * Constants that are for interpretting MindSensors PSP-Nx button set 2 values. * @{ */ #define PSP_BTNSET2_SQUARE 0x01 /*!< The PSP-Nx button set 2 square */ #define PSP_BTNSET2_CROSS 0x02 /*!< The PSP-Nx button set 2 cross */ #define PSP_BTNSET2_CIRCLE 0x04 /*!< The PSP-Nx button set 2 circle */ #define PSP_BTNSET2_TRIANGLE 0x08 /*!< The PSP-Nx button set 2 triangle */ #define PSP_BTNSET2_R1 0x10 /*!< The PSP-Nx button set 2 R1 */ #define PSP_BTNSET2_L1 0x20 /*!< The PSP-Nx button set 2 L1 */ #define PSP_BTNSET2_R2 0x40 /*!< The PSP-Nx button set 2 R2 */ #define PSP_BTNSET2_L2 0x80 /*!< The PSP-Nx button set 2 L2 */ /** @} */ // end of MSPSPNXBtnSet2 group /** @} */ // end of MSPSPNX group /** @defgroup MSNRLink MindSensors nRLink constants * Constants that are for use with the MindSensors nRLink device. * @{ */ // NRLink commands #define NRLINK_CMD_2400 0x44 /*!< Set NRLink to 2400 baud */ #define NRLINK_CMD_FLUSH 0x46 /*!< Flush the NRLink */ #define NRLINK_CMD_4800 0x48 /*!< Set NRLink to 4800 baud */ #define NRLINK_CMD_IR_LONG 0x4C /*!< Set the NRLink to long range IR */ #define NRLINK_CMD_IR_SHORT 0x53 /*!< Set the NRLink to short range IR */ #define NRLINK_CMD_RUN_MACRO 0x52 /*!< Run an NRLink macro */ #define NRLINK_CMD_TX_RAW 0x55 /*!< Set the NRLink to transmit raw bytes */ #define NRLINK_CMD_SET_RCX 0x58 /*!< Set the NRLink to RCX mode */ #define NRLINK_CMD_SET_TRAIN 0x54 /*!< Set the NRLink to IR Train mode */ #define NRLINK_CMD_SET_PF 0x50 /*!< Set the NRLink to Power Function mode */ // NRLink registers #define NRLINK_REG_BYTES 0x40 /*!< The NRLink bytes register */ #define NRLINK_REG_DATA 0x42 /*!< The NRLink data register */ #define NRLINK_REG_EEPROM 0x50 /*!< The NRLink eeprom register */ /** @} */ // end of MSNRLink group /** @defgroup MSACCLNx MindSensors ACCL-Nx constants * Constants that are for use with the MindSensors ACCL-Nx device. * @{ */ // ACCL-Nx commands #define ACCL_CMD_X_CAL 0x58 /*!< Acquire X-axis calibration point */ #define ACCL_CMD_Y_CAL 0x59 /*!< Acquire Y-axis calibration point */ #define ACCL_CMD_Z_CAL 0x5a /*!< Acquire Z-axis calibration point */ #define ACCL_CMD_X_CAL_END 0x78 /*!< Acquire X-axis calibration point and end calibration */ #define ACCL_CMD_Y_CAL_END 0x79 /*!< Acquire Y-axis calibration point and end calibration */ #define ACCL_CMD_Z_CAL_END 0x7a /*!< Acquire Z-axis calibration point and end calibration */ #define ACCL_CMD_RESET_CAL 0x52 /*!< Reset to factory calibration */ // ACCL-Nx registers #define ACCL_REG_SENS_LVL 0x19 /*!< The current sensitivity */ #define ACCL_REG_X_TILT 0x42 /*!< The X-axis tilt data */ #define ACCL_REG_Y_TILT 0x43 /*!< The Y-axis tilt data */ #define ACCL_REG_Z_TILT 0x44 /*!< The Z-axis tilt data */ #define ACCL_REG_X_ACCEL 0x45 /*!< The X-axis acceleration data */ #define ACCL_REG_Y_ACCEL 0x47 /*!< The Y-axis acceleration data */ #define ACCL_REG_Z_ACCEL 0x49 /*!< The Z-axis acceleration data */ #define ACCL_REG_X_OFFSET 0x4b /*!< The X-axis offset */ #define ACCL_REG_X_RANGE 0x4d /*!< The X-axis range */ #define ACCL_REG_Y_OFFSET 0x4f /*!< The Y-axis offset */ #define ACCL_REG_Y_RANGE 0x51 /*!< The Y-axis range */ #define ACCL_REG_Z_OFFSET 0x53 /*!< The Z-axis offset */ #define ACCL_REG_Z_RANGE 0x55 /*!< The Z-axis range */ /** @defgroup MSACCLNxSLevel MindSensors ACCL-Nx sensitivity level constants * Constants that are for setting the MindSensors ACCL-Nx sensitivity level. * @{ */ #define ACCL_SENSITIVITY_LEVEL_1 0x31 /*!< The ACCL-Nx sensitivity level 1 */ #define ACCL_SENSITIVITY_LEVEL_2 0x32 /*!< The ACCL-Nx sensitivity level 2 */ #define ACCL_SENSITIVITY_LEVEL_3 0x33 /*!< The ACCL-Nx sensitivity level 3 */ #define ACCL_SENSITIVITY_LEVEL_4 0x34 /*!< The ACCL-Nx sensitivity level 4 */ /** @} */ // end of MSACCLNxSLevel group /** @} */ // end of MSACCLNx group /** @defgroup PFMateConstants MindSensors PFMate constants * Constants that are for use with the MindSensors PFMate device. * @{ */ #define PFMATE_REG_CMD 0x41 /*!< PFMate command */ #define PFMATE_REG_CHANNEL 0x42 /*!< PF channel? 1, 2, 3, or 4 */ #define PFMATE_REG_MOTORS 0x43 /*!< PF motors? (0 = both, 1 = A, 2 = B) */ #define PFMATE_REG_A_CMD 0x44 /*!< PF command for motor A? (PF_CMD_FLOAT, PF_CMD_FWD, PF_CMD_REV, PF_CMD_BRAKE) */ #define PFMATE_REG_A_SPEED 0x45 /*!< PF speed for motor A? (0-7) */ #define PFMATE_REG_B_CMD 0x46 /*!< PF command for motor B? (PF_CMD_FLOAT, PF_CMD_FWD, PF_CMD_REV, PF_CMD_BRAKE) */ #define PFMATE_REG_B_SPEED 0x47 /*!< PF speed for motor B? (0-7) */ #define PFMATE_CMD_GO 0x47 /*!< Send IR signal to IR receiver */ #define PFMATE_CMD_RAW 0x52 /*!< Send raw IR signal to IR receiver */ /** @defgroup PFMateMotorConstants PFMate motor constants * Constants that are for specifying PFMate motors. * @{ */ #define PFMATE_MOTORS_BOTH 0x00 /*!< Control both motors */ #define PFMATE_MOTORS_A 0x01 /*!< Control only motor A */ #define PFMATE_MOTORS_B 0x02 /*!< Control only motor B */ /** @} */ // end of PFMateMotorConstants group /** @defgroup PFMateChannelConstants PFMate channel constants * Constants that are for specifying PFMate channels. * @{ */ #define PFMATE_CHANNEL_1 1 /*!< Power function channel 1 */ #define PFMATE_CHANNEL_2 2 /*!< Power function channel 2 */ #define PFMATE_CHANNEL_3 3 /*!< Power function channel 3 */ #define PFMATE_CHANNEL_4 4 /*!< Power function channel 4 */ /** @} */ // end of PFMateChannelConstants group /** @} */ // end of PFMateConstants group /** @defgroup NXTServoConstants MindSensors NXTServo constants * Constants that are for use with the MindSensors NXTServo device. * @{ */ /** @defgroup NXTServoRegisters MindSensors NXTServo registers * NXTServo device register constants. * @{ */ #define NXTSERVO_REG_VOLTAGE 0x41 /*!< Battery voltage register. (read only) */ #define NXTSERVO_REG_CMD 0x41 /*!< NXTServo command register. See \ref NXTServoCommands group. (write only) */ // position registers (2 bytes little endian) #define NXTSERVO_REG_S1_POS 0x42 /*!< NXTServo servo 1 position register. */ #define NXTSERVO_REG_S2_POS 0x44 /*!< NXTServo servo 2 position register. */ #define NXTSERVO_REG_S3_POS 0x46 /*!< NXTServo servo 3 position register. */ #define NXTSERVO_REG_S4_POS 0x48 /*!< NXTServo servo 4 position register. */ #define NXTSERVO_REG_S5_POS 0x4A /*!< NXTServo servo 5 position register. */ #define NXTSERVO_REG_S6_POS 0x4C /*!< NXTServo servo 6 position register. */ #define NXTSERVO_REG_S7_POS 0x4E /*!< NXTServo servo 7 position register. */ #define NXTSERVO_REG_S8_POS 0x50 /*!< NXTServo servo 8 position register. */ // speed registers #define NXTSERVO_REG_S1_SPEED 0x52 /*!< NXTServo servo 1 speed register. */ #define NXTSERVO_REG_S2_SPEED 0x53 /*!< NXTServo servo 2 speed register. */ #define NXTSERVO_REG_S3_SPEED 0x54 /*!< NXTServo servo 3 speed register. */ #define NXTSERVO_REG_S4_SPEED 0x55 /*!< NXTServo servo 4 speed register. */ #define NXTSERVO_REG_S5_SPEED 0x56 /*!< NXTServo servo 5 speed register. */ #define NXTSERVO_REG_S6_SPEED 0x57 /*!< NXTServo servo 6 speed register. */ #define NXTSERVO_REG_S7_SPEED 0x58 /*!< NXTServo servo 7 speed register. */ #define NXTSERVO_REG_S8_SPEED 0x59 /*!< NXTServo servo 8 speed register. */ // quick position registers #define NXTSERVO_REG_S1_QPOS 0x5A /*!< NXTServo servo 1 quick position register. (write only) */ #define NXTSERVO_REG_S2_QPOS 0x5B /*!< NXTServo servo 2 quick position register. (write only) */ #define NXTSERVO_REG_S3_QPOS 0x5C /*!< NXTServo servo 3 quick position register. (write only) */ #define NXTSERVO_REG_S4_QPOS 0x5D /*!< NXTServo servo 4 quick position register. (write only) */ #define NXTSERVO_REG_S5_QPOS 0x5E /*!< NXTServo servo 5 quick position register. (write only) */ #define NXTSERVO_REG_S6_QPOS 0x5F /*!< NXTServo servo 6 quick position register. (write only) */ #define NXTSERVO_REG_S7_QPOS 0x60 /*!< NXTServo servo 7 quick position register. (write only) */ #define NXTSERVO_REG_S8_QPOS 0x61 /*!< NXTServo servo 8 quick position register. (write only) */ #define NXTSERVO_EM_REG_CMD 0x00 /*!< NXTServo in macro edit mode command register. */ #define NXTSERVO_EM_REG_EEPROM_START 0x21 /*!< NXTServo in macro edit mode EEPROM start register. */ #define NXTSERVO_EM_REG_EEPROM_END 0xFF /*!< NXTServo in macro edit mode EEPROM end register. */ /** @} */ // end of NXTServoRegisters group /** @defgroup NXTServoPos MindSensors NXTServo position constants * NXTServo device position constants. * @{ */ #define NXTSERVO_POS_CENTER 1500 /*!< Center position for 1500us servos. */ #define NXTSERVO_POS_MIN 500 /*!< Minimum position for 1500us servos. */ #define NXTSERVO_POS_MAX 2500 /*!< Maximum position for 1500us servos. */ /** @} */ // end of NXTServoPos group /** @defgroup NXTServoQPos MindSensors NXTServo quick position constants * NXTServo device quick position constants. * @{ */ #define NXTSERVO_QPOS_CENTER 150 /*!< Center quick position for 1500us servos. */ #define NXTSERVO_QPOS_MIN 50 /*!< Minimum quick position for 1500us servos. */ #define NXTSERVO_QPOS_MAX 250 /*!< Maximum quick position for 1500us servos. */ /** @} */ // end of NXTServoQPos group /** @defgroup NXTServoNumbers MindSensors NXTServo servo numbers * NXTServo device servo number constants. * @{ */ #define NXTSERVO_SERVO_1 0 /*!< NXTServo server number 1. */ #define NXTSERVO_SERVO_2 1 /*!< NXTServo server number 2. */ #define NXTSERVO_SERVO_3 2 /*!< NXTServo server number 3. */ #define NXTSERVO_SERVO_4 3 /*!< NXTServo server number 4. */ #define NXTSERVO_SERVO_5 4 /*!< NXTServo server number 5. */ #define NXTSERVO_SERVO_6 5 /*!< NXTServo server number 6. */ #define NXTSERVO_SERVO_7 6 /*!< NXTServo server number 7. */ #define NXTSERVO_SERVO_8 7 /*!< NXTServo server number 8. */ /** @} */ // end of NXTServoNumbers group /** @defgroup NXTServoCommands MindSensors NXTServo commands * NXTServo device command constants. These are written to the command register * to control the device. * @{ */ #define NXTSERVO_CMD_INIT 0x49 /*!< Store the initial speed and position properties of the servo motor 'n'. Current speed and position values of the nth servo is read from the servo speed register and servo position register and written to permanent memory. */ #define NXTSERVO_CMD_RESET 0x53 /*!< Reset servo properties to factory default. Initial Position of servos to 1500, and speed to 0. */ #define NXTSERVO_CMD_HALT 0x48 /*!< Halt Macro. This command re-initializes the macro environment. */ #define NXTSERVO_CMD_RESUME 0x52 /*!< Resume macro Execution. This command resumes macro where it was paused last, using the same environment. */ #define NXTSERVO_CMD_GOTO 0x47 /*!< Goto EEPROM position x. This command re-initializes the macro environment. */ #define NXTSERVO_CMD_PAUSE 0x50 /*!< Pause Macro. This command will pause the macro, and save the environment for subsequent resumption. */ #define NXTSERVO_CMD_EDIT1 0x45 /*!< Edit Macro (part 1 of 2 character command sequence) */ #define NXTSERVO_CMD_EDIT2 0x4D /*!< Edit Macro (part 2 of 2 character command sequence) */ #define NXTSERVO_EM_CMD_QUIT 0x51 /*!< Exit edit macro mode */ /** @} */ // end of NXTServoCommands group /** @} */ // end of NXTServoConstants group /** @defgroup NXTHIDConstants MindSensors NXTHID constants * Constants that are for use with the MindSensors NXTHID device. * @{ */ /** @defgroup NXTHIDRegisters MindSensors NXTHID registers * NXTHID device register constants. * @{ */ #define NXTHID_REG_CMD 0x41 /*!< NXTHID command register. See \ref NXTHIDCommands group. */ #define NXTHID_REG_MODIFIER 0x42 /*!< NXTHID modifier register. See \ref NXTHIDModifiers group. */ #define NXTHID_REG_DATA 0x43 /*!< NXTHID data register. */ /** @} */ // end of NXTHIDRegisters group /** @defgroup NXTHIDModifiers MindSensors NXTHID modifier keys * NXTHID device modifier key constants. * @{ */ #define NXTHID_MOD_NONE 0x00 /*!< NXTHID no modifier. */ #define NXTHID_MOD_LEFT_CTRL 0x01 /*!< NXTHID left control modifier. */ #define NXTHID_MOD_LEFT_SHIFT 0x02 /*!< NXTHID left shift modifier. */ #define NXTHID_MOD_LEFT_ALT 0x04 /*!< NXTHID left alt modifier. */ #define NXTHID_MOD_LEFT_GUI 0x08 /*!< NXTHID left gui modifier. */ #define NXTHID_MOD_RIGHT_CTRL 0x10 /*!< NXTHID right control modifier. */ #define NXTHID_MOD_RIGHT_SHIFT 0x20 /*!< NXTHID right shift modifier. */ #define NXTHID_MOD_RIGHT_ALT 0x40 /*!< NXTHID right alt modifier. */ #define NXTHID_MOD_RIGHT_GUI 0x80 /*!< NXTHID right gui modifier. */ /** @} */ // end of NXTHIDModifiers group /** @defgroup NXTHIDCommands MindSensors NXTHID commands * NXTHID device command constants. These are written to the command register * to control the device. * @{ */ #define NXTHID_CMD_ASCII 0x41 /*!< Use ASCII data mode. In ASCII mode no non-printable characters can be sent. */ #define NXTHID_CMD_DIRECT 0x44 /*!< Use direct data mode In direct mode any character can be sent. */ #define NXTHID_CMD_TRANSMIT 0x54 /*!< Transmit data to the host computer. */ /** @} */ // end of NXTHIDCommands group /** @} */ // end of NXTHIDConstants group /** @defgroup NXTPowerMeterConstants MindSensors NXTPowerMeter constants * Constants that are for use with the MindSensors NXTPowerMeter device. * @{ */ /** @defgroup NXTPowerMeterRegisters MindSensors NXTPowerMeter registers * NXTPowerMeter device register constants. * @{ */ #define NXTPM_REG_CMD 0x41 /*!< NXTPowerMeter command register. See the \ref NXTPowerMeterCommands group. */ #define NXTPM_REG_CURRENT 0x42 /*!< NXTPowerMeter present current in mA register. (2 bytes) */ #define NXTPM_REG_VOLTAGE 0x44 /*!< NXTPowerMeter present voltage in mV register. (2 bytes) */ #define NXTPM_REG_CAPACITY 0x46 /*!< NXTPowerMeter capacity used since last reset register. (2 bytes) */ #define NXTPM_REG_POWER 0x48 /*!< NXTPowerMeter present power register. (2 bytes) */ #define NXTPM_REG_TOTALPOWER 0x4A /*!< NXTPowerMeter total power consumed since last reset register. (4 bytes) */ #define NXTPM_REG_MAXCURRENT 0x4E /*!< NXTPowerMeter max current register. (2 bytes) */ #define NXTPM_REG_MINCURRENT 0x50 /*!< NXTPowerMeter min current register. (2 bytes) */ #define NXTPM_REG_MAXVOLTAGE 0x52 /*!< NXTPowerMeter max voltage register. (2 bytes) */ #define NXTPM_REG_MINVOLTAGE 0x54 /*!< NXTPowerMeter min voltage register. (2 bytes) */ #define NXTPM_REG_TIME 0x56 /*!< NXTPowerMeter time register. (4 bytes) */ #define NXTPM_REG_USERGAIN 0x5A /*!< NXTPowerMeter user gain register. Not yet implemented. (4 bytes) */ #define NXTPM_REG_GAIN 0x5E /*!< NXTPowerMeter gain register. (1 byte) */ #define NXTPM_REG_ERRORCOUNT 0x5F /*!< NXTPowerMeter error count register. (2 bytes) */ /** @} */ // end of NXTPowerMeterRegisters group /** @defgroup NXTPowerMeterCommands MindSensors NXTPowerMeter commands * NXTPowerMeter device command constants. These are written to the command register * to control the device. * @{ */ #define NXTPM_CMD_RESET 0x52 /*!< Reset counters. */ /** @} */ // end of NXTPowerMeterCommands group /** @} */ // end of NXTPowerMeterConstants group /** @defgroup NXTSumoEyesConstants MindSensors NXTSumoEyes constants * Constants that are for use with the MindSensors NXTSumoEyes device. * @{ */ #define NXTSE_ZONE_NONE 0 /*!< Obstacle zone none. */ #define NXTSE_ZONE_FRONT 1 /*!< Obstacle zone front. */ #define NXTSE_ZONE_LEFT 2 /*!< Obstacle zone left. */ #define NXTSE_ZONE_RIGHT 3 /*!< Obstacle zone right. */ /** @} */ // end of NXTSumoEyesConstants group /** @defgroup NXTLineLeaderConstants MindSensors NXTLineLeader constants * Constants that are for use with the MindSensors NXTLineLeader device. * @{ */ /** @defgroup NXTLineLeaderRegisters MindSensors NXTLineLeader registers * NXTLineLeader device register constants. * @{ */ #define NXTLL_REG_CMD 0x41 /*!< NXTLineLeader command register. See the \ref NXTLineLeaderCommands group. */ #define NXTLL_REG_STEERING 0x42 /*!< NXTLineLeader steering register. */ #define NXTLL_REG_AVERAGE 0x43 /*!< NXTLineLeader average result register. */ #define NXTLL_REG_RESULT 0x44 /*!< NXTLineLeader result register (sensor bit values). */ #define NXTLL_REG_SETPOINT 0x45 /*!< NXTLineLeader user settable average (setpoint) register. Default = 45. */ #define NXTLL_REG_KP_VALUE 0x46 /*!< NXTLineLeader Kp value register. Default = 25. */ #define NXTLL_REG_KI_VALUE 0x47 /*!< NXTLineLeader Ki value register. Default = 0. */ #define NXTLL_REG_KD_VALUE 0x48 /*!< NXTLineLeader Kd value register. Default = 8. */ #define NXTLL_REG_CALIBRATED 0x49 /*!< NXTLineLeader calibrated sensor reading registers. 8 bytes. */ #define NXTLL_REG_WHITELIMITS 0x51 /*!< NXTLineLeader white limit registers. 8 bytes. */ #define NXTLL_REG_BLACKLIMITS 0x59 /*!< NXTLineLeader black limit registers. 8 bytes. */ #define NXTLL_REG_KP_FACTOR 0x61 /*!< NXTLineLeader Kp factor register. Default = 32. */ #define NXTLL_REG_KI_FACTOR 0x62 /*!< NXTLineLeader Ki factor register. Default = 32. */ #define NXTLL_REG_KD_FACTOR 0x63 /*!< NXTLineLeader Kd factor register. Default = 32. */ #define NXTLL_REG_WHITEDATA 0x64 /*!< NXTLineLeader white calibration data registers. 8 bytes. */ #define NXTLL_REG_BLACKDATA 0x6C /*!< NXTLineLeader black calibration data registers. 8 bytes. */ #define NXTLL_REG_RAWVOLTAGE 0x74 /*!< NXTLineLeader uncalibrated sensor voltage registers. 16 bytes. */ /** @} */ // end of NXTLineLeaderRegisters group /** @defgroup NXTLineLeaderCommands MindSensors NXTLineLeader commands * NXTLineLeader device command constants. These are written to the command register * to control the device. * @{ */ #define NXTLL_CMD_USA 0x41 /*!< USA power frequency. (60hz) */ #define NXTLL_CMD_BLACK 0x42 /*!< Black calibration. */ #define NXTLL_CMD_POWERDOWN 0x44 /*!< Power down the device. */ #define NXTLL_CMD_EUROPEAN 0x45 /*!< European power frequency. (50hz) */ #define NXTLL_CMD_INVERT 0x49 /*!< Invert color. */ #define NXTLL_CMD_POWERUP 0x50 /*!< Power up the device. */ #define NXTLL_CMD_RESET 0x52 /*!< Reset inversion. */ #define NXTLL_CMD_SNAPSHOT 0x53 /*!< Setpoint based on snapshot (automatically sets invert if needed). */ #define NXTLL_CMD_UNIVERSAL 0x55 /*!< Universal power frequency. The sensor auto adjusts for any frequency. This is the default mode. */ #define NXTLL_CMD_WHITE 0x57 /*!< White balance calibration. */ /** @} */ // end of NXTLineLeaderCommands group /** @} */ // end of NXTLineLeaderConstants group /** @} */ // end of MindSensorsConstants group /** @} */ // end of MindSensorsAPI group /** @addtogroup CodatexAPI * @{ */ /** @defgroup CodatexConstants Codatex device constants * Constants that are for use with Codatex devices. * @{ */ /** @defgroup CTRFIDConstants Codatex RFID sensor constants * Constants that are for use with the Codatex RFID sensor device. * @{ */ /** @defgroup CTRFIDModeConstants Codatex RFID sensor modes * Constants that are for configuring the Codatex RFID sensor mode. * @{ */ #define RFID_MODE_STOP 0 /*!< Stop the RFID device */ #define RFID_MODE_SINGLE 1 /*!< Configure the RFID device for a single reading */ #define RFID_MODE_CONTINUOUS 2 /*!< Configure the RFID device for continuous reading */ /** @} */ // end of CTRFIDModeConstants group #define CT_ADDR_RFID 0x04 /*!< RFID I2C address */ #define CT_REG_STATUS 0x32 /*!< RFID status register */ #define CT_REG_MODE 0x41 /*!< RFID mode register */ #define CT_REG_DATA 0x42 /*!< RFID data register */ /** @} */ // end of CTRFIDConstants group /** @} */ // end of CodatexConstants group /** @} */ // end of CodatexAPI group /** @} */ // end of ThirdPartyDevices group /** @addtogroup RICMacros * @{ */ /** * Output an RIC ImgPoint structure * \param _X The X coordinate. * \param _Y The Y coordinate. */ #define RICImgPoint(_X, _Y) (_X)&0xFF, (_X)>>8, (_Y)&0xFF, (_Y)>>8 /** * Output an RIC ImgRect structure * \param _Pt An ImgPoint. See \ref RICImgPoint. * \param _W The rectangle width. * \param _H The rectangle height. */ #define RICImgRect(_Pt, _W, _H) _Pt, (_W)&0xFF, (_W)>>8, (_H)&0xFF, (_H)>>8 /** * Output an RIC Description opcode * \param _Options RIC options. * \param _Width The total RIC width. * \param _Height The total RIC height. */ #define RICOpDescription(_Options, _Width, _Height) 8, 0, 0, 0, (_Options)&0xFF, (_Options)>>8, (_Width)&0xFF, (_Width)>>8, (_Height)&0xFF, (_Height)>>8 /** * Output an RIC CopyBits opcode * \param _CopyOptions CopyBits copy options. See \ref DisplayDrawOptionConstants. * \param _DataAddr The address of the sprite from which to copy data. * \param _SrcRect The rectangular portion of the sprite to copy. See \ref RICImgRect. * \param _DstPoint The LCD coordinate to which to copy the data. See \ref RICImgPoint. */ #define RICOpCopyBits(_CopyOptions, _DataAddr, _SrcRect, _DstPoint) 18, 0, 3, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, (_DataAddr)&0xFF, (_DataAddr)>>8, _SrcRect, _DstPoint /** * Output an RIC Pixel opcode * \param _CopyOptions Pixel copy options. See \ref DisplayDrawOptionConstants. * \param _Point The pixel coordinate. See \ref RICImgPoint. * \param _Value The pixel value (unused). */ #define RICOpPixel(_CopyOptions, _Point, _Value) 10, 0, 4, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point, (_Value)&0xFF, (_Value)>>8 /** * Output an RIC Line opcode * \param _CopyOptions Line copy options. See \ref DisplayDrawOptionConstants. * \param _Point1 The starting point of the line. See \ref RICImgPoint. * \param _Point2 The ending point of the line. See \ref RICImgPoint. */ #define RICOpLine(_CopyOptions, _Point1, _Point2) 12, 0, 5, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point1, _Point2 /** * Output an RIC Rect opcode * \param _CopyOptions Rect copy options. See \ref DisplayDrawOptionConstants. * \param _Point The rectangle's top left corner. See \ref RICImgPoint. * \param _Width The rectangle's width. * \param _Height The rectangle's height. */ #define RICOpRect(_CopyOptions, _Point, _Width, _Height) 12, 0, 6, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point, (_Width)&0xFF, (_Width)>>8, (_Height)&0xFF, (_Height)>>8 /** * Output an RIC Circle opcode * \param _CopyOptions Circle copy options. See \ref DisplayDrawOptionConstants. * \param _Point The circle's center point. See \ref RICImgPoint. * \param _Radius The circle's radius. */ #define RICOpCircle(_CopyOptions, _Point, _Radius) 10, 0, 7, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point, (_Radius)&0xFF, (_Radius)>>8 /** * Output an RIC NumBox opcode * \param _CopyOptions NumBox copy options. See \ref DisplayDrawOptionConstants. * \param _Point The numbox bottom left corner. See \ref RICImgPoint. * \param _Value The number to draw. */ #define RICOpNumBox(_CopyOptions, _Point, _Value) 10, 0, 8, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point, (_Value)&0xFF, (_Value)>>8 /** * Output an RIC Sprite opcode * \param _DataAddr The address of the sprite. * \param _Rows The number of rows of data. * \param _BytesPerRow The number of bytes per row. * \param _SpriteData The actual sprite data. See \ref RICSpriteData. */ #define RICOpSprite(_DataAddr, _Rows, _BytesPerRow, _SpriteData) ((_Rows*_BytesPerRow)+((_Rows*_BytesPerRow)%2)+8)&0xFF, ((_Rows*_BytesPerRow)+((_Rows*_BytesPerRow)%2)+8)>>8, 1, 0, (_DataAddr)&0xFF, (_DataAddr)>>8, (_Rows)&0xFF, (_Rows)>>8, (_BytesPerRow)&0xFF, (_BytesPerRow)>>8, _SpriteData /** * Output RIC sprite data */ #define RICSpriteData(...) __VA_ARGS__ /** * Output an RIC VarMap opcode * \param _DataAddr The address of the varmap. * \param _MapCount The number of points in the function. * \param _MapFunction The definition of the varmap function. See \ref RICMapFunction. */ #define RICOpVarMap(_DataAddr, _MapCount, _MapFunction) ((_MapCount*4)+6)&0xFF, ((_MapCount*4)+6)>>8, 2, 0, (_DataAddr)&0xFF, (_DataAddr)>>8, (_MapCount)&0xFF, (_MapCount)>>8, _MapFunction /** * Output an RIC map element * \param _Domain The map element domain. * \param _Range The map element range. */ #define RICMapElement(_Domain, _Range) (_Domain)&0xFF, (_Domain)>>8, (_Range)&0xFF, (_Range)>>8 /** * Output an RIC VarMap function * \param _MapElement An entry in the varmap function. At least 2 elements are * required. See \ref RICMapElement. */ #define RICMapFunction(_MapElement, ...) _MapElement, __VA_ARGS__ /** * Output an RIC parameterized argument * \param _arg The argument that you want to parameterize. */ #define RICArg(_arg) ((_arg)|0x1000) /** * Output an RIC parameterized and mapped argument * \param _mapidx The varmap data address. * \param _arg The parameterized argument you want to pass through a varmap. */ #define RICMapArg(_mapidx, _arg) ((_arg)|0x1000|(((_mapidx)&0xF)<<8)) /** * Output an RIC Polygon opcode * \param _CopyOptions Polygon copy options. See \ref DisplayDrawOptionConstants. * \param _Count The number of points in the polygon. * \param _ThePoints The list of polygon points. See \ref RICPolygonPoints. */ #define RICOpPolygon(_CopyOptions, _Count, _ThePoints) ((_Count*4)+6)&0xFF, ((_Count*4)+6)>>8, 10, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, (_Count)&0xFF, (_Count)>>8, _ThePoints /** * Output RIC polygon points * \param _pPoint1 The first polygon point. See \ref RICImgPoint. * \param _pPoint2 The second polygon point (at least 3 points are required). * See \ref RICImgPoint. */ #define RICPolygonPoints(_pPoint1, _pPoint2, ...) _pPoint1, _pPoint2, __VA_ARGS__ /** * Output an RIC Ellipse opcode * \param _CopyOptions Ellipse copy options. See \ref DisplayDrawOptionConstants. * \param _Point The center of the ellipse. See \ref RICImgPoint. * \param _RadiusX The x-axis radius of the ellipse. * \param _RadiusY The y-axis radius of the ellipse. */ #define RICOpEllipse(_CopyOptions, _Point, _RadiusX, _RadiusY) 12, 0, 9, 0, (_CopyOptions)&0xFF, (_CopyOptions)>>8, _Point, (_RadiusX)&0xFF, (_RadiusX)>>8, (_RadiusY)&0xFF, (_RadiusY)>>8 /** @} */ // end of RICMacros group /** @addtogroup MiscConstants * @{ */ /** @defgroup NXTLimits Data type limits * Constants that define various data type limits. * @{ */ #define CHAR_BIT 8 /*!< The number of bits in the char type */ #define SCHAR_MIN -128 /*!< The minimum value of the signed char type */ #define SCHAR_MAX 127 /*!< The maximum value of the signed char type */ #define UCHAR_MAX 255 /*!< The maximum value of the unsigned char type */ #define CHAR_MIN -128 /*!< The minimum value of the char type */ #define CHAR_MAX 127 /*!< The maximum value of the char type */ #define SHRT_MIN -32768 /*!< The minimum value of the short type */ #define SHRT_MAX 32767 /*!< The maximum value of the short type */ #define USHRT_MAX 65535 /*!< The maximum value of the unsigned short type */ #define INT_MIN -32768 /*!< The minimum value of the int type */ #define INT_MAX 32767 /*!< The maximum value of the int type */ #define UINT_MAX 65535 /*!< The maximum value of the unsigned int type */ #define LONG_MIN -2147483648 /*!< The minimum value of the long type */ #define LONG_MAX 2147483647 /*!< The maximum value of the long type */ #define ULONG_MAX 4294967295 /*!< The maximum value of the unsigned long type */ #define RAND_MAX 32768 /*!< The maximum unsigned int random number returned by rand */ /** @} */ // end of NXTLimits group /** @} */ // end of MiscConstants group /** @addtogroup GraphicsLibrary * @{ */ /*------------------------------------------------------------------------------ ; File : nbcGL.nbc ; Description : Data and subroutines for a very simple 3D engine. ; Programmed by : Arno van der Vegt, avandervegt@home.nl ;-----------------------------------------------------------------------------*/ /** @defgroup GLConstantsBeginModes Graphics library begin modes * Constants that are used to specify the polygon surface begin mode. * @{ */ #define GL_POLYGON 1 /*!< Use polygon mode. */ #define GL_LINE 2 /*!< Use line mode. */ #define GL_POINT 3 /*!< Use point mode. */ #define GL_CIRCLE 4 /*!< Use circle mode. */ /** @} */ // end of GLConstantsBeginModes group /** @defgroup GLConstantsActions Graphics library actions * Constants that are used to specify a graphics library action. * @{ */ #define GL_TRANSLATE_X 1 /*!< Translate along the X axis. */ #define GL_TRANSLATE_Y 2 /*!< Translate along the Y axis. */ #define GL_TRANSLATE_Z 3 /*!< Translate along the Z axis. */ #define GL_ROTATE_X 4 /*!< Rotate around the X axis. */ #define GL_ROTATE_Y 5 /*!< Rotate around the Y axis. */ #define GL_ROTATE_Z 6 /*!< Rotate around the Z axis. */ #define GL_SCALE_X 7 /*!< Scale along the X axis. */ #define GL_SCALE_Y 8 /*!< Scale along the Y axis. */ #define GL_SCALE_Z 9 /*!< Scale along the Z axis. */ /** @} */ // end of GLConstantsSettings group /** @defgroup GLConstantsSettings Graphics library settings * Constants that are used to configure the graphics library settings. * @{ */ #define GL_CIRCLE_SIZE 1 /*!< Set the circle size. */ #define GL_CULL_MODE 2 /*!< Set the cull mode. */ #define GL_CAMERA_DEPTH 3 /*!< Set the camera depth. */ #define GL_ZOOM_FACTOR 4 /*!< Set the zoom factor. */ /** @} */ // end of GLConstantsSettings group /** @defgroup GLConstantsCullMode Graphics library cull mode * Constants to use when setting the graphics library cull mode. * @{ */ #define GL_CULL_BACK 2 /*!< Cull lines in back. */ #define GL_CULL_FRONT 3 /*!< Cull lines in front. */ #define GL_CULL_NONE 4 /*!< Do not cull any lines. */ /** @} */ // end of GLConstantsCullMode group /** @} */ // end of GraphicsLibrary group #endif // NBCCOMMON_H NXT/uRPGComp.pas0000644000175000017500000002610311537752673013272 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uRPGComp; interface uses Classes; type TOnCompilerMessage = procedure(const msg : string; var stop : boolean) of object; TMainState = (msNormal, msBlockComment); TRPGComp = class private fMainStateLast : TMainState; fMainStateCurrent : TMainState; fCommands : TStrings; fCurFile: string; fMsgs: TStrings; fBadProgram : boolean; fProgErrorCount : integer; fLineCounter : integer; fOnCompMSg: TOnCompilerMessage; fCheckEOPLine : boolean; fMaxCommands: integer; fMaxErrors: word; procedure ProcessRPGLine(line : string); procedure ReportProblem(const lineNo: integer; const fName, line, msg: string; err: boolean); function ValidCommand(const line : string) : boolean; public constructor Create; destructor Destroy; override; procedure Parse(aStream : TStream); overload; procedure Parse(aStrings : TStrings); overload; function SaveToStream(aStream : TStream) : boolean; property CompilerMessages : TStrings read fMsgs; property CurrentFile : string read fCurFile write fCurFile; property MaxCommands : integer read fMaxCommands write fMaxCommands; property MaxErrors : word read fMaxErrors write fMaxErrors; property OnCompilerMessage : TOnCompilerMessage read fOnCompMSg write fOnCompMsg; end; implementation uses SysUtils, uCommonUtils, uLocalizedStrings; { TRPGComp } constructor TRPGComp.Create; begin fMsgs := TStringList.Create; fCommands := TStringList.Create; fMaxCommands := 5; fMaxErrors := 0; end; destructor TRPGComp.Destroy; begin FreeAndNil(fMsgs); FreeAndNil(fCommands); inherited; end; procedure TRPGComp.Parse(aStream: TStream); var S : TStrings; begin S := TStringList.Create; try S.LoadFromStream(aStream); Parse(S); finally S.Free; end; end; procedure TRPGComp.Parse(aStrings: TStrings); var i : integer; begin try fCommands.Clear; fBadProgram := False; fProgErrorCount := 0; fLineCounter := 0; fMainStateLast := msNormal; fMainStateCurrent := msNormal; fCheckEOPLine := False; for i := 0 to aStrings.Count - 1 do begin inc(fLineCounter); ProcessRPGLine(aStrings[i]); end; except on E : EAbort do begin fBadProgram := True; // end processing file due to Abort in ReportProblem end; on E : Exception do begin fBadProgram := True; ReportProblem(fLineCounter, CurrentFile, sException, E.Message, true); end; end; end; (* typedef struct { UBYTE FormatMsb; UBYTE FormatLsb; UBYTE DataBytesMsb; UBYTE DataBytesLsb; UBYTE Steps; UBYTE NotUsed1; UBYTE NotUsed2; UBYTE NotUsed3; UBYTE Data[]; } PROGRAM; *) const FILEFORMAT_PROGRAM = $0800; cmdTypeEmptyMove = $21; cmdTypeForward = $22; cmdTypeForwardFive = $23; cmdTypeBackLeftTwo = $24; cmdTypeTurnLeft = $25; cmdTypeTurnLeftTwo = $26; cmdTypeBackRight = $27; cmdTypeTurnRight = $28; cmdTypeTurnRightTwo = $29; cmdTypeBackLeft = $2A; cmdTypePlayTone1 = $2B; cmdTypePlayTone2 = $2C; cmdTypeBackward = $2D; cmdTypeBackwardFive = $2E; cmdTypeBackRightTwo = $2F; cmdTypeINVALID = $30; waitTypeEmptyWait = $41; waitTypeWaitForLight = $42; waitTypeWaitForObject = $43; waitTypeWaitForSound = $44; waitTypeWaitForTouch = $45; waitTypeWaitTwoSeconds = $46; waitTypeWaitFiveSeconds = $47; waitTypeWaitTenSeconds = $48; waitTypeWaitForDark = $49; // waitTypeINVALID = $4A; eopLOOP = $FC; eopSTOP = $FB; type RPGCommand = record Name : string; Value : byte; end; const RPG_COMMAND_COUNT = 26; RPGCommands : array[0..RPG_COMMAND_COUNT - 1] of RPGCommand = ( (Name : 'EmptyMove'; Value : cmdTypeEmptyMove;), (Name : 'Forward'; Value : cmdTypeForward;), (Name : 'ForwardFive'; Value : cmdTypeForwardFive;), (Name : 'BackLeftTwo'; Value : cmdTypeBackLeftTwo;), (Name : 'TurnLeft'; Value : cmdTypeTurnLeft;), (Name : 'TurnLeftTwo'; Value : cmdTypeTurnLeftTwo;), (Name : 'BackRight'; Value : cmdTypeBackRight;), (Name : 'TurnRight'; Value : cmdTypeTurnRight;), (Name : 'TurnRightTwo'; Value : cmdTypeTurnRightTwo;), (Name : 'BackLeft'; Value : cmdTypeBackLeft;), (Name : 'PlayToneOne'; Value : cmdTypePlayTone1;), (Name : 'PlayToneTwo'; Value : cmdTypePlayTone2;), (Name : 'Backward'; Value : cmdTypeBackward;), (Name : 'BackwardFive'; Value : cmdTypeBackwardFive;), (Name : 'BackRightTwo'; Value : cmdTypeBackRightTwo;), (Name : 'EmptyWait'; Value : waitTypeEmptyWait;), (Name : 'WaitForLight'; Value : waitTypeWaitForLight;), (Name : 'WaitForObject'; Value : waitTypeWaitForObject;), (Name : 'WaitForSound'; Value : waitTypeWaitForSound;), (Name : 'WaitForTouch'; Value : waitTypeWaitForTouch;), (Name : 'WaitTwoSeconds'; Value : waitTypeWaitTwoSeconds;), (Name : 'WaitFiveSeconds'; Value : waitTypeWaitFiveSeconds;), (Name : 'WaitTenSeconds'; Value : waitTypeWaitTenSeconds;), (Name : 'WaitForDark'; Value : waitTypeWaitForDark;), (Name : 'EndLoop'; Value : eopLOOP;), (Name : 'EndStop'; Value : eopSTOP;) ); function NameToValue(const name : string) : byte; var i : integer; begin Result := cmdTypeINVALID; for i := Low(RPGCommands) to High(RPGCommands) do begin if LowerCase(RPGCommands[i].Name) = LowerCase(name) then begin Result := RPGCommands[i].Value; break; end; end; end; function TRPGComp.SaveToStream(aStream: TStream) : boolean; var w : word; b : byte; i : integer; begin Result := False; if fBadProgram then begin ReportProblem(-1, CurrentFile, '', Format(sProgramError, [fProgErrorCount]), true) end else begin // and write everything to the stream aStream.Position := 0; w := FILEFORMAT_PROGRAM; WriteWordToStream(aStream, w, False); w := Word(fCommands.Count); WriteWordToStream(aStream, w, False); b := Byte(w); aStream.Write(b, 1); // three bytes of zero b := 0; aStream.Write(b, 1); aStream.Write(b, 1); aStream.Write(b, 1); for i := 0 to fCommands.Count - 1 do begin b := NameToValue(fCommands[i]); aStream.Write(b, 1); end; Result := True; end; end; procedure TRPGComp.ReportProblem(const lineNo: integer; const fName, line, msg: string; err : boolean); var tmp, tmp1, tmp2, tmp3, tmp4 : string; stop : boolean; begin if lineNo = -1 then begin tmp := msg; fMsgs.Add(tmp); end else begin if err then tmp1 := Format('# Error: %s', [msg]) else tmp1 := Format('# Warning: %s', [msg]); fMsgs.Add(tmp1); tmp2 := Format('File "%s" ; line %d', [fName, lineNo]); fMsgs.Add(tmp2); tmp3 := Format('# %s', [line]); fMsgs.Add(tmp3); tmp4 := '#----------------------------------------------------------'; fMsgs.Add(tmp4); tmp := tmp1+#13#10+tmp2+#13#10+tmp3+#13#10+tmp4; end; fBadProgram := err; if err then inc(fProgErrorCount); stop := (MaxErrors > 0) and (fProgErrorCount >= MaxErrors); // stop := false; if assigned(fOnCompMsg) then fOnCompMsg(tmp, stop); if stop then Abort; end; procedure TRPGComp.ProcessRPGLine(line: string); var i, endBCPos : integer; inBlockComment : boolean; lowline : string; begin line := Trim(line); // do nothing if line is blank or a comment if (line = '') or (Pos(';', line) = 1) or (Pos('//', line) = 1) then Exit; // check for the possibility that we are starting or ending a block comment on this line // nesting block comments is not supported and will result in compiler errors i := Pos('/*', line); endBCPos := Pos('*/', line); if (endBCPos = 0) or ((fMainStateCurrent <> msBlockComment) and (endBCPos = 0)) then inBlockComment := i > 0 else if endBCPos <> 0 then inBlockComment := i > endBCPos+1 else inBlockComment := False; if (endBCPos > 0) and (fMainStateCurrent = msBlockComment) then begin // remove everything from line up to end block comment Delete(line, 1, endBCPos+1); // revert to previous state fMainStateCurrent := fMainStateLast; end; if inBlockComment then begin Delete(line, i, MaxInt); // delete to end of line end else if (i > 0) and (endBCPos > i+1) then begin // just remove the block comment portion of the line Delete(line, i, endBCPos-i+2); // we don't want a block comment remove to result in a valid // identifier or function Insert(' ', line, i); end; // if we were already in a block comment before starting this line // and we still are in a block comment after the above processing // then we can skip the rest of this routine if fMainStateCurrent = msBlockComment then Exit; // double check for a blank line since we have manipulated it if Trim(line) <> '' then begin if fCheckEOPLine then begin ReportProblem(fLineCounter, CurrentFile, line, sNothingAfterEnd, true); end else begin if fCommands.Count >= MaxCommands then ReportProblem(fLineCounter, CurrentFile, line, sTooManyCommands, true) else begin i := Pos(';', line); if i <> 0 then System.Delete(line, i, MaxInt); i := Pos('//', line); if i <> 0 then System.Delete(line, i, MaxInt); if ValidCommand(line) then begin lowline := LowerCase(line); fCommands.Add(lowline); if (lowline = 'endloop') or (lowline = 'endstop') then fCheckEOPLine := True; end else begin ReportProblem(fLineCounter, CurrentFile, line, sUnknownCommand, true); end; end; end; end; end; function TRPGComp.ValidCommand(const line: string): boolean; var i : integer; begin Result := False; for i := Low(RPGCommands) to High(RPGCommands) do begin if LowerCase(RPGCommands[i].Name) = LowerCase(line) then begin Result := True; break; end; end; end; end. NXT/uNBCInterface.pas0000644000175000017500000006540511537752673014256 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNBCInterface; interface uses Classes, {$IFDEF CAN_DOWNLOAD} uSpirit, FantomSpirit, {$ENDIF} uNXTClasses, uRPGComp, uNXCComp, uRICComp; type TWriteMessages = procedure(aStrings : TStrings); TNBCCompiler = class private fFilename : string; fQuiet: boolean; fWriteSymbolTable: boolean; fSymbolTableFilename: string; fWriteIntermediateCode: boolean; fIntermediateCodeFilename: string; fWriteOutput: boolean; fOutputFilename: string; fNXTName : string; fUseSpecialName: boolean; fSpecialName: string; fOptLevel: integer; fBinaryInput: boolean; fDownload: boolean; fRunProgram: boolean; fDefaultIncludeDir: string; fMoreIncludes: boolean; fIncludePaths: string; fOnWriteMessages: TWriteMessages; fWarningsAreOff: boolean; fEnhancedFirmware: boolean; fWriteCompilerOutput: boolean; fCompilerOutputFilename: string; fExtraDefines: TStrings; fMessages : TStrings; fCommandLine: string; fWriteCompilerMessages: boolean; fCompilerMessagesFilename: string; fIgnoreSystemFile: boolean; fSafeCalls: boolean; fMaxErrors: word; fFirmwareVersion: word; fMaxPreProcDepth: word; protected fOnCompilerStatusChange : TCompilerStatusChangeEvent; fDump : TStrings; fBCCreated : boolean; fUsePort: boolean; fPortName: string; fDownloadList : string; {$IFDEF CAN_DOWNLOAD} fBC : TBrickComm; function GetBrickComm : TBrickComm; procedure SetBrickComm(Value : TBrickComm); procedure DoBeep; procedure DownloadRequestedFiles; function CheckFirmwareVersion : boolean; {$ENDIF} procedure DoWriteCompilerOutput(aStrings: TStrings); procedure DoWriteSymbolTable(C : TRXEProgram); procedure DoWriteIntermediateCode(NC : TNXCComp); procedure DoWriteMessages(aStrings : TStrings); procedure DoWriteMessage(const aString : String); function GetCurrentFilename : string; procedure SetCommandLine(const Value: string); public constructor Create; virtual; destructor Destroy; override; function Execute : integer; procedure Decompile; class procedure DumpAPI(const idx : integer); procedure HandleOnCompilerStatusChange(Sender : TObject; const StatusMsg : string; const bDone : boolean); property CommandLine : string read fCommandLine write SetCommandLine; property InputFilename : string read fFilename write fFilename; property IgnoreSystemFile : boolean read fIgnoreSystemFile write fIgnoreSystemFile; property Quiet : boolean read fQuiet write fQuiet; property MaxErrors : word read fMaxErrors write fMaxErrors; property MaxPreprocessorDepth : word read fMaxPreProcDepth write fMaxPreProcDepth; property WriteCompilerOutput : boolean read fWriteCompilerOutput write fWriteCompilerOutput; property CompilerOutputFilename : string read fCompilerOutputFilename write fCompilerOutputFilename; property WriteSymbolTable : boolean read fWriteSymbolTable write fWriteSymbolTable; property SymbolTableFilename : string read fSymbolTableFilename write fSymbolTableFilename; property WriteIntermediateCode : boolean read fWriteIntermediateCode write fWriteIntermediateCode; property IntermediateCodeFilename : string read fIntermediateCodeFilename write fIntermediateCodeFilename; property WriteOutput : boolean read fWriteOutput write fWriteOutput; property OutputFilename : string read fOutputFilename write fOutputFilename; property WriteCompilerMessages : boolean read fWriteCompilerMessages write fWriteCompilerMessages; property CompilerMessagesFilename : string read fCompilerMessagesFilename write fCompilerMessagesFilename; property Decompilation : TStrings read fDump; property ExtraDefines : TStrings read fExtraDefines; property Messages : TStrings read fMessages; property NXTName : string read fNXTName write fNXTName; property UseSpecialName : boolean read fUseSpecialName write fUseSpecialName; property SpecialName : string read fSpecialName write fSpecialName; property OptimizationLevel : integer read fOptLevel write fOptLevel; property UsePort : boolean read fUsePort write fUsePort; property PortName : string read fPortName write fPortName; property BinaryInput : boolean read fBinaryInput write fBinaryInput; property Download : boolean read fDownload write fDownload; property RunProgram : boolean read fRunProgram write fRunProgram; property DefaultIncludeDir : string read fDefaultIncludeDir write fDefaultIncludeDir; property MoreIncludes : boolean read fMoreIncludes write fMoreIncludes; property IncludePaths : string read fIncludePaths write fIncludePaths; property WarningsAreOff : boolean read fWarningsAreOff write fWarningsAreOff; property EnhancedFirmware : boolean read fEnhancedFirmware write fEnhancedFirmware; property FirmwareVersion : word read fFirmwareVersion write fFirmwareVersion; property SafeCalls : boolean read fSafeCalls write fSafeCalls; property OnWriteMessages : TWriteMessages read fOnWriteMessages write fOnWriteMessages; property OnCompilerStatusChange : TCompilerStatusChangeEvent read fOnCompilerStatusChange write fOnCompilerStatusChange; {$IFDEF CAN_DOWNLOAD} property BrickComm : TBrickComm read GetBrickComm write SetBrickComm; {$ENDIF} end; function APIAsText(const idx : integer) : string; implementation uses SysUtils, Math, uVersionInfo, ParamUtils, uNXTConstants, NBCCommonData, NXTDefsData, NXCDefsData, uGlobals, uLocalizedStrings; { TNBCCompiler } constructor TNBCCompiler.Create; begin inherited; fMaxPreprocDepth := 10; fMaxErrors := 0; fIgnoreSystemFile := False; fEnhancedFirmware := False; fFirmwareVersion := 128; // 1.28 NXT 2.0 firmware fWarningsAreOff := False; fMoreIncludes := False; fBinaryInput := False; fDownload := False; fRunProgram := False; fUsePort := False; fBCCreated := False; fQuiet := False; fWriteSymbolTable := False; fWriteIntermediateCode := False; fUseSpecialName := False; fOptLevel := 0; fDump := TStringList.Create; fExtraDefines := TStringList.Create; fMessages := TStringList.Create; {$IFDEF CAN_DOWNLOAD} fBC := nil; {$ENDIF} end; destructor TNBCCompiler.Destroy; begin FreeAndNil(fDump); FreeAndNil(fExtraDefines); FreeAndNil(fMessages); {$IFDEF CAN_DOWNLOAD} if fBCCreated then FreeAndNil(fBC); {$ENDIF} inherited; end; {$IFDEF CAN_DOWNLOAD} function TNBCCompiler.GetBrickComm : TBrickComm; begin if not Assigned(fBC) then begin fBC := TFantomSpirit.Create(); fBCCreated := True; fBC.BrickType := rtNXT; end; Result := fBC; end; procedure TNBCCompiler.SetBrickComm(Value: TBrickComm); begin if fBCCreated then FreeAndNil(fBC); fBC := Value; fBCCreated := False; end; procedure TNBCCompiler.DoBeep; begin if not fQuiet then begin BrickComm.PlayTone(440, 100); end; end; {$ENDIF} procedure TNBCCompiler.DoWriteCompilerOutput(aStrings : TStrings); var dir, logFilename : string; begin if WriteCompilerOutput then begin logFilename := CompilerOutputFilename; dir := ExtractFilePath(logFilename); if dir <> '' then ForceDirectories(dir); // the code listing is the source code (since it is assembler) aStrings.SaveToFile(logFilename); end; end; procedure TNBCCompiler.DoWriteSymbolTable(C : TRXEProgram); var dir, logFilename : string; begin if WriteSymbolTable then begin logFilename := SymbolTableFilename; dir := ExtractFilePath(logFilename); if dir <> '' then ForceDirectories(dir); C.SymbolTable.SaveToFile(logFilename); end; end; procedure TNBCCompiler.DoWriteIntermediateCode(NC : TNXCComp); var dir, logFilename : string; begin if WriteIntermediateCode then begin logFilename := IntermediateCodeFilename; dir := ExtractFilePath(logFilename); if dir <> '' then ForceDirectories(dir); NC.NBCSource.SaveToFile(logFilename); end; end; procedure TNBCCompiler.Decompile; var D : TRXEDumper; ext : string; begin ext := Lowercase(ExtractFileExt(fFilename)); if (ext = '.rxe') or (ext = '.sys') or (ext = '.rtm') then begin D := TRXEDumper.Create; try D.FirmwareVersion := FirmwareVersion; D.LoadFromFile(fFilename); D.Decompile(fDump); finally D.Free; end; end else if (ext = '.ric') then begin fDump.Text := TRICComp.RICToText(fFilename); end else Exit; // do nothing if WriteOutput then begin // write the contents of fDump to the file fDump.SaveToFile(OutputFilename); end; end; function GetDefaultPath : string; begin // Result := ExtractFilePath(ParamStr(0)); Result := IncludeTrailingPathDelimiter(GetCurrentDir); end; function TNBCCompiler.GetCurrentFilename : string; var ext : string; begin ext := ExtractFileExt(InputFilename); Result := ChangeFileExt(NXTName, ext); // add a path if there isn't one already if ExtractFilename(Result) = Result then Result := GetDefaultPath + Result; end; function TNBCCompiler.Execute : integer; var sIn : TMemoryStream; sOut : TMemoryStream; tmpIncDirs : TStringList; C : TRXEProgram; NC : TNXCComp; RC : TRPGComp; RIC : TRICComp; {$IFDEF CAN_DOWNLOAD} theType : TNXTFileType; tmpName : string; {$ENDIF} i : integer; incDirs : string; bNXCErrors : boolean; begin fDownloadList := ''; Result := 0; if WriteOutput then NXTName := OutputFilename else if UseSpecialName then NXTName := SpecialName else NXTName := InputFilename; {$IFDEF CAN_DOWNLOAD} if Download or RunProgram then begin if BrickComm.Port = '' then begin if UsePort then begin BrickComm.Port := PortName; end else BrickComm.Port := 'usb'; // if no port is specified then default to usb end; end; {$ENDIF} sIn := TMemoryStream.Create; try if FileExists(InputFilename) then sIn.LoadFromFile(InputFilename) else begin // can't find input file Result := 1; // compiler error DoWriteMessage('# Error: ' + Format(sCannotFindFile, [InputFilename])); Exit; end; if BinaryInput and (Download or RunProgram) then begin {$IFDEF CAN_DOWNLOAD} // just download the already compiled binary file if not BrickComm.IsOpen then BrickComm.Open; theType := NameToNXTFileType(InputFilename); if LowerCase(ExtractFileExt(InputFilename)) = '.rpg' then theType := nftOther; BrickComm.StopProgram; if Download then begin if BrickComm.NXTDownloadStream(sIn, InputFilename, theType) then DoBeep else begin Result := 2; HandleOnCompilerStatusChange(Self, sDownloadFailed, True); end; end; if RunProgram then BrickComm.StartProgram(InputFilename); {$ENDIF} end else begin tmpIncDirs := TStringList.Create; try tmpIncDirs.Sorted := True; tmpIncDirs.Duplicates := dupIgnore; // add the default include directory tmpIncDirs.Add(IncludeTrailingPathDelimiter(DefaultIncludeDir)); if MoreIncludes then begin incDirs := IncludePaths; // does the path contain ';'? If so parse i := Pos(';', incDirs); while i > 0 do begin tmpIncDirs.Add(IncludeTrailingPathDelimiter(Copy(incDirs, 1, i-1))); Delete(incDirs, 1, i); i := Pos(';', incDirs); end; tmpIncDirs.Add(IncludeTrailingPathDelimiter(incDirs)); end; if LowerCase(ExtractFileExt(InputFilename)) = '.npg' then begin // RPG compiler RC := TRPGComp.Create; try RC.CurrentFile := GetCurrentFilename; RC.MaxErrors := MaxErrors; try RC.Parse(sIn); sOut := TMemoryStream.Create; try if RC.SaveToStream(sOut) then begin {$IFDEF CAN_DOWNLOAD} if Download then begin // download the compiled code to the brick if not BrickComm.IsOpen then BrickComm.Open; BrickComm.StopProgram; if BrickComm.NXTDownloadStream(sOut, ChangeFileExt(nxtName, '.rpg'), nftOther) then DoBeep else Result := 2; end; {$ENDIF} if WriteOutput then sOut.SaveToFile(nxtName); end else Result := 1; finally sOut.Free; end; finally DoWriteMessages(RC.CompilerMessages); end; finally RC.Free; end; end else if LowerCase(ExtractFileExt(InputFilename)) = '.rs' then begin // RIC compiler RIC := TRICComp.Create; try RIC.IncludeDirs.AddStrings(tmpIncDirs); RIC.CurrentFile := GetCurrentFilename; RIC.EnhancedFirmware := EnhancedFirmware; RIC.FirmwareVersion := FirmwareVersion; RIC.MaxErrors := MaxErrors; try RIC.Parse(sIn); if RIC.CompilerMessages.Count = 0 then begin sOut := TMemoryStream.Create; try RIC.SaveToStream(sOut); {$IFDEF CAN_DOWNLOAD} if Download then begin // download the compiled code to the brick if not BrickComm.IsOpen then BrickComm.Open; if CheckFirmwareVersion then begin BrickComm.StopProgram; if BrickComm.NXTDownloadStream(sOut, ChangeFileExt(nxtName, '.ric'), nftGraphics) then DoBeep else Result := 2; end else Result := 3; end; {$ENDIF} if WriteOutput then sOut.SaveToFile(nxtName); finally sOut.Free; end; end else Result := 1; finally DoWriteMessages(RIC.CompilerMessages); end; finally RIC.Free; end; end else begin bNXCErrors := False; if LowerCase(ExtractFileExt(InputFilename)) = '.nxc' then begin NC := TNXCComp.Create; try NC.OnCompilerStatusChange := HandleOnCompilerStatusChange; NC.Defines.AddStrings(ExtraDefines); NC.OptimizeLevel := OptimizationLevel; NC.IncludeDirs.AddStrings(tmpIncDirs); NC.CurrentFile := GetCurrentFilename; NC.WarningsOff := WarningsAreOff; NC.IgnoreSystemFile := IgnoreSystemFile; NC.EnhancedFirmware := EnhancedFirmware; NC.FirmwareVersion := FirmwareVersion; NC.SafeCalls := SafeCalls; NC.MaxErrors := MaxErrors; NC.MaxPreprocessorDepth := MaxPreprocessorDepth; try NC.Parse(sIn); DoWriteIntermediateCode(NC); sIn.Clear; NC.NBCSource.SaveToStream(sIn); // this used to pass at least 1 as the optimization level // but if a user says no optimizations then the compiler // really should respect that and do no optimizations whatsoever OptimizationLevel := Max(OptimizationLevel, 0); sIn.Position := 0; finally DoWriteMessages(NC.CompilerMessages); end; bNXCErrors := NC.ErrorCount > 0; finally NC.Free; end; end; if not bNXCErrors then begin // compile the nbc file C := TRXEProgram.Create; try C.Defines.AddStrings(ExtraDefines); C.ReturnRequiredInSubroutine := True; C.OptimizeLevel := OptimizationLevel; C.WarningsOff := WarningsAreOff; C.EnhancedFirmware := EnhancedFirmware; C.FirmwareVersion := FirmwareVersion; C.IgnoreSystemFile := IgnoreSystemFile; C.MaxErrors := MaxErrors; C.MaxPreprocessorDepth := MaxPreprocessorDepth; C.OnCompilerStatusChange := HandleOnCompilerStatusChange; try C.IncludeDirs.AddStrings(tmpIncDirs); C.CurrentFile := GetCurrentFilename; fDownloadList := C.Parse(sIn); sOut := TMemoryStream.Create; try if C.SaveToStream(sOut) then begin DoWriteSymbolTable(C); {$IFDEF CAN_DOWNLOAD} tmpName := ChangeFileExt(MakeValidNXTFilename(NXTName), '.rxe'); if Download then begin // download the compiled code to the brick if not BrickComm.IsOpen then BrickComm.Open; if CheckFirmwareVersion then begin BrickComm.StopProgram; if BrickComm.NXTDownloadStream(sOut, tmpName, nftProgram) then DoBeep else begin Result := 2; HandleOnCompilerStatusChange(Self, sDownloadFailed, True); end; end else begin Result := 3; HandleOnCompilerStatusChange(Self, sVersionCheckFailed, True); end; end; if RunProgram then BrickComm.StartProgram(tmpName); {$ENDIF} if WriteOutput then sOut.SaveToFile(NXTName); end else begin Result := 1; HandleOnCompilerStatusChange(Self, sNBCCompilationFailed, True); end; finally sOut.Free; end; DoWriteCompilerOutput(C.CompilerOutput); finally DoWriteMessages(C.CompilerMessages); end; finally C.Free; end; end else begin Result := 1; HandleOnCompilerStatusChange(Self, sNXCCompilationFailed, True); end; end; finally tmpIncDirs.Free; end; end; finally sIn.Free; end; {$IFDEF CAN_DOWNLOAD} DownloadRequestedFiles; {$ENDIF} end; procedure TNBCCompiler.DoWriteMessages(aStrings: TStrings); begin fMessages.AddStrings(aStrings); // fMessages.Assign(aStrings); if Assigned(fOnWriteMessages) then fOnWriteMessages(aStrings); end; procedure TNBCCompiler.SetCommandLine(const Value: string); begin fCommandLine := Value; // set properties given command line switches IgnoreSystemFile := ParamSwitch('-n', False, Value); Quiet := ParamSwitch('-q', False, Value); MaxErrors := ParamIntValue('-ER', 0, False, Value); MaxPreprocessorDepth := ParamIntValue('-PD', 10, False, Value); FirmwareVersion := ParamIntValue('-v', 128, False, Value); WriteCompilerOutput := ParamSwitch('-L', False, Value); CompilerOutputFilename := ParamValue('-L', False, Value); WriteSymbolTable := ParamSwitch('-Y', False, Value); SymbolTableFilename := ParamValue('-Y', False, Value); WriteIntermediateCode := ParamSwitch('-nbc', False, Value); IntermediateCodeFilename := ParamValue('-nbc', False, Value); WriteOutput := ParamSwitch('-O', False, Value); OutputFilename := ParamValue('-O', False, Value); UseSpecialName := ParamSwitch('-N', False, Value); SpecialName := ParamValue('-N', False, Value); OptimizationLevel := 1; if ParamSwitch('-Z', False, Value) then OptimizationLevel := 2 else if ParamSwitch('-Z6', False, Value) then OptimizationLevel := 6 else if ParamSwitch('-Z5', False, Value) then OptimizationLevel := 5 else if ParamSwitch('-Z4', False, Value) then OptimizationLevel := 4 else if ParamSwitch('-Z3', False, Value) then OptimizationLevel := 3 else if ParamSwitch('-Z2', False, Value) then OptimizationLevel := 2 else if ParamSwitch('-Z1', False, Value) then OptimizationLevel := 1 else if ParamSwitch('-Z0', False, Value) then OptimizationLevel := 0; UsePort := ParamSwitch('-S', False, Value); PortName := ParamValue('-S', False, Value); BinaryInput := ParamSwitch('-b', False, Value); Download := ParamSwitch('-d', False, Value); RunProgram := ParamSwitch('-r', False, Value); MoreIncludes := ParamSwitch('-I', False, Value); IncludePaths := ParamValue('-I', False, Value); WarningsAreOff := ParamSwitch('-w-', False, Value); EnhancedFirmware := ParamSwitch('-EF', False, Value); SafeCalls := ParamSwitch('-safecall', False, Value); WriteCompilerMessages := ParamSwitch('-E', False, Value); CompilerMessagesFilename := ParamValue('-E', False, Value); end; procedure WriteBytes(data : array of byte); var i : integer; begin for i := Low(data) to High(data) do Write(Char(data[i])); end; class procedure TNBCCompiler.DumpAPI(const idx : integer); begin case idx of 0 : begin WriteBytes(nbc_common_data); WriteBytes(nxt_defs_data); WriteBytes(nxc_defs_data); end; 1 : WriteBytes(nbc_common_data); 2 : WriteBytes(nxt_defs_data); 3 : WriteBytes(nxc_defs_data); end; end; function APIAsText(const idx: integer): string; var X : TStringStream; tmp : string; begin X := TStringStream.Create(tmp); try case idx of 0 : begin X.Write(nbc_common_data, SizeOf(nbc_common_data)); X.Write(nxt_defs_data, SizeOf(nxt_defs_data)); X.Write(nxc_defs_data, SizeOf(nxc_defs_data)); end; 1 : X.Write(nbc_common_data, SizeOf(nbc_common_data)); 2 : X.Write(nxt_defs_data, SizeOf(nxt_defs_data)); 3 : X.Write(nxc_defs_data, SizeOf(nxc_defs_data)); end; Result := Copy(X.DataString, 1, MaxInt); finally X.Free; end; end; procedure TNBCCompiler.HandleOnCompilerStatusChange(Sender: TObject; const StatusMsg: string; const bDone : boolean); begin if Assigned(fOnCompilerStatusChange) then fOnCompilerStatusChange(Sender, StatusMsg, bDone); end; {$IFDEF CAN_DOWNLOAD} procedure TNBCCompiler.DownloadRequestedFiles; var tmpSL : TStringList; i : integer; tmpFilename, ext : string; begin if Download and (fDownloadList <> '') then begin tmpSL := TStringList.Create; try tmpSL.Text := fDownloadList; for i := 0 to tmpSL.Count - 1 do begin tmpFilename := tmpSL[i]; ext := AnsiLowercase(ExtractFileExt(tmpFilename)); // all files other than .npg, .rs, .nxc, and .nbc should // just be downloaded and not compiled first. BinaryInput := not ((ext = '.npg') or (ext = '.rs') or (ext = '.nxc') or (ext = '.nbc')); InputFilename := tmpFilename; // never write any output for these files WriteOutput := False; WriteCompilerOutput := False; WriteSymbolTable := False; WriteIntermediateCode := False; WriteCompilerMessages := False; // don't use a special name either UseSpecialName := False; // and do not run these either RunProgram := False; Execute; end; finally tmpSL.Free; end; end; end; function TNBCCompiler.CheckFirmwareVersion: boolean; var fwVer : word; begin fwVer := BrickComm.NXTFirmwareVersion; if fwVer <> 0 then begin // if we say we are targetting a 1.0x firmware then the actual // firmware version needs to be a 1.0x firmware. If we are targetting // the 1.2x firmware thne the actual firmware version is a 1.2x firmware. if FirmwareVersion <= MAX_FW_VER1X then begin // 1.0x Result := fwVer <= MAX_FW_VER1X; end else begin // 1.2x Result := fwVer >= MIN_FW_VER2X; end; end else begin // if, for some reason, this function returns false then we will go ahead // and assume that the correct version is installed Result := True; end; end; {$ENDIF} procedure TNBCCompiler.DoWriteMessage(const aString: String); var SL : TStringList; begin fMessages.Add(aString); if Assigned(fOnWriteMessages) then begin SL := TStringList.Create; try SL.Add(aString); fOnWriteMessages(SL); finally SL.Free; end; end; end; initialization VerCompanyName := 'JoCar Consulting'; VerFileDescription := ''; VerFileVersion := '1.2.1.r4'; VerInternalName := 'NBC'; VerLegalCopyright := 'Copyright (c) 2006-2010, John Hansen'; VerOriginalFileName := 'NBC'; VerProductName := 'Next Byte Codes Compiler'; VerProductVersion := '1.2'; VerComments := ''; end. NXT/uPreprocess.pas0000644000175000017500000014017211537752673014153 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uPreprocess; interface uses Classes, Contnrs, SysUtils, mwGenericLex, uGenLexer, uNBCCommon; type EPreprocessorException = class(Exception) private fLineNo : integer; public constructor Create(const msg : string; const lineno : integer); property LineNo : integer read fLineNo; end; { TMapList } TMapList = class(TStringList) private fConsiderCase: boolean; function GetMapValue(index: integer): string; procedure SetConsiderCase(const AValue: boolean); procedure SetMapValue(index: integer; const Value: string); protected {$IFDEF FPC} function DoCompareText(const s1,s2 : string) : PtrInt; override; {$ENDIF} public constructor Create; function AddEntry(const aName, aValue : string) : integer; procedure AddDefines(aValue : TStrings); procedure Define(const aName : string); procedure Clear; override; procedure Delete(Index: Integer); override; property MapValue[index : integer] : string read GetMapValue write SetMapValue; property ConsiderCase : boolean read fConsiderCase write SetConsiderCase; end; TPreprocessorStatusChangeEvent = procedure(Sender : TObject; const StatusMsg : string) of object; TLangPreprocessor = class private fLangName : TLangName; fWarnings : TStrings; fCalc : TNBCExpParser; fIncludeFilesToSkip : TStrings; IncludeDirs : TStringList; MacroDefs : TMapList; MacroFuncArgs : TMapList; fLevel : integer; fLevelIgnore : TObjectList; fGLC : TGenLexerClass; fLexers : TObjectList; fRecursionDepth : integer; fAddPoundLine: boolean; fOnPreprocessorStatusChange: TPreprocessorStatusChangeEvent; { fVarI : integer; fVarJ : integer; procedure SetThreadName(const name : string); procedure SetCurrentFile(const name : string); procedure SetVarJ(val : integer); procedure SetVarI(val : integer); procedure LoadStandardMacros; } function DoProcessStream(name: string; lineNo: integer; Stream: TMemoryStream; OutStrings: TStrings) : string; function GetLevelIgnoreValue(const lineno : integer): boolean; procedure SwitchLevelIgnoreValue(const lineno : integer); function ProcessIdentifier(const ident : string; Lex: TGenLexer; var lineNo: integer): string; function EvaluateIdentifier(const ident : string) : string; function ReplaceTokens(const tokenstring: string; lineNo : integer; bArgs : boolean): string; function ProcessMacroDefinition(const fname : string; bUndefine : boolean; Lex: TGenLexer; var lineNo: integer): integer; function GenLexerType : TGenLexerClass; function GetDefines: TMapList; function ProcessDefinedFunction(expr : string) : string; function EvaluateExpression(expr : string; lineno : integer) : boolean; function AcquireLexer(const lineNo : integer) : TGenLexer; procedure ReleaseLexer; procedure InitializeLexers(const num: integer); procedure AddOneOrMoreLines(OutStrings: TStrings; const S, name: string; var lineNo: integer); function IgnoringAtLowerLevel(const lineno: integer): boolean; function ImportRIC(const fname, varname : string) : string; function ImportFile(const fname : string; varname : string) : string; function GetPreprocPath(const fname : string; const path : string) : string; procedure DoPreprocessorStatusChange(const Status: string); public class function PreprocessStrings(GLType : TGenLexerClass; const fname : string; aStrings : TStrings; aLN : TLangName; MaxDepth : word) : string; class function PreprocessFile(GLType : TGenLexerClass; const fin, fout : string; aLN : TLangName; MaxDepth : word) : string; constructor Create(GLType : TGenLexerClass; const defIncDir : string; aLN : TLangName; MaxDepth : word); destructor Destroy; override; procedure SkipIncludeFile(const fname : string); function Preprocess(const fname: string; aStrings: TStrings) : string; overload; function Preprocess(const fname: string; aStream: TMemoryStream) : string; overload; procedure AddIncludeDirs(aStrings : TStrings); property Defines : TMapList read GetDefines; property AddPoundLineToMultiLineMacros : boolean read fAddPoundLine write fAddPoundLine; property Warnings : TStrings read fWarnings; property OnPreprocessorStatusChange : TPreprocessorStatusChangeEvent read fOnPreprocessorStatusChange write fOnPreprocessorStatusChange; end; implementation uses Math, uVersionInfo, uLocalizedStrings, uRICComp; type TPreprocLevel = class public Taken : boolean; Ignore : boolean; constructor Create; virtual; end; TIgnoreLevel = class(TPreprocLevel) public constructor Create; override; end; TProcessLevel = class(TPreprocLevel) public constructor Create; override; end; function CountLineEndings(ablock : string) : integer; var tmpSL : TStringList; begin tmpSL := TStringList.Create; try tmpSL.Text := ablock+'_'; Result := tmpSL.Count - 1; finally tmpSL.Free; end; end; { TLangPreprocessor } class function TLangPreprocessor.PreprocessStrings(GLType : TGenLexerClass; const fname : string; aStrings : TStrings; aLN : TLangName; MaxDepth : word) : string; var P : TLangPreprocessor; begin P := TLangPreprocessor.Create(GLType, ExtractFilePath(fname), aLN, MaxDepth); try Result := P.Preprocess(fname, aStrings); finally P.Free; end; end; class function TLangPreprocessor.PreprocessFile(GLType : TGenLexerClass; const fin, fout : string; aLN : TLangName; MaxDepth : word) : string; var SL : TStringList; begin SL := TStringList.Create; try SL.LoadFromFile(fin); Result := TLangPreprocessor.PreprocessStrings(GLType, fin, SL, aLN, MaxDepth); SL.SaveToFile(fout); finally SL.Free; end; end; function TLangPreprocessor.Preprocess(const fname: string; aStream: TMemoryStream) : string; var Strings : TStringList; begin // MacroDefs.Clear; fWarnings.Clear; fLevelIgnore.Clear; IncludeDirs.Add(IncludeTrailingPathDelimiter(ExtractFilePath(fname))); fLevelIgnore.Add(TProcessLevel.Create); // level zero is NOT ignored fLevel := 0; // starting level is zero fRecursionDepth := 0; Strings := TStringList.Create; try Result := DoProcessStream(fname, 0, aStream, Strings); aStream.Size := 0; // empty the stream Strings.SaveToStream(aStream); aStream.Position := 0; finally Strings.Free; end; end; function TLangPreprocessor.Preprocess(const fname : string; aStrings : TStrings) : string; var Stream: TMemoryStream; begin Stream := TMemoryStream.Create; try aStrings.SaveToStream(Stream); aStrings.Clear; Result := Preprocess(fname, Stream); aStrings.LoadFromStream(Stream); finally Stream.Free; end; end; function TLangPreprocessor.IgnoringAtLowerLevel(const lineno : integer) : boolean; var PL : TPreprocLevel; i : integer; begin Result := False; if (fLevel < 0) or (fLevel >= fLevelIgnore.Count) then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineno); for i := fLevel-1 downto 0 do begin PL := TPreprocLevel(fLevelIgnore[i]); if PL.Ignore then begin Result := True; Break; end; end; end; function TLangPreprocessor.GetLevelIgnoreValue(const lineno : integer) : boolean; var PL : TPreprocLevel; begin if (fLevel < 0) or (fLevel >= fLevelIgnore.Count) then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineno); PL := TPreprocLevel(fLevelIgnore[fLevel]); Result := PL.Ignore; end; procedure TLangPreprocessor.SwitchLevelIgnoreValue(const lineno : integer); var PL : TPreprocLevel; begin if (fLevel < 0) or (fLevel >= fLevelIgnore.Count) then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineno); PL := TPreprocLevel(fLevelIgnore[fLevel]); if PL.Taken then PL.Ignore := True else PL.Ignore := not PL.Ignore; if not PL.Ignore then PL.Taken := True; end; procedure TLangPreprocessor.AddOneOrMoreLines(OutStrings : TStrings; const S, name : string; var lineNo : integer); var SL : TStringList; lineCount : integer; begin if Pos(#10, S) > 0 then begin SL := TStringList.Create; try SL.Text := S; lineCount := SL.Count; if AddPoundLineToMultiLineMacros then begin dec(lineCount); if Copy(S, Length(S), 1) <> #10 then dec(lineCount); end; OutStrings.Add(Format('#pragma macro %d', [lineCount])); OutStrings.AddStrings(SL); // at the end of each multi-line macro expansion output a #line directive OutStrings.Add(Format('#line %d "%s"', [lineNo, name])); finally SL.Free; end; end else OutStrings.Add(S); end; function TLangPreprocessor.ReplaceTokens(const tokenstring: string; lineNo : integer; bArgs : boolean): string; var Lex : TGenLexer; map : TMapList; procedure AddToResult; var i{, len} : integer; charTok, ident : string; begin if Lex.Id = piIdent then begin if bArgs then begin i := map.IndexOf(Lex.Token); if i <> -1 then begin Result := Result + map.MapValue[i]; end else Result := Result + Lex.Token; end else begin // pass lex to ProcessIdentifier ident := Lex.Token; Result := Result + ProcessIdentifier(ident, Lex, lineNo); end; end { else if (Lex.Id = piSymbol) and (Lex.Token = '#') then begin len := Length(Result); if Pos('#', Result) = len then begin // the previous token was '#' and current token is '#' System.Delete(Result, len, 1); end else Result := Result + Lex.Token; end } else if Lex.Id = piChar then begin charTok := Lex.Token; charTok := Replace(charTok, '''', ''); if Length(charTok) > 1 then raise EPreprocessorException.Create(sInvalidCharConstant, lineNo); if Length(charTok) = 1 then Result := Result + IntToStr(Ord(charTok[1])); // if the length is not > 1 or = 1 then it must be = 0, // in which case there is no need to add anything to the result end else Result := Result + Lex.Token; end; begin Result := ''; if bArgs then map := MacroFuncArgs else map := MacroDefs; Lex := AcquireLexer(lineNo); try Lex.SetStartData(@tokenstring[1], Length(tokenstring)); while not Lex.AtEnd do begin AddToResult; Lex.Next; end; if Lex.Id <> piUnknown then AddToResult; finally ReleaseLexer; end; end; const WhiteSpaceIds = [piSpace, piComment, piInnerLineEnd, piLineEnd]; procedure SkipWhitespace(Lex : TGenLexer; var linesSkipped : integer); begin while (Lex.Id in WhiteSpaceIds) and not Lex.AtEnd do begin if Lex.Id = piLineEnd then inc(linesSkipped); Lex.Next; end; end; function TLangPreprocessor.ProcessIdentifier(const ident : string; Lex : TGenLexer; var lineNo : integer) : string; var i, linesSkipped : integer; macroVal, dirText, prevToken, tmp, tok : string; nestLevel : integer; bDone : boolean; begin Result := ''; // is token in defmap? if so replace it (smartly) // token may be a function which takes parameters // so if it is then we need to grab more tokens from ( to ) tok := ident; i := MacroDefs.IndexOf(tok); if i <> -1 then begin macroVal := MacroDefs.MapValue[i]; if Pos('#', macroVal) = 1 then begin linesSkipped := 0; // function macro - complicated // format of macroVal == #arg1,arg2,...,argn#formula // is next non-whitespace token '('? Lex.Next; // skip whitespace prior to '(' if any exists SkipWhitespace(Lex, linesSkipped); if (Lex.Id = piSymbol) and (Lex.Token = '(') then begin // move past the '(' Lex.Next; MacroFuncArgs.Clear; // start with an empty arg map Delete(macroVal, 1, 1); // remove starting '#' i := Pos('#', macroVal); dirText := Copy(macroVal, 1, i-1)+ ','; // arg1,arg2,...,argn, macroVal := Copy(macroVal, i+1, MaxInt); if (dirText = ',') and Lex.AtEnd then begin i := 1; dirText := ''; end; while not Lex.AtEnd do begin // skip whitespace prior to each arg instance SkipWhitespace(Lex, linesSkipped); prevToken := ''; // now collect tokens until either ',' or ')' or whitespace nestLevel := 0; while not ({((nestLevel <= 0) and (Lex.Id in WhiteSpaceIds)) or} ((Lex.Id = piSymbol) and (((nestLevel <= 0) and (Lex.Token = ',')) or ((nestLevel <= 0) and (Lex.Token = ')'))))) do begin prevToken := prevToken + Lex.Token; if Lex.Token = '(' then inc(nestLevel) else if Lex.Token = ')' then dec(nestLevel); Lex.Next; if Lex.AtEnd then break; end; prevToken := TrimRight(prevToken); // trim any whitespace // now match instance to arg // each identifier in the instance maps to // an argument in the defined macro function i := Pos(',', dirText); if i = 0 then Break; if ((i > 1) and (prevToken = '')) or ((i = 1) and (prevToken <> '')) then Break; if i > 1 then begin tmp := Copy(dirText, 1, i-1); if tmp = '...' then begin tmp := '__VA_ARGS__'; // now collect the rest of the tokens all the way up to the ')' while not (((Lex.Id = piSymbol) and (((nestLevel <= 0) and (Lex.Token = ')'))))) do begin // 2010-01-03 JCH - changed code to replace line endings with space. if (Lex.Token = #13#10) or (Lex.Token = #10#13) or (Lex.Token = #10) or (Lex.Token = #13) then prevToken := prevToken + ' ' else prevToken := prevToken + Lex.Token; if Lex.Token = '(' then inc(nestLevel) else if Lex.Token = ')' then dec(nestLevel); Lex.Next; if Lex.AtEnd then break; end; prevToken := TrimRight(prevToken); // trim any whitespace end; MacroFuncArgs.AddEntry(tmp, prevToken); end; Delete(dirText, 1, i); // skip whitespace following each arg instance SkipWhitespace(Lex, linesSkipped); if (Lex.Id = piSymbol) and (Lex.Token = ')') then Break; // stop looping Lex.Next; end; if (i = 0) or (dirText <> '') then raise EPreprocessorException.Create(Format(sMacroMismatch, [macroVal]), lineNo); // we have eaten '(' through ')' (possibly to end of line) bDone := False; Result := macroVal; while not bDone do begin tmp := Result; Result := ReplaceTokens(tmp, lineNo, True); Result := ReplaceTokens(Result, lineNo, False); Result := Replace(Result, '##', ''); bDone := tmp = Result; end; end else raise EPreprocessorException.Create(Format(sMacroMismatch, [macroVal]), lineNo); inc(lineNo, linesSkipped); end else begin // simple macro substitution // Result := ReplaceTokens(macroVal, lineNo, False); bDone := False; Result := macroVal; while not bDone do begin tmp := Result; Result := ReplaceTokens(Result, lineNo, False); Result := Replace(Result, '##', ''); bDone := tmp = Result; end; end; Result := EvaluateIdentifier(Result); end else Result := tok; end; function TrimTrailingSpaces(const S: string) : string; var I: Integer; begin I := Length(S); while (I > 0) and (S[I] = ' ') do Dec(I); Result := Copy(S, 1, I); end; function TLangPreprocessor.ProcessMacroDefinition(const fname : string; bUndefine : boolean; Lex : TGenLexer; var lineNo : integer) : integer; var macro, dirText, oldDef, macroVal, prevToken : string; bEndOfDefine, bArgMode : boolean; i, prevId : integer; procedure HandleDefinition; begin macroVal := ''; bEndOfDefine := (Lex.Id = piLineEnd) or Lex.AtEnd; while not bEndOfDefine do begin prevId := Lex.Id; prevToken := Lex.Token; Lex.Next; if bArgMode then begin if prevId = piIdent then begin dirText := dirText + prevToken + ','; // add argument end else if (prevId = piSymbol) and (prevToken = '...') then begin dirText := dirText + prevToken + ','; // add argument end else if (prevId = piSymbol) and (prevToken = ')') then begin Delete(dirText, Length(dirText), 1); // remove last character dirText := dirText + '#'; // end arguments bArgMode := False; end; end else begin if prevId <> piComment then begin if (prevId = piSymbol) and (prevToken = '\') and (Lex.Id = piLineEnd) then begin inc(lineNo); inc(Result); continue; end else macroVal := macroVal + prevToken; end; end; bEndOfDefine := (Lex.Id = piLineEnd) or Lex.AtEnd; end; end; begin Result := 0; // add/remove definition to/from defmap // line should have a space token (1) and then an identifier // token followed by an optional parameter list ( ... ) // followed by an optional value (everything left on the line // to EOL -- or multiple lines if line ends with '\') Lex.Next; // token ID should be piSpace if Lex.Id <> piSpace then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineNo); Lex.Next; // token ID should be piIdent if Lex.Id <> piIdent then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineNo); macro := Lex.Token; // the macro name if bUndefine then begin // no more info needed. Remove macro i := MacroDefs.IndexOf(macro); if i <> -1 then MacroDefs.Delete(i); end else begin // is the next token whitespace? Lex.Next; if Lex.Id in [piSpace, piLineEnd] then begin // collect to end of #define (skipping comments) bArgMode := False; dirText := ''; HandleDefinition; end else if (Lex.Id = piSymbol) and (Lex.Token = '(') then begin bArgMode := True; Lex.Next; dirText := '#'; // flag that this is a function macro HandleDefinition; end; dirText := Trim(dirText) + TrimTrailingSpaces(TrimLeft(macroVal)); // check for macro definition i := MacroDefs.IndexOf(macro); if i <> -1 then begin oldDef := MacroDefs.MapValue[i]; if dirText <> oldDef then fWarnings.Add(IntToStr(lineNo) + '=' + fname + '|Redefinition of ''' + macro + ''' is not identical'); // now remove the previous declaration MacroDefs.Delete(i); end; MacroDefs.AddEntry(macro, dirText); end; end; function TLangPreprocessor.DoProcessStream(name : string; lineNo : integer; Stream : TMemoryStream; OutStrings : TStrings) : string; var Lex: TGenLexer; S, dir, dirText, tmpname, usePath, macro, tmp : string; X : TMemoryStream; i, j, cnt, origLevel, qPos, oldLineNo : integer; bFileFound, bDefined, bProcess : boolean; origName, ident : string; begin DoPreprocessorStatusChange(sIncludePath + ' = ' + IncludeDirs.DelimitedText); Result := ''; origName := name; S := ''; origLevel := fLevel; // at the start of each call to this function output a #line directive bProcess := not GetLevelIgnoreValue(lineNo); if bProcess and (lineNo > 0) then OutStrings.Add('#line 0 "' + name + '"'); // OutStrings.Add('#line ' + IntToStr(lineNo) + ' "' + name + '"'); if lineNo <= 0 then lineNo := 1; Lex := GenLexerType.CreateLexer; try Lex.SetStartData(Stream.Memory, Integer(Stream.Size)); while not Lex.AtEnd do begin case Lex.Id of piSpace : begin S := S + ' '; // all space == single space end; piLineEnd, piInnerLineEnd : begin // output S and clear it if bProcess then AddOneOrMoreLines(OutStrings, S, name, lineNo) else OutStrings.Add(''); S := ''; inc(lineNo); end; piComment : begin // strip all comments end; piDirective : begin // if we have some non-blank text collected then output it before // we process the directive if Trim(S) <> '' then begin // output S and clear it if bProcess then AddOneOrMoreLines(OutStrings, S, name, lineNo) else OutStrings.Add(''); S := ''; end; // some sort of preprocessor directive. dir := AnsiLowerCase(Lex.Token); dirText := ''; if dir = '#download' then begin // collect to end of line Lex.Next; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; if bProcess then begin S := dir + dirText; dirText := Trim(dirText); // get filename qPos := Pos('"', dirText); if qPos > 0 then begin System.Delete(dirText, 1, qPos); qPos := Pos('"', dirText); if qPos > 0 then begin tmpName := Copy(dirText, 1, qPos-1); DoPreprocessorStatusChange(sProcessingDownload + ': ' + tmpName); usePath := ''; // first try to find the file without any include path DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(tmpName); if not bFileFound then begin for i := 0 to IncludeDirs.Count - 1 do begin usePath := GetPreprocPath(origName, IncludeDirs[i]); DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(usePath+tmpName); if bFileFound then Break; end; end; if bFileFound then begin DoPreprocessorStatusChange(sFoundFile + ': ' + usePath+tmpName); // add this filename to the result Result := Result + usePath+tmpName + #13#10; end else raise EPreprocessorException.Create(Format(sDownloadNotFound, [tmpName]), lineNo); // // output a blank line to replace directive // OutStrings.Add(''); OutStrings.Add(S); // leave the #download in for the next stage to process S := ''; end else raise EPreprocessorException.Create(sDownloadMissingQuotes, lineNo); end else raise EPreprocessorException.Create(sDownloadMissingQuotes, lineNo); end; end else if dir = '#import' then begin // collect to end of line Lex.Next; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; if bProcess then begin dirText := Trim(dirText); // get filename qPos := Pos('"', dirText); if qPos > 0 then begin System.Delete(dirText, 1, qPos); qPos := Pos('"', dirText); if qPos > 0 then begin tmpName := Copy(dirText, 1, qPos-1); DoPreprocessorStatusChange(sProcessingImport + ': ' + tmpName); System.Delete(dirText, 1, qPos); usePath := ''; // first try to find the file without any include path DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(tmpName); if not bFileFound then begin for i := 0 to IncludeDirs.Count - 1 do begin usePath := GetPreprocPath(origName, IncludeDirs[i]); DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(usePath+tmpName); if bFileFound then Break; end; end; if bFileFound then begin DoPreprocessorStatusChange(sFoundFile + ': ' + usePath+tmpName); dirtext := Trim(dirText); // the optional parameter is only up to the first space or '/' i := Pos(' ', dirText); j := Pos('/', dirText); i := Min(i, j); if i > 0 then System.Delete(dirText, i, MaxInt); // delete the rest of the line // import the file if LowerCase(ExtractFileExt(usepath+tmpName)) = '.ric' then begin S := ImportRIC(usePath+tmpName, dirText); // AddOneOrMoreLines(OutStrings, S, name, lineNo); // S := ''; end else S := ImportFile(usePath+tmpName, dirText); // raise EPreprocessorException.Create(sImportRICInvalid, lineNo); end else raise EPreprocessorException.Create(Format(sImportRICNotFound, [tmpName]), lineNo); end else raise EPreprocessorException.Create(sImportRICMissingQuotes, lineNo); end else raise EPreprocessorException.Create(sImportRICMissingQuotes, lineNo); end else OutStrings.Add(''); end else if dir = '#include' then begin // collect to end of line Lex.Next; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; if bProcess then begin dirText := Trim(dirText); // get filename qPos := Pos('"', dirText); if qPos > 0 then begin System.Delete(dirText, 1, qPos); qPos := Pos('"', dirText); if qPos > 0 then begin tmpName := Copy(dirText, 1, qPos-1); DoPreprocessorStatusChange(sProcessingInclude + ': ' + tmpName); if fIncludeFilesToSkip.IndexOf(tmpName) = -1 then begin X := TMemoryStream.Create; try usePath := ''; // first try to find the file without any include path DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(tmpName); if not bFileFound then begin for i := 0 to IncludeDirs.Count - 1 do begin usePath := GetPreprocPath(origName, IncludeDirs[i]); DoPreprocessorStatusChange(sSearchingForFile + ': ' + usePath+tmpName); bFileFound := FileExists(usePath+tmpName); if bFileFound then Break; end; end; if bFileFound then begin DoPreprocessorStatusChange(sFoundFile + ': ' + usePath+tmpName); // load into stream X.LoadFromFile(usePath+tmpName); // call function recursively DoProcessStream(usePath+tmpName, 1, X, OutStrings); end else raise EPreprocessorException.Create(Format(sIncludeNotFound, [tmpName]), lineNo); finally X.Free; end; // at the end of each #include output a #line directive OutStrings.Add('#line ' + IntToStr(lineNo) + ' "' + name + '"'); end else // output a blank line to replace directive OutStrings.Add(''); end else raise EPreprocessorException.Create(sIncludeMissingQuotes, lineNo); end else raise EPreprocessorException.Create(sIncludeMissingQuotes, lineNo); end; end else if dir = '#reset' then begin lineNo := 0; name := origName; OutStrings.Add('#line ' + IntToStr(lineNo) + ' "' + name + '"'); end else if dir = '#error' then begin // collect to end of line Lex.Next; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; if bProcess then begin dirText := Replace(Trim(dirText), '"', ''); raise EPreprocessorException.Create(dirText, lineNo); end; // output a blank line to replace directive OutStrings.Add(''); end else if (dir = '#define') or (dir = '#undef') then begin cnt := 1; // number of lines in #define if bProcess then begin cnt := cnt + ProcessMacroDefinition(name, dir = '#undef', Lex, lineNo); end; // output blank line(s) to replace #define for i := 0 to cnt - 1 do OutStrings.Add(''); end else if (dir = '#if') or (dir = '#elif') then begin // increment level Lex.Next; // token ID should be piSpace if Lex.Id <> piSpace then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineNo); dirText := ''; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; // replace defined(xxx) or defined IDENT with a 0 or 1 dirText := ProcessDefinedFunction(dirText); // replace defined macros in expression dirText := ReplaceTokens(dirText, lineNo, False); if dir = '#if' then begin // reset bProcess to reflect the containing level's value bProcess := not GetLevelIgnoreValue(lineNo); // evaluate expression // if we are already ignoring code because of a containing // if/elif/ifdef/ifndef then it doesn't matter what the // expression evaluates to bDefined := EvaluateExpression(dirText, lineNo) and bProcess; if bDefined then fLevelIgnore.Add(TProcessLevel.Create) else fLevelIgnore.Add(TIgnoreLevel.Create); // continue to ignore inc(fLevel); bProcess := not GetLevelIgnoreValue(lineNo); end else begin dec(fLevel); // reset bProcess to reflect the containing level's value bProcess := not GetLevelIgnoreValue(lineNo); // evaluate expression // if we are already ignoring code because of a containing // if/elif/ifdef/ifndef then it doesn't matter what the // expression evaluates to bDefined := EvaluateExpression(dirText, lineNo) and bProcess; // restore current nesting level inc(fLevel); // #elif does not increase the level // have we already been processing code at this level? bProcess := not GetLevelIgnoreValue(lineNo); if bProcess or (not bProcess and bDefined) then begin // if we are already processing then always // turn off processing // if we are not already processing then turn ON // processing if bDefined is true SwitchLevelIgnoreValue(lineNo); bProcess := not GetLevelIgnoreValue(lineNo); end; end; // output a blank line to replace directive OutStrings.Add(''); end else if (dir = '#ifndef') or (dir = '#ifdef') then begin // increment level Lex.Next; // token ID should be piSpace if Lex.Id <> piSpace then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineNo); Lex.Next; // token ID should be piIdent or piNumber if not Lex.Id in [piIdent, piNumber] then raise EPreprocessorException.Create(sInvalidPreprocDirective, lineNo); if Lex.Id = piIdent then begin macro := Lex.Token; // the macro name bDefined := MacroDefs.IndexOf(macro) <> -1; end else begin // Lex.Token == number i := StrToIntDef(Lex.Token, 0); bDefined := i <> 0; end; if not bProcess then begin // if we are already ignoring code because of a containing // ifdef/ifndef then always ignore anything below this level fLevelIgnore.Add(TIgnoreLevel.Create); end else begin if (bDefined and (dir = '#ifdef')) or not (bDefined or (dir = '#ifdef')) then fLevelIgnore.Add(TProcessLevel.Create) else fLevelIgnore.Add(TIgnoreLevel.Create); end; inc(fLevel); bProcess := not GetLevelIgnoreValue(lineNo); // output a blank line to replace directive OutStrings.Add(''); end else if dir = '#endif' then begin // decrement level fLevelIgnore.Delete(fLevel); dec(fLevel); bProcess := not GetLevelIgnoreValue(lineNo); // output a blank line to replace directive OutStrings.Add(''); end else if dir = '#else' then begin // if we are already ignoring code because of a containing // if/elif/ifdef/ifndef then we just ignore the #else if not IgnoringAtLowerLevel(lineNo) then begin // switch mode at current level (must be > 0) SwitchLevelIgnoreValue(lineNo); bProcess := not GetLevelIgnoreValue(lineNo); end; // output a blank line to replace directive OutStrings.Add(''); end else if (dir = '#pragma') or (dir = '#line') then begin // collect to end of line Lex.Next; while (Lex.Id <> piLineEnd) and not Lex.AtEnd do begin dirText := dirText + Lex.Token; Lex.Next; end; if bProcess then begin dirText := dir + ' ' + Trim(dirText); OutStrings.Add(dirText); if dir = '#line' then begin // get filename qPos := Pos('"', dirText); if qPos > 0 then begin System.Delete(dirText, 1, qPos); qPos := Pos('"', dirText); if qPos > 0 then begin tmpName := Copy(dirText, 1, qPos-1); name := tmpName; end; end; end; end; end; // eat to end of line while (Lex.Id <> piLineEnd) and not Lex.AtEnd do Lex.Next; inc(lineNo); end; piZero, piUnknown : {do nothing}; piIdent : begin if bProcess then begin oldLineNo := lineNo; ident := Lex.Token; // we need to fix a problem here where our tokenizer is including // a leading "." as part of the identifier if Pos('.', ident) = 1 then begin System.Delete(ident, 1, 1); // remove the "." tmp := '.' + ProcessIdentifier(ident, Lex, lineNo); end else begin tmp := ProcessIdentifier(ident, Lex, lineNo); end; if Pos(#10, tmp) > 0 then begin if AddPoundLineToMultiLineMacros then begin // add #line to multi-line macros tmp := tmp + Format(#13#10'#line %d "%s"'#13#10, [oldLineNo-1, name]); end; // if we just processed a multi-line macro then we need to first // output S (if not empty) and then set S equal to our multi-line macro if Trim(S) <> '' then begin // output S and then set it to tmp AddOneOrMoreLines(OutStrings, S, name, lineNo); end; S := tmp; end else S := S + tmp; end; end; else if bProcess then S := S + Lex.Token; end; Lex.Next; end; // 2006-12-11 JCH - need to add the very last token if bProcess and not (Lex.Id in [piLineEnd, piInnerLineEnd]) then S := S + Lex.Token; if fLevel <> origLevel then raise EPreprocessorException.Create(sUnmatchedDirective, lineNo); if (S <> '') and bProcess then AddOneOrMoreLines(OutStrings, S, name, lineNo); finally Lex.Free; end; end; constructor TLangPreprocessor.Create(GLType : TGenLexerClass; const defIncDir : string; aLN : TLangName; MaxDepth : word); begin inherited Create; fLangName := aLN; fAddPoundLine := False; fGLC := GLType; fWarnings := TStringList.Create; IncludeDirs := TStringList.Create; IncludeDirs.Duplicates := dupIgnore; IncludeDirs.Sorted := True; IncludeDirs.Delimiter := ';'; IncludeDirs.Add(IncludeTrailingPathDelimiter(defIncDir)); MacroDefs := TMapList.Create; MacroFuncArgs := TMapList.Create; fLevelIgnore := TObjectList.Create; fIncludeFilesToSkip := TStringList.Create; with TStringList(fIncludeFilesToSkip) do begin Sorted := True; Duplicates := dupIgnore; end; fCalc := TNBCExpParser.Create(nil); fCalc.CaseSensitive := True; fCalc.StandardDefines := True; fCalc.ExtraDefines := True; fLexers := TObjectList.Create; InitializeLexers(MaxDepth); // fCalc.OnParserError := HandleCalcParserError; // fVarI := 0; // fVarJ := 0; // LoadStandardMacros; end; destructor TLangPreprocessor.Destroy; begin IncludeDirs.Clear; MacroDefs.Clear; MacroFuncArgs.Clear; FreeAndNil(IncludeDirs); FreeAndNil(MacroDefs); FreeAndNil(MacroFuncArgs); FreeAndNil(fLevelIgnore); FreeAndNil(fIncludeFilesToSkip); FreeAndNil(fCalc); FreeAndNil(fLexers); FreeAndNil(fWarnings); inherited; end; procedure TLangPreprocessor.AddIncludeDirs(aStrings: TStrings); var i : integer; begin for i := 0 to aStrings.Count - 1 do IncludeDirs.Add(IncludeTrailingPathDelimiter(aStrings[i])); end; function TLangPreprocessor.GenLexerType: TGenLexerClass; begin Result := fGLC; end; function TLangPreprocessor.EvaluateIdentifier(const ident: string): string; begin Result := ident; // try to evaluate Result fCalc.SilentExpression := Result; if not fCalc.ParserError then begin Result := NBCFloatToStr(fCalc.Value); end; end; function TLangPreprocessor.GetDefines: TMapList; begin Result := MacroDefs; end; function TLangPreprocessor.EvaluateExpression(expr: string; lineno : integer): boolean; begin // try to evaluate Result while Pos(' ', expr) > 0 do expr := Replace(expr, ' ', ''); fCalc.SilentExpression := expr; if not fCalc.ParserError then begin Result := fCalc.Value <> 0; end else raise EPreprocessorException.Create(Format(sInvalidPreprocExpression, [fCalc.ErrorMessage]), lineno); end; function TLangPreprocessor.ProcessDefinedFunction(expr: string): string; var p : integer; first, ident, last, delim : string; begin Result := Trim(expr); p := Pos('defined', Result); while p <> 0 do begin // replace defined(xxx) or defined xxx with 0 or 1 first := Copy(Result, 1, p-1); System.Delete(Result, 1, p+6); Result := Trim(Result); // remove any initial or trailing whitespace delim := ' '; if Pos('(', Result) = 1 then begin System.Delete(Result, 1, 1); delim := ')'; end; // grab the identifier p := Pos(delim, Result); if p = 0 then p := Length(Result)+1; ident := Trim(Copy(Result, 1, p-1)); System.Delete(Result, 1, p); last := Result; // is ident defined? Result := Format('%s %d %s', [first, Ord(MacroDefs.IndexOf(ident) <> -1), last]); p := Pos('defined', Result); end; end; procedure TLangPreprocessor.SkipIncludeFile(const fname: string); begin fIncludeFilesToSkip.Add(fname); end; function TLangPreprocessor.AcquireLexer(const lineNo : integer): TGenLexer; begin if fRecursionDepth < fLexers.Count then begin Result := TGenLexer(fLexers[fRecursionDepth]); inc(fRecursionDepth); end else raise EPreprocessorException.Create(Format(sMaxRecursionDepthError, [fLexers.Count]), lineNo); end; procedure TLangPreprocessor.ReleaseLexer; begin dec(fRecursionDepth); end; procedure TLangPreprocessor.InitializeLexers(const num: integer); var i : integer; begin for i := 0 to num - 1 do fLexers.Add(fGLC.CreateLexer); end; function TLangPreprocessor.ImportRIC(const fname, varname: string): string; var RC : TRICComp; begin RC := TRICComp.Create; try RC.LoadFromFile(fname); Result := RC.SaveAsDataArray(fLangName, varname); finally RC.Free; end; end; function TLangPreprocessor.ImportFile(const fname : string; varname: string): string; var tmp : string; i, cnt : integer; Data : TMemoryStream; P : PChar; begin if fLangName in [lnNBC, lnNXC] then begin if varname = '' then varname := ChangeFileExt(ExtractFileName(fname),'') else varname := Format(varname, [ChangeFileExt(ExtractFileName(fname),'')]); Data := TMemoryStream.Create; try Data.LoadFromFile(fname); Data.Position := 0; tmp := ''; P := Data.Memory; cnt := Integer(Data.Size) - 1; for i := 0 to cnt do begin tmp := tmp + Format('0x%2.2x', [Byte(P^)]); if i < cnt then tmp := tmp + ', '; inc(P); end; if fLangName = lnNXC then begin Result := 'byte ' + varname + '[] = {' + tmp + '};'; end else if fLangName = lnNBC then begin Result := 'dseg segment'#13#10 + ' ' + varname + ' byte[] ' + tmp + #13#10 + 'dseg ends'; end; finally Data.Free; end; end else Result := '// unable to import "' + ExtractFileName(fname) + '"'; end; function TLangPreprocessor.GetPreprocPath(const fname, path: string): string; begin Result := IncludeTrailingPathDelimiter(path); // if the path is relative then prepend it with the path from the file if Pos('.', Result) = 1 then Result := ExtractFilePath(fname) + Result else if Pos(PathDelim, Result) = 1 then Result := ExtractFileDrive(fname) + Result; end; procedure TLangPreprocessor.DoPreprocessorStatusChange(const Status: string); begin if Assigned(fOnPreprocessorStatusChange) then fOnPreprocessorStatusChange(Self, Status); end; { EPreprocessorException } constructor EPreprocessorException.Create(const msg: string; const lineno: integer); begin inherited Create(msg); fLineNo := lineno; end; { TMapList } type TStrObj = class(TObject) public Value : string; end; function TMapList.AddEntry(const aName, aValue: string): integer; var obj : TStrObj; begin Result := IndexOf(aName); if Result = -1 then begin obj := TStrObj.Create; Result := AddObject(aName, obj); obj.Value := aValue; end; end; procedure TMapList.Clear; var i : integer; begin for i := 0 to Count - 1 do Objects[i].Free; inherited; end; constructor TMapList.Create; begin inherited; CaseSensitive := True; ConsiderCase := True; Sorted := True; Duplicates := dupIgnore; end; procedure TMapList.Delete(Index: Integer); begin Objects[Index].Free; Objects[Index] := nil; inherited; end; function TMapList.GetMapValue(index: integer): string; begin Result := TStrObj(Objects[index]).Value; end; procedure TMapList.SetMapValue(index: integer; const Value: string); begin TStrObj(Objects[index]).Value := Value; end; procedure TMapList.SetConsiderCase(const AValue: boolean); begin if fConsiderCase=AValue then exit; fConsiderCase:=AValue; if Sorted then Sort; end; {$IFDEF FPC} function TMapList.DoCompareText(const s1, s2: string): PtrInt; begin if CaseSensitive or ConsiderCase then result := AnsiCompareStr(s1,s2) else result := AnsiCompareText(s1,s2); end; {$ENDIF} procedure TMapList.AddDefines(aValue: TStrings); var i : integer; begin for i := 0 to aValue.Count - 1 do AddEntry(aValue.Names[i], aValue.ValueFromIndex[i]); end; procedure TMapList.Define(const aName: string); begin AddEntry(aName, '1'); end; { TPreprocLevel } constructor TPreprocLevel.Create; begin Taken := False; Ignore := False; end; { TProcessLevel } constructor TProcessLevel.Create; begin inherited; Ignore := False; Taken := True; end; { TIgnoreLevel } constructor TIgnoreLevel.Create; begin inherited; Ignore := True; end; end. NXT/nbc.cfg0000644000175000017500000000106711537752673012356 0ustar slavkoslavko-$A8 -$B- -$C+ -$D+ -$E- -$F- -$G+ -$H+ -$I+ -$J- -$K- -$L+ -$M- -$N+ -$O+ -$P+ -$Q- -$R- -$S- -$T- -$U- -$V+ -$W- -$X+ -$YD -$Z1 -cc -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -H+ -W+ -M -$M16384,1048576 -K$00400000 -LE"c:\win32apps\borland\delphi7\Projects\Bpl" -LN"c:\win32apps\borland\delphi7\Projects\Bpl" -U"..;..\bricktools;..\png" -O"..;..\bricktools;..\png" -I"..;..\bricktools;..\png" -R"..;..\bricktools;..\png" -DFAST_MM, CAN_DOWNLOAD -w-UNSAFE_TYPE -w-UNSAFE_CODE -w-UNSAFE_CAST NXT/nbc.dof0000644000175000017500000000605411537752673012370 0ustar slavkoslavko[FileVersion] Version=7.0 [Compiler] A=8 B=0 C=1 D=1 E=0 F=0 G=1 H=1 I=1 J=0 K=0 L=1 M=0 N=1 O=1 P=1 Q=0 R=0 S=0 T=0 U=0 V=1 W=0 X=1 Y=1 Z=1 ShowHints=1 ShowWarnings=1 UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; NamespacePrefix= SymbolDeprecated=1 SymbolLibrary=1 SymbolPlatform=1 UnitLibrary=1 UnitPlatform=1 UnitDeprecated=1 HResultCompat=1 HidingMember=1 HiddenVirtual=1 Garbage=1 BoundsError=1 ZeroNilCompat=1 StringConstTruncated=1 ForLoopVarVarPar=1 TypedConstVarPar=1 AsgToTypedConst=1 CaseLabelRange=1 ForVariable=1 ConstructingAbstract=1 ComparisonFalse=1 ComparisonTrue=1 ComparingSignedUnsigned=1 CombiningSignedUnsigned=1 UnsupportedConstruct=1 FileOpen=1 FileOpenUnitSrc=1 BadGlobalSymbol=1 DuplicateConstructorDestructor=1 InvalidDirective=1 PackageNoLink=1 PackageThreadVar=1 ImplicitImport=1 HPPEMITIgnored=1 NoRetVal=1 UseBeforeDef=1 ForLoopVarUndef=1 UnitNameMismatch=1 NoCFGFileFound=1 MessageDirective=1 ImplicitVariants=1 UnicodeToLocale=1 LocaleToUnicode=1 ImagebaseMultiple=1 SuspiciousTypecast=1 PrivatePropAccessor=1 UnsafeType=0 UnsafeCode=0 UnsafeCast=0 [Linker] MapFile=0 OutputObjs=0 ConsoleApp=0 DebugInfo=0 RemoteSymbols=0 MinStackSize=16384 MaxStackSize=1048576 ImageBase=4194304 ExeDescription= [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath=..;..\bricktools;..\png Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;vcldb;soaprtl;VclSmp;inetdb;bdertl;vcldbx;adortl;vclactnband;SynEdit_D7;BricxCCSyn_D7;M103_r70;S201DR70;cxExportVCLD7;vcl7cr10;TCSComp_65 Conditionals=FAST_MM, CAN_DOWNLOAD DebugSourceDirs=d:\nxt\nxt\BricxCC\source\bricktools\;d:\nxt\nxt\BricxCC\source\ UsePackages=0 [Parameters] RunParams=test.nxc HostApplication= Launcher= UseLauncher=0 DebugCWD= [Language] ActiveLang= ProjectLang=$00000409 RootDir= [Version Info] IncludeVerInfo=1 AutoIncBuild=0 MajorVer=1 MinorVer=2 Release=1 Build=4 Debug=0 PreRelease=0 Special=0 Private=0 DLL=0 Locale=1033 CodePage=1252 [Version Info Keys] CompanyName=JoCar Consulting FileDescription=Next Byte Codes Compiler FileVersion=1.2.1.r4 InternalName=NBC LegalCopyright=Copyright (c) 2006-2010, John Hansen LegalTrademarks= OriginalFilename= ProductName=Next Byte Codes Compiler ProductVersion=1.2 Comments= [HistoryLists\hlDebugSourcePath] Count=3 Item0=d:\nxt\nxt\BricxCC\source\bricktools\;d:\nxt\nxt\BricxCC\source\ Item1=E:\nxt\BricxCC\source\bricktools\;E:\nxt\BricxCC\source\ Item2=E:\nxt\BricxCC\source\bricktools\ [HistoryLists\hlConditionals] Count=3 Item0=FAST_MM, CAN_DOWNLOAD Item1=FAST_MM Item2=FAST_MM, WITHTINY [HistoryLists\hlUnitAliases] Count=1 Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; [HistoryLists\hlSearchPath] Count=4 Item0=..;..\bricktools;..\png Item1=..;..\bricktools Item2=..;..\bricktool Item3=.. [HistoryLists\hlBPLOutput] Count=1 Item0=.. [HistoryLists\hlDCPOutput] Count=1 Item0=.. NXT/nbc.dpr0000644000175000017500000001735411537752673012412 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) program nbc; {$APPTYPE CONSOLE} uses {$IFNDEF FPC} FastMM4 in '..\FastMM4.pas', FastMM4Messages in '..\FastMM4Messages.pas', FastMove in '..\FastMove.pas', {$ENDIF} {$IFDEF CAN_DOWNLOAD} uGlobals in '..\uGlobals.pas', FantomSpirit in '..\bricktools\FantomSpirit.pas', {$ENDIF} Classes, SysUtils, uCmdLineUtils in '..\uCmdLineUtils.pas', uLocalizedStrings in '..\uLocalizedStrings.pas', ParamUtils in '..\ParamUtils.pas', uVersionInfo in '..\uVersionInfo.pas', mwGenericLex in '..\mwGenericLex.pas', uCommonUtils in '..\uCommonUtils.pas', uGenLexer in '..\uGenLexer.pas', uNBCLexer in '..\uNBCLexer.pas', uNXCLexer in '..\uNXCLexer.pas', uNBCInterface in 'uNBCInterface.pas', uNXTClasses in 'uNXTClasses.pas', uRICComp in 'uRICComp.pas', uRPGComp in 'uRPGComp.pas', uNXCComp in 'uNXCComp.pas', Parser10 in 'Parser10.pas'; {$IFNDEF FPC} {$R *.RES} {$ENDIF} {$I nbc_preproc.inc} procedure PrintUsage; begin PrintVersion(COMPILATION_TIMESTAMP); WriteLn(Format(UsageSyntax, [progName])); WriteLn(''); // WriteLn(' -T=: target must be NXT (optional)'); {$IFDEF CAN_DOWNLOAD} WriteLn(UsagePort); Writeln(UsageDownload); Writeln(UsageRunProg); Writeln(UsageBinary); Writeln(UsageQuiet); {$ENDIF} Writeln(UsageNoSystem); Writeln(UsageDefine); // Writeln(' -U=: undefine macro '); Writeln(UsageDecompile); Writeln(UsageOptimize); Writeln(UsageMaxErrors); Writeln(UsageMaxDepth); Writeln(UsageOutput); Writeln(UsageErrors); Writeln(UsageIncludes); Writeln(UsageNBCOutput); Writeln(UsageListing); Writeln(UsageSymbols); Writeln(UsageWarnings); Writeln(UsageStatusMsg); Writeln(UsageEnhanced); Writeln(UsageSafecall); Writeln(UsageAPI); Writeln(UsageFirmVer); Writeln(UsageHelp); // compiler also takes an undocumented "nxt name" parameter which is // used to tell the compiler what the downloaded program should be called // on the NXT: -N= end; type TStatusChangeHandler = class public procedure HandleCompilerStatusChange(Sender : TObject; const StatusMsg : string; const bDone : boolean); end; var C : TNBCCompiler; F : TextFile; i : integer; Filename : string; TheErrorCode : integer; SCH : TStatusChangeHandler; gNoStatusMessages : Boolean; procedure HandleWriteMessages(aStrings : TStrings); var i : integer; begin // write compiler messages to output if redirectErrorsToFile then begin for i := 0 to aStrings.Count - 1 do WriteLn(F, aStrings[i]); end else begin for i := 0 to aStrings.Count - 1 do WriteLn(ErrOutput, aStrings[i]); end; end; { TStatusChangeHandler } procedure TStatusChangeHandler.HandleCompilerStatusChange(Sender: TObject; const StatusMsg: string; const bDone : boolean); var msg : string; begin if gNoStatusMessages then Exit; msg := '# Status: ' + StatusMsg; WriteLn(Output, msg); end; begin TheErrorCode := 0; SCH := TStatusChangeHandler.Create; try if ParamSwitch('-help', False) then begin PrintUsage; Exit; end; if ParamCount = 0 then begin PrintUsageError(COMPILATION_TIMESTAMP); TheErrorCode := 1; Exit; end; {$IFDEF CAN_DOWNLOAD} if ParamSwitch('/UserPath', False) then UserDataLocalPath := IncludeTrailingPathDelimiter(ParamValue('/UserPath', False)); {$ENDIF} Filename := getFilenameParam(); if (Trim(Filename) = '') and not ParamSwitch('-api', False) then begin PrintUsageError(COMPILATION_TIMESTAMP); TheErrorCode := 1; Exit; end; try C := TNBCCompiler.Create; try LoadParamDefinitions(C.ExtraDefines); C.OnCompilerStatusChange := SCH.HandleCompilerStatusChange; C.OnWriteMessages := HandleWriteMessages; C.InputFilename := Filename; C.DefaultIncludeDir := DEFAULT_INCLUDE_DIR; C.IgnoreSystemFile := ParamSwitch('-n', False); C.Quiet := ParamSwitch('-q', False); C.MaxErrors := ParamIntValue('-ER', 0, False); C.MaxPreprocessorDepth := ParamIntValue('-PD', 10, False); C.FirmwareVersion := ParamIntValue('-v', 128, False); C.WriteCompilerOutput := ParamSwitch('-L', False); C.CompilerOutputFilename := ParamValue('-L', False); C.WriteSymbolTable := ParamSwitch('-Y', False); C.SymbolTableFilename := ParamValue('-Y', False); C.WriteIntermediateCode := ParamSwitch('-nbc', False); C.IntermediateCodeFilename := ParamValue('-nbc', False); C.WriteOutput := ParamSwitch('-O', False); C.OutputFilename := ParamValue('-O', False); C.UseSpecialName := ParamSwitch('-N', False); C.SpecialName := ParamValue('-N', False); C.OptimizationLevel := 1; if ParamSwitch('-Z', False) then C.OptimizationLevel := 2 else if ParamSwitch('-Z6', False) then C.OptimizationLevel := 6 else if ParamSwitch('-Z5', False) then C.OptimizationLevel := 5 else if ParamSwitch('-Z4', False) then C.OptimizationLevel := 4 else if ParamSwitch('-Z3', False) then C.OptimizationLevel := 3 else if ParamSwitch('-Z2', False) then C.OptimizationLevel := 2 else if ParamSwitch('-Z1', False) then C.OptimizationLevel := 1 else if ParamSwitch('-Z0', False) then C.OptimizationLevel := 0; C.UsePort := ParamSwitch('-S', False); C.PortName := ParamValue('-S', False); C.BinaryInput := ParamSwitch('-b', False); C.Download := ParamSwitch('-d', False) or ParamSwitch('-r', False); C.RunProgram := ParamSwitch('-r', False); C.MoreIncludes := ParamSwitch('-I', False); C.IncludePaths := ParamValue('-I', False); C.WarningsAreOff := ParamSwitch('-w-', False); C.EnhancedFirmware := ParamSwitch('-EF', False); C.SafeCalls := ParamSwitch('-safecall', False); C.WriteCompilerMessages := ParamSwitch('-E', False); C.CompilerMessagesFilename := ParamValue('-E', False); gNoStatusMessages := ParamSwitch('-sm-', False); if Filename <> '' then begin if ParamSwitch('-x', False) then begin C.Decompile; for i := 0 to C.Decompilation.Count - 1 do WriteLn(C.Decompilation[i]); end else begin setErrorOutputFile(F); try TheErrorCode := C.Execute; finally CloseFile(F); end; end; end; if ParamSwitch('-api', False) then C.DumpAPI(ParamIntValue('-api', 0, False)); finally C.Free; end; except TheErrorCode := 1; end; finally SCH.Free; if TheErrorCode <> 0 then Halt(TheErrorCode); end; end. NXT/nbc.res0000644000175000017500000000331011537752673012401 0ustar slavkoslavko ÿÿÿÿè ÿÿÿÿ ( @€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ3w;pp»€p°pp3p;ppp»€°ppp3p;pp»€°ppw3p€3;p3»€€»»°pp °3p€3;ppp3»€€»»°pp °p€3ppwp3‡€»»ww °€€3wp3€€»» °€€33€€»» °ÿÿ3ÿÿÿ!ÿÿÿÿÿûÿó?ÿòÿðÿ°ÿ0ÿ ÿûóòð°90 Ÿÿÿÿ€9ÿÀÿàÿðÿøŸÿüÿÿþÿÿÿÿÿÿ¹ÿÿ0ÿÿMAINICON  è< ÿÿÿÿ <4VS_VERSION_INFO½ïþ?šStringFileInfov040904E4BCompanyNameJoCar ConsultingZFileDescriptionNext Byte Codes Compiler2 FileVersion1.2.1.r4(InternalNameNBCn%LegalCopyrightCopyright (c) 2006-2010, John Hansen*LegalTrademarks*OriginalFilenameRProductNameNext Byte Codes Compiler,ProductVersion1.2CommentsDVarFileInfo$Translation äNXT/P10Build.pas0000644000175000017500000034557011537752673013172 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit P10Build; {$H+,S-} { long strings, no stack-checking} {.$DEFINE DEBUG} { by default make it lean and efficient } {$IFNDEF DEBUG} {$D-} {$L-} {$Q-} {$R-} {$S-} {$ENDIF} {$I+} { I/O checking ON } interface uses Parser10, SysUtils, Classes; procedure ParseFunction( FunctionString: string; { the unparsed string } Variables: TStringlist; { list of variables } { lists of available functions } FunctionOne, { functions with ONE argument, e.g. exp() } FunctionTwo: TStringList; { functions with TWO arguments, e.g. max(,) } UsePascalNumbers: boolean; { true: -> Val; false: NBCStrToFloat } CaseSensitive: boolean; { return pointer to tree, number of performed operations and error state } var FirstOP : PExpOperation; var Error : boolean); { error actually is superfluous as we are now using exceptions } implementation uses uNBCCommon; resourcestring msgErrBlanks = 'Expression has blanks'; msgMissingBrackets = 'Missing brackets in expression'; msgParseError = 'Error parsing expression:'; msgNestings = 'Expression contains too many nestings'; msgTooComplex = 'Expression is too complex'; msgInternalError = 'TParser internal error'; const TokenOperators = [ sum, diff, prod, divis, modulo, IntDiv, bitand, bitor, bitxor, sleft, sright, logand, logor, lessthan,lessoreq, greaterthan,greateroreq, equalto,notequalto, integerpower, realpower]; type TermString = string; procedure ParseFunction( FunctionString: string; Variables: TStringList; FunctionOne, FunctionTwo: TStringList; UsePascalNumbers: boolean; CaseSensitive: boolean; var FirstOP: PExpOperation; var Error: boolean); function CheckNumberBrackets(const s: string): boolean; forward; { checks whether number of ( = number of ) } function CheckNumber(const s: string; var FloatNumber: ParserFloat): boolean; forward; { checks whether s is a number } function CheckVariable(const s: string; var VariableID: integer): boolean; forward; { checks whether s is a variable string } function CheckTerm(var s1: string): boolean; forward; { checks whether s is a valid term } function CheckBracket(const s: string; var s1: string): boolean; forward; { checks whether s =(...(s1)...) and s1 is a valid term } function CheckNegate(const s: string; var s1: string): boolean; forward; {checks whether s denotes the negative value of a valid operation} function CheckBitNot(const s: string; var s1: string): boolean; forward; {checks whether ~ is the primary operation in s} function CheckLogicalNot(const s: string; var s1: string): boolean; forward; {checks whether ! is the primary operation in s} function CheckAdd(const s: string; var s1, s2: string): boolean; forward; {checks whether + is the primary operation in s} function CheckSubtract(const s: string; var s1, s2: string): boolean; forward; {checks whether - is the primary operation in s} function CheckMultiply(const s: string; var s1, s2: string): boolean; forward; {checks whether * is the primary operation in s} function CheckIntegerDiv(const s: string; var s1, s2: string): boolean; forward; {checks whether DIV is the primary TOperation in s} function CheckModulo(const s: string; var s1, s2: string): boolean; forward; {checks whether MOD is the primary TOperation in s} function CheckLogicalAnd(const s: string; var s1, s2: string): boolean; forward; {checks whether && is the primary TOperation in s} function CheckLogicalOr(const s: string; var s1, s2: string): boolean; forward; {checks whether || is the primary TOperation in s} function CheckBitAnd(const s: string; var s1, s2: string): boolean; forward; {checks whether & is the primary TOperation in s} function CheckBitOr(const s: string; var s1, s2: string): boolean; forward; {checks whether | is the primary TOperation in s} function CheckBitXor(const s: string; var s1, s2: string): boolean; forward; {checks whether ^ is the primary TOperation in s} function CheckEqualTo(const s: string; var s1, s2: string): boolean; forward; {checks whether == is the primary TOperation in s} function CheckNotEqualTo(const s: string; var s1, s2: string): boolean; forward; {checks whether != is the primary TOperation in s} function CheckLessThan(const s: string; var s1, s2: string): boolean; forward; {checks whether < is the primary TOperation in s} function CheckLessOrEqual(const s: string; var s1, s2: string): boolean; forward; {checks whether <= is the primary TOperation in s} function CheckGreaterThan(const s: string; var s1, s2: string): boolean; forward; {checks whether > is the primary TOperation in s} function CheckGreaterOrEqual(const s: string; var s1, s2: string): boolean; forward; {checks whether >= is the primary TOperation in s} function CheckShiftLeft(const s: string; var s1, s2: string): boolean; forward; {checks whether << is the primary TOperation in s} function CheckShiftRight(const s: string; var s1, s2: string): boolean; forward; {checks whether >> is the primary TOperation in s} function CheckRealDivision(const s: string; var s1, s2: string): boolean; forward; {checks whether / is the primary operation in s} function CheckFuncTwoVar(const s: string; var s1, s2: string): boolean; forward; {checks whether s=f(s1,s2); s1,s2 being valid terms} function CheckFuncOneVar(const s: string; var s1: string): boolean; forward; {checks whether s denotes the evaluation of a function fsort(s1)} function CheckPower(const s: string; var s1, s2: string; var AToken: TToken): boolean; forward; {checks whether ` is the primary operation in s} function CheckNumberBrackets(const s: string):boolean; {checks whether # of '(' equ. # of ')'} var counter, bracket : integer; begin bracket := 0; counter := length(s); while counter <> 0 do begin case s[counter] of '(': inc(bracket); ')': dec(bracket); end; dec(counter); end; Result := bracket = 0; end; function CheckNumber(const s: string; var FloatNumber: ParserFloat):boolean; {checks whether s is a number} var code: integer; tmpInt : Cardinal; // handle large hexadecimal strings (always a positive value) {$IFDEF Debug} { prevent debugger from showing conversion errors } SaveClass : TClass; {$ENDIF} begin if s = 'PI' then begin FloatNumber := Pi; Result := true; end else if s = '-PI' then begin FloatNumber := -Pi; Result := true; end else begin if UsePascalNumbers then begin code := 0; val(s, FloatNumber, code); Result := code = 0; // if this failed try an integer variable (handles hex notation) if not Result then begin val(s, tmpInt, code); Result := code = 0; if Result then FloatNumber := tmpInt; end; end else begin {$IFDEF Debug} SaveClass := ExceptionClass; ExceptionClass := nil; try {$ENDIF} try FloatNumber := NBCStrToFloatDef(s, 0); if (FloatNumber = 0) and (s <> '0') then begin // if this failed try an integer variable (handles hex notation) if Pos('0x', s) = 1 then begin val(s, tmpInt, code); Result := code = 0; if Result then FloatNumber := tmpInt; end else begin FloatNumber := NBCStrToFloat(s); Result := true; end; end else Result := true; except on E: Exception do begin Result := false; end; end; {$IFDEF Debug} finally ExceptionClass := SaveClass; end; {$ENDIF} end; end; end; function CheckVariable(const s: string; var VariableID: integer): boolean; {checks whether s is a variable string} begin Result := Variables.Find(s, VariableID); end; function CheckTerm(var s1: string) :boolean; { checks whether s is a valid term } var s2, s3: TermString; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; if length(s1) = 0 then exit; s2 := ''; s3 := ''; FloatNumber := 0; VariableID := 0; fsort := constant; if CheckNumber(s1, FloatNumber) or CheckVariable(s1, VariableID) or CheckNegate(s1, s2) or CheckBitNot(s1, s2) or CheckLogicalNot(s1, s2) or CheckLogicalOr(s1, s2, s3) or CheckLogicalAnd(s1, s2, s3) or CheckBitOr(s1, s2, s3) or CheckBitXor(s1, s2, s3) or CheckBitAnd(s1, s2, s3) or CheckEqualTo(s1, s2, s3) or CheckNotEqualTo(s1, s2, s3) or CheckLessThan(s1, s2, s3) or CheckLessOrEqual(s1, s2, s3) or CheckGreaterThan(s1, s2, s3) or CheckGreaterOrEqual(s1, s2, s3) or CheckShiftLeft(s1, s2, s3) or CheckShiftRight(s1, s2, s3) or CheckAdd(s1, s2, s3) or CheckSubtract(s1, s2, s3) or CheckMultiply(s1, s2, s3) or CheckIntegerDiv(s1, s2, s3) or CheckModulo(s1, s2, s3) or CheckRealDivision(s1, s2, s3) or CheckPower(s1, s2, s3, fsort) or CheckFuncTwoVar(s1, s2, s3) or CheckFuncOneVar(s1, s2) then Result := true else if CheckBracket(s1, s2) then begin s1 := s2; Result := true end; end; function CheckBracket(const s: string; var s1: string): boolean; {checks whether s =(...(s1)...) and s1 is a valid term} var SLen : integer; begin Result := false; SLen := Length(s); if (SLen > 0) and (s[SLen] = ')') and (s[1] = '(') then begin s1 := copy(s, 2, SLen-2); Result := CheckTerm(s1); end; end; function CheckNegate(const s: string; var s1: string) :boolean; {checks whether s denotes the negative value of a valid TOperation} var s2, s3: TermString; fsort: TToken; VariableID: integer; begin Result := false; if (length(s) <> 0) and (s[1] = '-') then begin s1 := copy(s, 2, length(s)-1); s2 := ''; if CheckBracket(s1, s2) then begin s1 := s2; Result := true; end else begin VariableID := 0; fsort := constant; s3 := ''; Result := CheckVariable(s1, VariableID) or CheckPower(s1, s2, s3, fsort) or CheckFuncOneVar(s1, s2) or CheckFuncTwoVar(s1, s2, s3); end; end; end; function CheckBitNot(const s: string; var s1: string) :boolean; {checks whether '~' is the primary TOperation in s} var s2, s3: TermString; fsort: TToken; VariableID: integer; FloatNumber: ParserFloat; begin Result := false; if (length(s) <> 0) and (s[1] = '~') then begin s1 := copy(s, 2, length(s)-1); VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s2 := ''; Result := CheckBracket(s1, s2); if Result then s1 := s2; end; if not Result then begin VariableID := 0; fsort := constant; s3 := ''; Result := CheckNegate(s1, s3) or CheckVariable(s1, VariableID) or CheckPower(s1, s2, s3, fsort) or CheckFuncOneVar(s1, s2) or CheckFuncTwoVar(s1, s2, s3); end; end; end; function CheckLogicalNot(const s: string; var s1: string) :boolean; {checks whether '!' is the primary TOperation in s} var s2, s3: TermString; fsort: TToken; VariableID: integer; FloatNumber: ParserFloat; begin Result := false; if (length(s) <> 0) and (s[1] = '!') then begin s1 := copy(s, 2, length(s)-1); VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s2 := ''; Result := CheckBracket(s1, s2); if Result then s1 := s2; end; if not Result then begin VariableID := 0; fsort := constant; s3 := ''; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckVariable(s1, VariableID) or CheckPower(s1, s2, s3, fsort) or CheckFuncOneVar(s1, s2) or CheckFuncTwoVar(s1, s2, s3); end; end; end; function CheckAdd(const s: string; var s1, s2: string): boolean; {checks whether '+' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '+' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckSubtract(const s: string; var s1, s2: string): boolean; {checks whether '-' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '-' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckMultiply(const s: string; var s1, s2: string): boolean; {checks whether '*' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '*' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckIntegerDiv(const s: string; var s1, s2: string): boolean; {checks whether 'div' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('div', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+3, length(s)-i-2); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2,VariableID) or CheckNumber(s2,FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or // CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckModulo(const s: string; var s1, s2: string): boolean; {checks whether 'MOD' ('%') is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; const // ModName = 'mod'; // ModLen = 3; ModName = '%'; ModLen = 1; begin Result := false; i := 0; repeat j := pos(ModName, copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+ModLen, length(s)-i-(ModLen-1)); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or // CheckIntegerDiv(s1, s3, s4) or // CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckModulo(s2, s3, s4) or // CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckLogicalOr(const s: string; var s1, s2: string): boolean; {checks whether '||' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('||', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckLogicalAnd(s1, s3, s4) or CheckBitOr(s1, s3, s4) or CheckBitXor(s1, s3, s4) or CheckBitAnd(s1, s3, s4) or CheckEqualTo(s1, s3, s4) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckLogicalOr(s2, s3, s4) or CheckLogicalAnd(s2, s3, s4) or CheckBitOr(s2, s3, s4) or CheckBitXor(s2, s3, s4) or CheckBitAnd(s2, s3, s4) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckLogicalAnd(const s: string; var s1, s2: string): boolean; {checks whether '&&' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('&&', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckBitOr(s1, s3, s4) or CheckBitXor(s1, s3, s4) or CheckBitAnd(s1, s3, s4) or CheckEqualTo(s1, s3, s4) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckLogicalAnd(s2, s3, s4) or CheckBitOr(s2, s3, s4) or CheckBitXor(s2, s3, s4) or CheckBitAnd(s2, s3, s4) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckBitAnd(const s: string; var s1, s2: string): boolean; {checks whether '&' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '&' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckEqualTo(s1, s3, s4) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckBitAnd(s2, s3, s4) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckBitOr(const s: string; var s1, s2: string): boolean; {checks whether '|' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '|' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckBitXor(s1, s3, s4) or CheckBitAnd(s1, s3, s4) or CheckEqualTo(s1, s3, s4) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckBitOr(s2, s3, s4) or CheckBitXor(s2, s3, s4) or CheckBitAnd(s2, s3, s4) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckBitXor(const s: string; var s1, s2: string): boolean; {checks whether '^' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '^' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckBitAnd(s1, s3, s4) or CheckEqualTo(s1, s3, s4) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckBitXor(s2, s3, s4) or CheckBitAnd(s2, s3, s4) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckEqualTo(const s: string; var s1, s2: string): boolean; {checks whether '==' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('==', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckNotEqualTo(s1, s3, s4) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckEqualTo(s2, s3, s4) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckNotEqualTo(const s: string; var s1, s2: string): boolean; {checks whether '!=' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('!=', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckLessThan(s1, s3, s4) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckNotEqualTo(s2, s3, s4) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckLessThan(const s: string; var s1, s2: string): boolean; {checks whether '<' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '<' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckLessOrEqual(s1, s3, s4) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckLessThan(s2, s3, s4) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckLessOrEqual(const s: string; var s1, s2: string): boolean; {checks whether '<=' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('<=', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckGreaterThan(s1, s3, s4) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckLessOrEqual(s2, s3, s4) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckGreaterThan(const s: string; var s1, s2: string): boolean; {checks whether '>' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; fsort: TToken; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '>' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckGreaterOrEqual(s1, s3, s4) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckGreaterThan(s2, s3, s4) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckGreaterOrEqual(const s: string; var s1, s2: string): boolean; {checks whether '>=' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('>=', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckShiftLeft(s1, s3, s4) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckGreaterOrEqual(s2, s3, s4) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckShiftLeft(const s: string; var s1, s2: string): boolean; {checks whether '<<' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('<<', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckShiftRight(s1, s3, s4) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckShiftLeft(s2, s3, s4) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckShiftRight(const s: string; var s1, s2: string): boolean; {checks whether '>>' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; repeat j := pos('>>', copy(s, i+1, length(s)-i)); if j > 0 then begin inc(i, j); if (i > 1) and (i < length(s)) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+2, length(s)-i-1); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckAdd(s1, s3, s4) or CheckSubtract(s1, s3, s4) or CheckMultiply(s1, s3, s4) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckShiftRight(s2, s3, s4) or CheckAdd(s2, s3, s4) or CheckSubtract(s2, s3, s4) or CheckMultiply(s2, s3, s4) or CheckIntegerDiv(s2, s3, s4) or CheckModulo(s2, s3, s4) or CheckRealDivision(s2, s3, s4) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end end; end; end; end; until Result or (j = 0) or (i >= length(s)); end; function CheckRealDivision(const s: string; var s1, s2: string): boolean; {checks whether '/' is the primary TOperation in s} var s3, s4: TermString; i, j: integer; VariableID: integer; FloatNumber: ParserFloat; fsort: TToken; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '/' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; fsort := constant; Result := CheckNegate(s1, s3) or CheckBitNot(s1, s3) or CheckLogicalNot(s1, s3) or CheckIntegerDiv(s1, s3, s4) or CheckModulo(s1, s3, s4) or CheckRealDivision(s1, s3, s4) or CheckPower(s1, s3, s4, fsort) or CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin Result := CheckVariable(s2, VariableID) or CheckNumber(s2, FloatNumber); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3 else Result := CheckNegate(s2, s3) or CheckBitNot(s2, s3) or CheckLogicalNot(s2, s3) or CheckPower(s2, s3, s4, fsort) or CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; end; end; end else break; until Result; end; function CheckFuncTwoVar(const s: string; var s1, s2: string): boolean; {checks whether s=f(s1,s2); s1,s2 being valid terms} function CheckComma(const s: string; var s1, s2: string): boolean; var i, j: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = ',' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); if CheckTerm(s1) then begin s2 := copy(s, i+1, j-i); Result := CheckTerm(s2); end; end else break; until Result; end; var SLen, counter : integer; begin Result := false; SLen := Pos('(', s); dec(SLen); if (SLen > 0) and (s[length(s)] = ')') then begin counter := 0; if FunctionTwo.Find(copy(s, 1, SLen), counter) then begin inc(SLen, 2); Result := CheckComma( copy(s, SLen, length(s)-SLen), s1, s2); end; end; end; function CheckFuncOneVar(const s: string; var s1: string): boolean; {checks whether s denotes the evaluation of a function fsort(s1)} var counter: integer; SLen: integer; begin Result := false; SLen := Pos('(', s); dec(SLen); if (SLen > 0) then begin counter := 0; if FunctionOne.Find(copy(s, 1, SLen), counter) then begin Result := CheckBracket(copy(s, SLen+1, length(s)-SLen), s1); end; end; end; function CheckPower(const s: string; var s1, s2: string; var AToken: TToken): boolean; var s3, s4: TermString; i, j: integer; FloatNumber: ParserFloat; VariableID: integer; begin Result := false; i := 0; j := length(s); repeat while i <> j do begin inc(i); if s[i] = '`' then break; end; if (i > 1) and (i < j) then begin s1 := copy(s, 1, i-1); s2 := copy(s, i+1, j-i); Result := CheckNumberBrackets(s1) and CheckNumberBrackets(s2); if Result then begin VariableID := 0; FloatNumber := 0; Result := CheckVariable(s1, VariableID) or CheckNumber(s1, FloatNumber); if not Result then begin s3 := ''; Result := CheckBracket(s1, s3); if Result then s1 := s3; end; if not Result then begin s4 := ''; Result := CheckFuncOneVar(s1, s3) or CheckFuncTwoVar(s1, s3, s4); end; if Result then begin if CheckNumber(s2, FloatNumber) then begin i := Integer(Trunc(FloatNumber)); if (i <> FloatNumber) then begin { this is a real number } AToken := realpower; end else begin case i of 2: AToken := square; 3: AToken := third; 4: AToken := fourth; else AToken := integerpower; end; end; end else begin Result := CheckVariable(s2, VariableID); if not Result then begin Result := CheckBracket(s2, s3); if Result then s2 := s3; end; if not Result then begin Result := CheckFuncOneVar(s2, s3) or CheckFuncTwoVar(s2, s3, s4); end; if Result then AToken := realPower; end; end; end; end else break; until Result; end; function CreateOperation(const Term: TToken; const Proc: Pointer): PExpOperation; begin new(Result); with Result^ do begin Arg1 := nil; Arg2 := nil; Dest := nil; NextOperation := nil; Token := Term; Operation := TMathProcedure(Proc); end; end; const BlankString = ' '; type PTermRecord = ^TermRecord; TermRecord = record { this usage of string is a bit inefficient, as in 16bit always 256 bytes are consumed. But since we a) are allocating memory dynamically and b) this will be released immediately when finished with parsing this seems to be OK One COULD create a "TermClass" where this is handled } StartString: string; LeftString, RightString: string; Token: TToken; Position: array[1..3] of integer; Next1, Next2, Previous: PTermRecord; end; const { side effect: for each bracketing level added SizeOf(integer) bytes additional stack usage maxLevelWidth*SizeOf(Pointer) additional global memory used } maxBracketLevels = 20; { side effect: for each additional (complexity) level width maxBracketLevels*SizeOf(Pointer) additional global memory used } maxLevelWidth = 50; type LevelArray = array[0..maxBracketLevels] of integer; OperationPointerArray = array[0..maxBracketLevels, 1..maxLevelWidth] of PExpOperation; POperationPointerArray = ^OperationPointerArray; var Matrix: POperationPointerArray; { bracket positions } CurrentBracket, i, CurBracketLevels: integer; BracketLevel: LevelArray; LastOP: PExpOperation; FloatNumber: ParserFloat; VariableID: integer; ANewTerm, { need this particlar pointer to guarantee a good, flawless memory cleanup in except } FirstTerm, Next1Term, Next2Term, LastTerm: PTermRecord; counter1, counter2: integer; begin { initialize local variables for safe checking in try..finally..end} { FirstTerm := nil; } { not necessary since not freed in finally } LastTerm := nil; ANewTerm := nil; Next1Term := nil; Next2Term := nil; Error := false; BracketLevel[0] := 0; FillChar(BracketLevel, SizeOf(BracketLevel), 0); { initialize bracket array } BracketLevel[0] := 1; CurBracketLevels := 0; new(Matrix); try { this block protects the whole of ALL assignments...} FillChar(Matrix^, SizeOf(Matrix^), 0); new(ANewTerm); with ANewTerm^ do begin if CaseSensitive then StartString := FunctionString else StartString := UpperCase(FunctionString); { remove leading and trailing spaces } counter1 := 1; counter2 := length(StartString); while counter1 <= counter2 do if StartString[counter1] <> ' ' then break else inc(counter1); counter2 := length(StartString); while counter2 > counter1 do if StartString[counter2] <> ' ' then break else dec(counter2); StartString := Copy(StartString, counter1, counter2 - counter1 + 1); if Pos(' ', StartString) > 0 then raise EExpressionHasBlanks.Create(msgErrBlanks); { Old code: StartString := RemoveBlanks(UpperCase(FunctionString)); ...do not use! Using it would create the following situation: Passed string: "e xp(12)" Modified string: "exp(12)" This MAY or may not be the desired meaning - there may well exist a variable "e" and a function "xp" and just the operator would be missing. Conclusion: the above line has the potential of changing the meaning of an expression. } if not CheckNumberBrackets(StartString) then raise EMissMatchingBracket.Create(msgMissingBrackets); { remove enclosing brackets, e.g. ((pi)) } while CheckBracket(StartString, FunctionString) do StartString := FunctionString; LeftString := BlankString; RightString := BlankString; Token := variab; Next1 := nil; Next2 := nil; Previous := nil; end; Matrix^[0,1] := CreateOperation(variab, nil); LastTerm := ANewTerm; FirstTerm := ANewTerm; ANewTerm := nil; with LastTerm^ do begin Position[1] := 0; Position[2] := 1; Position[3] := 1; end; repeat repeat with LastTerm^ do begin CurrentBracket := Position[1]; i := Position[2]; if Next1 = nil then begin VariableID := 0; if CheckVariable(StartString, VariableID) then begin Token := variab; if Position[3] = 1 then Matrix^[CurrentBracket, i]^.Arg1 := PParserFloat(Variables.Objects[VariableID]) else Matrix^[CurrentBracket, i]^.Arg2 := PParserFloat(Variables.Objects[VariableID]) end else begin FloatNumber := 0; if CheckNumber(StartString, FloatNumber) then begin Token := constant; if Position[3] = 1 then begin new(Matrix^[CurrentBracket, i]^.Arg1); Matrix^[CurrentBracket, i]^.Arg1^ := FloatNumber; end else begin new(Matrix^[CurrentBracket, i]^.Arg2); Matrix^[CurrentBracket, i]^.Arg2^ := FloatNumber; end; end else if CheckNegate(StartString, LeftString) then Token := minus else if CheckBitNot(StartString, LeftString) then Token := bitnot else if CheckLogicalNot(StartString, LeftString) then Token := lognot else if CheckLogicalOr(StartString, LeftString, RightString) then Token := logor else if CheckLogicalAnd(StartString, LeftString, RightString) then Token := logand else if CheckBitOr(StartString, LeftString, RightString) then Token := bitor else if CheckBitXor(StartString, LeftString, RightString) then Token := bitxor else if CheckBitAnd(StartString, LeftString, RightString) then Token := bitand else if CheckEqualTo(StartString, LeftString, RightString) then Token := equalto else if CheckNotEqualTo(StartString, LeftString, RightString) then Token := notequalto else if CheckLessThan(StartString, LeftString, RightString) then Token := lessthan else if CheckLessOrEqual(StartString, LeftString, RightString) then Token := lessoreq else if CheckGreaterThan(StartString, LeftString, RightString) then Token := greaterthan else if CheckGreaterOrEqual(StartString, LeftString, RightString) then Token := greateroreq else if CheckShiftLeft(StartString, LeftString, RightString) then Token := sleft else if CheckShiftRight(StartString, LeftString, RightString) then Token := sright else if CheckAdd(StartString, LeftString, RightString) then Token := sum else if CheckSubtract(StartString, LeftString, RightString) then Token := diff else if CheckMultiply(StartString, LeftString, RightString) then Token := prod else if CheckIntegerDiv(StartString, LeftString, RightString) then Token := IntDiv else if CheckModulo(StartString, LeftString, RightString) then Token := modulo else if CheckRealDivision(StartString, LeftString, RightString) then Token := divis else if not CheckPower(StartString, LeftString, RightString, Token) then begin if CheckFuncOneVar(StartString, LeftString) then Token := FuncOneVar else if CheckFuncTwoVar(StartString, LeftString, RightString) then Token := FuncTwoVar else begin Error := true; {with an exception raised this is meaningless...} if (LeftString = BlankString) and (RightString = BlankString) then raise ESyntaxError.CreateFmt(msgParseError+' %s', [StartString]) else raise ESyntaxError.CreateFmt(msgParseError+' %s | %s', [Leftstring, RightString]); end; end; end; end; end; { with LastTerm^ } if LastTerm^.Token in ( [minus, bitnot, lognot, square, third, fourth, FuncOneVar, FuncTwoVar] + TokenOperators) then begin if LastTerm^.Next1 = nil then begin try Next1Term := nil; new(Next1Term); inc(CurrentBracket); if CurrentBracket > maxBracketLevels then begin Error := true; raise ETooManyNestings.Create(msgNestings); end; if CurBracketLevels < CurrentBracket then CurBracketLevels := CurrentBracket; i := BracketLevel[CurrentBracket] + 1; if i > maxLevelWidth then begin Error := true; raise EExpressionTooComplex.Create(msgTooComplex); end; with Next1Term^ do begin StartString := LastTerm^.LeftString; LeftString := BlankString; RightString := BlankString; Position[1] := CurrentBracket; Position[2] := i; Position[3] := 1; Token := variab; Previous := LastTerm; Next1 := nil; Next2 := nil; end; with LastTerm^ do begin case Token of FuncOneVar: with FunctionOne do Matrix^[CurrentBracket, i] := CreateOperation( Token, Objects[IndexOf(copy(StartString, 1, pos('(', StartString)-1))] ); FuncTwoVar: with FunctionTwo do Matrix^[CurrentBracket, i] := CreateOperation( Token, Objects[IndexOf(copy(StartString, 1, pos('(', StartString)-1))] ); else Matrix^[CurrentBracket, i] := CreateOperation(Token, nil); end; new(Matrix^[CurrentBracket, i]^.Dest); Matrix^[CurrentBracket, i]^.Dest^ := 0; if Position[3] = 1 then Matrix^[Position[1], Position[2]]^.Arg1 := Matrix^[CurrentBracket, i]^.Dest else Matrix^[Position[1], Position[2]]^.Arg2 := Matrix^[CurrentBracket, i]^.Dest; Next1 := Next1Term; Next1Term := nil; end; if LastTerm^.Token in [minus, bitnot, lognot, square, third, fourth, FuncOneVar] then inc(BracketLevel[CurrentBracket]); except on E: Exception do begin if assigned(Next1Term) then begin dispose(Next1Term); Next1Term := nil; end; raise; end; end; end else begin if LastTerm^.Token in (TokenOperators + [FuncTwoVar]) then begin try Next2Term := nil; new(Next2Term); inc(CurrentBracket); if CurrentBracket > maxBracketLevels then begin Error := true; raise ETooManyNestings.Create(msgNestings); end; if CurBracketLevels < CurrentBracket then CurBracketLevels := CurrentBracket; i := BracketLevel[CurrentBracket] + 1; if i > maxLevelWidth then begin Error := true; raise EExpressionTooComplex.Create(msgTooComplex); end; with Next2Term^ do begin StartString := LastTerm^.RightString; LeftString := BlankString; RightString := BlankString; Token := variab; Position[1] := CurrentBracket; Position[2] := i; Position[3] := 2; Previous := LastTerm; Next1 := nil; Next2 := nil; end; LastTerm^.Next2 := Next2Term; Next2Term := nil; inc(BracketLevel[CurrentBracket]); except on E: Exception do begin if assigned(Next2Term) then begin dispose(Next2Term); Next2Term := nil; end; end; end; end else raise EParserInternalError.Create(msgInternalError); end; end; with LastTerm^ do if Next1 = nil then begin { we are done with THIS loop } break; end else if Next2 = nil then LastTerm := Next1 else LastTerm := Next2; until false; { endless loop, break'ed 7 lines above } if LastTerm = FirstTerm then begin dispose(LastTerm); FirstTerm := nil; break; { OK - that is it, we did not find any more terms} end; repeat with LastTerm^ do { cannot use "with LastTerm^" OUTSIDE loop } begin if Next1 <> nil then begin dispose(Next1); Next1 := nil; end; if Next2 <> nil then begin dispose(Next2); Next2 := nil; end; LastTerm := Previous; end; until ((LastTerm^.Token in (TokenOperators + [FuncTwoVar])) and (LastTerm^.Next2 = nil)) or (LastTerm = FirstTerm); with FirstTerm^ do if (LastTerm = FirstTerm) and ( (Token in [minus, bitnot, lognot, square, third, fourth, FuncOneVar]) or ((Token in (TokenOperators + [FuncTwoVar])) and Assigned(Next2)) ) then begin break; end; until false; { after having built the expression matrix, translate it into a tree/list } with FirstTerm^ do if FirstTerm <> nil then begin if Next1 <> nil then begin dispose(Next1); Next1 := nil; end; if Next2 <> nil then begin dispose(Next2); Next2 := nil; end; dispose(FirstTerm); end; BracketLevel[0] := 1; if CurBracketLevels = 0 then begin FirstOP := Matrix^[0,1]; Matrix^[0,1] := nil; FirstOP^.Dest := FirstOP^.Arg1; end else begin FirstOP := Matrix^[CurBracketLevels, 1]; LastOP := FirstOP; for counter2 := 2 to BracketLevel[CurBracketLevels] do begin LastOP^.NextOperation := Matrix^[CurBracketLevels, counter2]; LastOP := LastOP^.NextOperation; end; for counter1 := CurBracketLevels-1 downto 1 do for counter2 := 1 to BracketLevel[counter1] do begin LastOP^.NextOperation := Matrix^[counter1, counter2]; LastOP := LastOP^.NextOperation; end; with Matrix^[0,1]^ do begin Arg1 := nil; Arg2 := nil; Dest := nil; end; dispose(Matrix^[0,1]); end; dispose(Matrix); except on E: Exception do begin if Assigned(Matrix) then begin if assigned(Matrix^[0,1]) then dispose(Matrix^[0,1]); for counter1 := CurBracketLevels downto 1 do for counter2 := 1 to BracketLevel[counter1] do if Assigned(Matrix^[counter1, counter2]) then dispose(Matrix^[counter1, counter2]); dispose(Matrix); end; if Assigned(Next1Term) then dispose(Next1Term); if Assigned(Next2Term) then dispose(Next2Term); { do NOT kill this one at it is possibly the same as LastTerm (see below)! if Assigned(FirstTerm) then dispose(FirstTerm); instead, DO kill ANewTerm, which will only be <> nil if it has NOT passed its value to some other pointer already so it can safely be freed } if Assigned(ANewTerm) then dispose(ANewTerm); if Assigned(LastTerm) and (LastTerm <> Next2Term) and (LastTerm <> Next1Term) then dispose(LastTerm); FirstOP := nil; raise; { re-raise exception } end; { on E:Exception do } end; end; end. NXT/NXCDefs.h0000644000175000017500000235422211537752673012544 0ustar slavkoslavko/** \file NXCDefs.h * \brief Constants, macros, and API functions for NXC * * NXCDefs.h contains declarations for the NXC NXT API resources * * License: * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009-2010 John Hansen. * All Rights Reserved. * * ---------------------------------------------------------------------------- * * \author John Hansen (bricxcc_at_comcast.net) * \date 2011-03-15 * \version 93 */ #ifndef NXCDEFS_H #define NXCDEFS_H #include "NBCCommon.h" /** @addtogroup MiscConstants * @{ */ /** @defgroup TypeAliases Type aliases * Short type aliases indicating signed/unsigned and bit count for each type. * @{ */ #define u8 unsigned char /*!< Unsigned 8 bit type */ #define s8 char /*!< Signed 8 bit type */ #define u16 unsigned int /*!< Unsigned 16 bit type */ #define s16 int /*!< Signed 16 bit type */ #define u32 unsigned long /*!< Unsigned 32 bit type */ #define s32 long /*!< Signed 32 bit type */ /** @} */ // end of TypeAliases group /** @} */ // end of MiscConstants group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// INPUT MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup InputModule * @{ */ /** @addtogroup InputModuleConstants * @{ */ /** @defgroup InPorts Input port constants * Input port constants are used when calling NXC sensor control API functions. * @{ */ #define S1 0 /*!< Input port 1 */ #define S2 1 /*!< Input port 2 */ #define S3 2 /*!< Input port 3 */ #define S4 3 /*!< Input port 4 */ /** @} */ // end of InPorts group /** @addtogroup InputModuleTypesAndModes * @{ */ /** @defgroup SensorTypes Sensor type constants * Use sensor type constants to configure an input port for a specific type * of sensor. * \sa SetSensorType() * @{ */ #define SENSOR_TYPE_NONE IN_TYPE_NO_SENSOR /*!< No sensor configured */ #define SENSOR_TYPE_TOUCH IN_TYPE_SWITCH /*!< NXT or RCX touch sensor */ #define SENSOR_TYPE_TEMPERATURE IN_TYPE_TEMPERATURE /*!< RCX temperature sensor */ #define SENSOR_TYPE_LIGHT IN_TYPE_REFLECTION /*!< RCX light sensor */ #define SENSOR_TYPE_ROTATION IN_TYPE_ANGLE /*!< RCX rotation sensor */ #define SENSOR_TYPE_LIGHT_ACTIVE IN_TYPE_LIGHT_ACTIVE /*!< NXT light sensor with light */ #define SENSOR_TYPE_LIGHT_INACTIVE IN_TYPE_LIGHT_INACTIVE /*!< NXT light sensor without light */ #define SENSOR_TYPE_SOUND_DB IN_TYPE_SOUND_DB /*!< NXT sound sensor with dB scaling */ #define SENSOR_TYPE_SOUND_DBA IN_TYPE_SOUND_DBA /*!< NXT sound sensor with dBA scaling */ #define SENSOR_TYPE_CUSTOM IN_TYPE_CUSTOM /*!< NXT custom sensor */ #define SENSOR_TYPE_LOWSPEED IN_TYPE_LOWSPEED /*!< NXT I2C digital sensor */ #define SENSOR_TYPE_LOWSPEED_9V IN_TYPE_LOWSPEED_9V /*!< NXT I2C digital sensor with 9V power */ #define SENSOR_TYPE_HIGHSPEED IN_TYPE_HISPEED /*!< NXT Hi-speed port (only S4) */ #if __FIRMWARE_VERSION > 107 #define SENSOR_TYPE_COLORFULL IN_TYPE_COLORFULL /*!< NXT 2.0 color sensor in full color mode */ #define SENSOR_TYPE_COLORRED IN_TYPE_COLORRED /*!< NXT 2.0 color sensor with red light */ #define SENSOR_TYPE_COLORGREEN IN_TYPE_COLORGREEN /*!< NXT 2.0 color sensor with green light */ #define SENSOR_TYPE_COLORBLUE IN_TYPE_COLORBLUE /*!< NXT 2.0 color sensor with blue light */ #define SENSOR_TYPE_COLORNONE IN_TYPE_COLORNONE /*!< NXT 2.0 color sensor with no light */ #endif /** @} */ // end of SensorTypes group /** @defgroup SensorModes Sensor mode constants * Use sensor mode constants to configure an input port for the desired * sensor mode. * \sa SetSensorMode() * @{ */ #define SENSOR_MODE_RAW IN_MODE_RAW /*!< Raw value from 0 to 1023 */ #define SENSOR_MODE_BOOL IN_MODE_BOOLEAN /*!< Boolean value (0 or 1) */ #define SENSOR_MODE_EDGE IN_MODE_TRANSITIONCNT /*!< Counts the number of boolean transitions */ #define SENSOR_MODE_PULSE IN_MODE_PERIODCOUNTER /*!< Counts the number of boolean periods */ #define SENSOR_MODE_PERCENT IN_MODE_PCTFULLSCALE /*!< Scaled value from 0 to 100 */ #define SENSOR_MODE_CELSIUS IN_MODE_CELSIUS /*!< RCX temperature sensor value in degrees celcius */ #define SENSOR_MODE_FAHRENHEIT IN_MODE_FAHRENHEIT /*!< RCX temperature sensor value in degrees fahrenheit */ #define SENSOR_MODE_ROTATION IN_MODE_ANGLESTEP /*!< RCX rotation sensor (16 ticks per revolution) */ /** @} */ // end of SensorModes group /** @defgroup SensorTypeModes Combined sensor type and mode constants * Use the combined sensor type and mode constants to configure both * the sensor mode and type in a single function call. * \sa SetSensor() * @{ */ #define _SENSOR_CFG(_type,_mode) (((_type)<<8)+(_mode)) /*!< Macro for defining \ref SetSensor combined type and mode constants */ #define SENSOR_TOUCH _SENSOR_CFG(SENSOR_TYPE_TOUCH, SENSOR_MODE_BOOL) /*!< Touch sensor in boolean mode */ #define SENSOR_LIGHT _SENSOR_CFG(SENSOR_TYPE_LIGHT, SENSOR_MODE_PERCENT) /*!< RCX Light sensor in percent mode */ #define SENSOR_ROTATION _SENSOR_CFG(SENSOR_TYPE_ROTATION, SENSOR_MODE_ROTATION) /*!< RCX rotation sensor in rotation mode */ #define SENSOR_CELSIUS _SENSOR_CFG(SENSOR_TYPE_TEMPERATURE, SENSOR_MODE_CELSIUS) /*!< RCX temperature sensor in celcius mode */ #define SENSOR_FAHRENHEIT _SENSOR_CFG(SENSOR_TYPE_TEMPERATURE, SENSOR_MODE_FAHRENHEIT) /*!< RCX temperature sensor in fahrenheit mode */ #define SENSOR_PULSE _SENSOR_CFG(SENSOR_TYPE_TOUCH, SENSOR_MODE_PULSE) /*!< Touch sensor in pulse mode */ #define SENSOR_EDGE _SENSOR_CFG(SENSOR_TYPE_TOUCH, SENSOR_MODE_EDGE) /*!< Touch sensor in edge mode */ #define SENSOR_NXTLIGHT _SENSOR_CFG(SENSOR_TYPE_LIGHT_ACTIVE, SENSOR_MODE_PERCENT) /*!< NXT light sensor in active mode */ #define SENSOR_SOUND _SENSOR_CFG(SENSOR_TYPE_SOUND_DB, SENSOR_MODE_PERCENT) /*!< NXT sound sensor (dB) in percent mode */ #define SENSOR_LOWSPEED_9V _SENSOR_CFG(SENSOR_TYPE_LOWSPEED_9V, SENSOR_MODE_RAW) /*!< NXT I2C sensor with 9V power in raw mode */ #define SENSOR_LOWSPEED _SENSOR_CFG(SENSOR_TYPE_LOWSPEED, SENSOR_MODE_RAW) /*!< NXT I2C sensor without 9V power in raw mode */ #if __FIRMWARE_VERSION > 107 #define SENSOR_COLORFULL _SENSOR_CFG(SENSOR_TYPE_COLORFULL, SENSOR_MODE_RAW) /*!< NXT 2.0 color sensor (full) in raw mode */ #define SENSOR_COLORRED _SENSOR_CFG(SENSOR_TYPE_COLORRED, SENSOR_MODE_PERCENT) /*!< NXT 2.0 color sensor (red) in percent mode */ #define SENSOR_COLORGREEN _SENSOR_CFG(SENSOR_TYPE_COLORGREEN, SENSOR_MODE_PERCENT) /*!< NXT 2.0 color sensor (green) in percent mode */ #define SENSOR_COLORBLUE _SENSOR_CFG(SENSOR_TYPE_COLORBLUE, SENSOR_MODE_PERCENT) /*!< NXT 2.0 color sensor (blue) in percent mode */ #define SENSOR_COLORNONE _SENSOR_CFG(SENSOR_TYPE_COLORNONE, SENSOR_MODE_PERCENT) /*!< NXT 2.0 color sensor (none) in percent mode */ #endif /** @} */ // end of SensorModes group /** @} */ // end of InputModuleTypesAndModes group /** @} */ // end of InputModuleConstants group /** @defgroup InputModuleTypes Input module types * Types used by various input module functions. * @{ */ #if __FIRMWARE_VERSION > 107 /** * Parameters for the ColorSensorRead system call. * This structure is used when calling the \ref SysColorSensorRead system call function. * Choose the sensor port (\ref InPorts) and after calling the function * read the sensor values from the ColorValue field or the raw, normalized, or * scaled value arrays. * \sa SysColorSensorRead() */ struct ColorSensorReadType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ byte Port; /*!< The sensor port. See the constants in the \ref InPorts group. */ int ColorValue; /*!< The color value returned by the sensor. See the \ref InputColorValueConstants group. */ unsigned int RawArray[]; /*!< Raw color values returned by the sensor. See the \ref InputColorIdxConstants group. */ unsigned int NormalizedArray[]; /*!< Normalized color values returned by the sensor. See the \ref InputColorIdxConstants group. */ int ScaledArray[]; /*!< Scaled color values returned by the sensor. See the \ref InputColorIdxConstants group. */ bool Invalid; /*!< Are the sensor values valid? */ }; #endif #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Parameters for the \ref RemoteGetInputValues function. * This structure is used when calling the \ref RemoteGetInputValues function. * Choose the sensor port (\ref InPorts) and after calling the function * read the sensor values from the various structure fields. */ struct InputValuesType { byte Port; /*!< The sensor port. See the \ref InPorts group. */ bool Valid; /*!< Is the sensor value valid? */ bool Calibrated; /*!< Is the sensor calibrated? */ byte SensorType; /*!< The sensor type. See the \ref SensorTypes group. */ byte SensorMode; /*!< The sensor mode. See the \ref SensorModes group. */ unsigned int RawValue; /*!< The raw value. */ unsigned int NormalizedValue; /*!< The normalized value. */ int ScaledValue; /*!< The scaled value. */ int CalibratedValue; /*!< The calibrated value. */ }; /* struct InputType { unsigned int CustomZeroOffset; unsigned int ADRaw; unsigned int SensorRaw; int SensorValue; byte SensorType; byte SensorMode; bool SensorBoolean; byte DigiPinsDir; byte DigiPinsIn; byte DigiPinsOut; byte CustomPctFullScale; byte CustomActiveStatus; bool InvalidData; }; */ #endif /** @} */ // end of InputModuleTypes group /** @defgroup InputModuleFunctions Input module functions * Functions for accessing and modifying input module features. * @{ */ /** @defgroup BasicSensorValues Basic analog sensor value names * Read analog sensor values using these names. Returns the current scaled value * of the sensor on the specified port. * @{ */ #define SENSOR_1 Sensor(S1) /*!< Read the value of the analog sensor on port S1 */ #define SENSOR_2 Sensor(S2) /*!< Read the value of the analog sensor on port S2 */ #define SENSOR_3 Sensor(S3) /*!< Read the value of the analog sensor on port S3 */ #define SENSOR_4 Sensor(S4) /*!< Read the value of the analog sensor on port S4 */ /** @} */ // end of BasicSensorValues group /** * Set sensor type. * Set a sensor's type, which must be one of the predefined sensor type * constants. After changing the type or the mode of a sensor * port you must call \ref ResetSensor to give the firmware time to reconfigure * the sensor port. * \sa SetSensorMode(), SetSensor() * \param port The port to configure. See \ref InPorts. * \param type The desired sensor type. See \ref SensorTypes. */ inline void SetSensorType(const byte & port, byte type) { asm { setin type, port, TypeField } } /** * Set sensor mode. * Set a sensor's mode, which should be one of the predefined sensor mode * constants. A slope parameter for boolean conversion, if desired, may be * added to the mode. After changing the type or the mode of a sensor * port you must call \ref ResetSensor to give the firmware time to reconfigure * the sensor port. * \sa SetSensorType(), SetSensor() * \param port The port to configure. See \ref InPorts. * \param mode The desired sensor mode. See \ref SensorModes. */ inline void SetSensorMode(const byte & port, byte mode) { asm { setin mode, port, InputModeField } } /** * Clear a sensor value. * Clear the value of a sensor - only affects sensors that are configured * to measure a cumulative quantity such as rotation or a pulse count. * \param port The port to clear. See \ref InPorts. */ inline void ClearSensor(const byte & port) { asm { setin 0, port, ScaledValueField } } /** * Reset the sensor port. * Sets the invalid data flag on the specified port and waits for it to * become valid again. After changing the type or the mode of a sensor * port you must call this function to give the firmware time to reconfigure * the sensor port. * \param port The port to reset. See \ref InPorts. */ inline void ResetSensor(const byte & port) { asm { __ResetSensor(port) } } /** * Set sensor configuration. * Set the type and mode of the given sensor to the specified configuration, * which must be a special constant containing both type and mode information. * \sa SetSensorType(), SetSensorMode(), and ResetSensor() * \param port The port to configure. See \ref InPorts. * \param config The configuration constant containing both the type and mode. * See \ref SensorTypeModes. */ inline void SetSensor(const byte & port, const unsigned int config) { asm { setin config>>8, port, TypeField setin config&0xff, port, InputModeField __ResetSensor(port) } } /** * Configure a touch sensor. * Configure the sensor on the specified port as a touch sensor. * \param port The port to configure. See \ref InPorts. */ inline void SetSensorTouch(const byte & port) { asm { __SetSensorTouch(port) } } /** * Configure a light sensor. * Configure the sensor on the specified port as an NXT light sensor. * \param port The port to configure. See \ref InPorts. * \param bActive A boolean flag indicating whether to configure the port * as an active or inactive light sensor. The default value for this * optional parameter is true. */ inline void SetSensorLight(const byte & port, bool bActive = true) { SetSensorType(port, bActive ? SENSOR_TYPE_LIGHT_ACTIVE : SENSOR_TYPE_LIGHT_INACTIVE); SetSensorMode(port, SENSOR_MODE_PERCENT); ResetSensor(port); } /** * Configure a sound sensor. * Configure the sensor on the specified port as a sound sensor. * \param port The port to configure. See \ref InPorts. * \param bdBScaling A boolean flag indicating whether to configure the port * as a sound sensor with dB or dBA scaling. The default value for this * optional parameter is true, meaning dB scaling. */ inline void SetSensorSound(const byte & port, bool bdBScaling = true) { SetSensorType(port, bdBScaling ? SENSOR_TYPE_SOUND_DB : SENSOR_TYPE_SOUND_DBA); SetSensorMode(port, SENSOR_MODE_PERCENT); ResetSensor(port); } /** * Configure an I2C sensor. * Configure the sensor on the specified port as an I2C digital sensor * for either powered (9 volt) or unpowered devices. * \param port The port to configure. See \ref InPorts. * \param bIsPowered A boolean flag indicating whether to configure the port * for powered or unpowered I2C devices. The default value for this * optional parameter is true. */ inline void SetSensorLowspeed(const byte & port, bool bIsPowered = true) { SetSensorType(port, bIsPowered ? SENSOR_TYPE_LOWSPEED_9V : SENSOR_TYPE_LOWSPEED); SetSensorMode(port, SENSOR_MODE_RAW); ResetSensor(port); } /** * Configure an ultrasonic sensor. * Configure the sensor on the specified port as an ultrasonic sensor. * \param port The port to configure. See \ref InPorts. */ inline void SetSensorUltrasonic(const byte & port) { SetSensorLowspeed(port); } /** * Configure an EMeter sensor. * Configure the sensor on the specified port as an EMeter sensor. * \param port The port to configure. See \ref InPorts. */ inline void SetSensorEMeter(const byte & port) { SetSensorLowspeed(port); } /** * Configure a temperature sensor. * Configure the sensor on the specified port as a temperature sensor. Use this * to setup the temperature sensor rather than \ref SetSensorLowspeed so that * the sensor is properly configured in 12-bit conversion mode. * \param port The port to configure. See \ref InPorts. */ inline void SetSensorTemperature(const byte & port) { SetSensorLowspeed(port); asm { __MSWriteToRegister(port, LEGO_ADDR_TEMP, TEMP_REG_CONFIG, TEMP_RES_12BIT, __WDSC_LSStatus) } } #if __FIRMWARE_VERSION > 107 /** * Configure an NXT 2.0 full color sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in full color mode. Requires an NXT 2.0 compatible firmware. * \param port The port to configure. See \ref InPorts. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SetSensorColorFull(const byte & port) { asm { __SetSensorColorFull(port) } } /** * Configure an NXT 2.0 red light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in red light mode. Requires an NXT 2.0 compatible firmware. * \param port The port to configure. See \ref InPorts. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SetSensorColorRed(const byte & port) { asm { __SetSensorColorRed(port) } } /** * Configure an NXT 2.0 green light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in green light mode. Requires an NXT 2.0 compatible firmware. * \param port The port to configure. See \ref InPorts. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SetSensorColorGreen(const byte & port) { asm { __SetSensorColorGreen(port) } } /** * Configure an NXT 2.0 blue light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in blue light mode. Requires an NXT 2.0 compatible firmware. * \param port The port to configure. See \ref InPorts. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SetSensorColorBlue(const byte & port) { asm { __SetSensorColorBlue(port) } } /** * Configure an NXT 2.0 no light sensor. * Configure the sensor on the specified port as an NXT 2.0 color sensor * in no light mode. Requires an NXT 2.0 compatible firmware. * \param port The port to configure. See \ref InPorts. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SetSensorColorNone(const byte & port) { asm { __SetSensorColorNone(port) } } #endif #ifdef __DOXYGEN_DOCS /** * Get an input field value. * Return the value of the specified field of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A constant or a variable may * be used (no expressions). * \param field An input field constant. See \ref InputFieldConstants. * \return The input field value. */ inline variant GetInput(const byte & port, const byte field); /** * Set an input field value. * Set the specified field of the sensor on the specified port to the value * provided. * * \param port The sensor port. See \ref InPorts. A constant or a variable * may be used (no expressions). * \param field An input field constant. See \ref InputFieldConstants. * \param value The new value, which may be any valid expression. */ inline void SetInput(const byte & port, const int field, variant value); /** * Read sensor scaled value. * Return the processed sensor reading for a sensor on the specified port. * This is the same value that is returned by the sensor value names * (e.g. \ref SENSOR_1). * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's scaled value. */ inline unsigned int Sensor(const byte & port); /** * Read sensor boolean value. * Return the boolean value of a sensor on the specified port. Boolean * conversion is either done based on preset cutoffs, or a slope parameter * specified by calling SetSensorMode. * * \param port The sensor port. See \ref InPorts. Must be a constant. * \return The sensor's boolean value. */ inline bool SensorBoolean(const byte port); /** * Read sensor digital pins direction. * Return the digital pins direction value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. Must be a constant. * \return The sensor's digital pins direction. */ inline byte SensorDigiPinsDirection(const byte port); /** * Read sensor digital pins output level. * Return the digital pins output level value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. Must be a constant. * \return The sensor's digital pins output level. */ inline byte SensorDigiPinsOutputLevel(const byte port); /** * Read sensor digital pins status. * Return the digital pins status value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. Must be a constant. * \return The sensor's digital pins status. */ inline byte SensorDigiPinsStatus(const byte port); /** * Read sensor invalid data flag. * Return the value of the InvalidData flag of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's invalid data flag. */ inline bool SensorInvalid(const byte & port); /** * Read sensor mode. * Return the mode of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's mode. See \ref SensorModes. */ inline byte SensorMode(const byte & port); /** * Read sensor normalized value. * Return the normalized value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's normalized value. */ inline unsigned int SensorNormalized(const byte & port); /** * Read sensor raw value. * Return the raw value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's raw value. */ inline unsigned int SensorRaw(const byte & port); /** * Read sensor scaled value. * Return the processed sensor reading for a sensor on the specified port. * This is the same value that is returned by the sensor value names * (e.g. \ref SENSOR_1) or the \ref Sensor function. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's scaled value. */ inline unsigned int SensorScaled(const byte & port); /** * Read sensor type. * Return the type of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's type. See \ref SensorTypes. */ inline byte SensorType(const byte & port); /** * Read sensor scaled value. * Return the processed sensor reading for a sensor on the specified port. * This is the same value that is returned by the sensor value names * (e.g. \ref SENSOR_1) or the \ref Sensor function. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's scaled value. */ inline unsigned int SensorValue(const byte & port); /** * Read sensor boolean value. * Return the boolean value of a sensor on the specified port. Boolean * conversion is either done based on preset cutoffs, or a slope parameter * specified by calling SetSensorMode. * * \param port The sensor port. See \ref InPorts. Must be a constant. * \return The sensor's boolean value. */ inline bool SensorValueBool(const byte port); /** * Read sensor raw value. * Return the raw value of a sensor on the specified port. * * \param port The sensor port. See \ref InPorts. A variable whose value is * the desired sensor port may also be used. * \return The sensor's raw value. */ inline unsigned int SensorValueRaw(const byte & port); /** * Get the custom sensor active status. * Return the custom sensor active status value of a sensor. * * \param port The sensor port. See \ref InPorts. * \return The custom sensor active status. */ inline byte CustomSensorActiveStatus(byte port); /** * Get the custom sensor percent full scale. * Return the custom sensor percent full scale value of a sensor. * * \param port The sensor port. See \ref InPorts. * \return The custom sensor percent full scale. */ inline byte CustomSensorPercentFullScale(byte port); /** * Get the custom sensor zero offset. * Return the custom sensor zero offset value of a sensor. * * \param port The sensor port. See \ref InPorts. * \return The custom sensor zero offset. */ inline unsigned int CustomSensorZeroOffset(byte port); /** * Set active status. * Sets the active status value of a custom sensor. * * \param port The sensor port. See \ref InPorts. * \param activeStatus The new active status value. */ inline void SetCustomSensorActiveStatus(byte port, byte activeStatus); /** * Set percent full scale. * Sets the percent full scale value of a custom sensor. * * \param port The sensor port. See \ref InPorts. * \param pctFullScale The new percent full scale value. */ inline void SetCustomSensorPercentFullScale(byte port, byte pctFullScale); /** * Set custom zero offset. * Sets the zero offset value of a custom sensor. * * \param port The sensor port. See \ref InPorts. * \param zeroOffset The new zero offset value. */ inline void SetCustomSensorZeroOffset(byte port, int zeroOffset); /** * Set sensor boolean value. * Sets the boolean value of a sensor. * * \param port The sensor port. See \ref InPorts. * \param value The new boolean value. */ inline void SetSensorBoolean(byte port, bool value); /** * Set digital pins direction. * Sets the digital pins direction value of a sensor. * * \param port The sensor port. See \ref InPorts. * \param direction The new digital pins direction value. */ inline void SetSensorDigiPinsDirection(byte port, byte direction); /** * Set digital pins output level. * Sets the digital pins output level value of a sensor. * * \param port The sensor port. See \ref InPorts. * \param outputLevel The new digital pins output level value. */ inline void SetSensorDigiPinsOutputLevel(byte port, byte outputLevel); /** * Set digital pins status. * Sets the digital pins status value of a sensor. * * \param port The sensor port. See \ref InPorts. * \param status The new digital pins status value. */ inline void SetSensorDigiPinsStatus(byte port, byte status); #if __FIRMWARE_VERSION > 107 /** * Read LEGO color sensor. * This function lets you read the LEGO color sensor given the parameters you * pass in via the \ref ColorSensorReadType structure. * * \param args The ColorSensorReadType structure containing the required parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysColorSensorRead(ColorSensorReadType & args); /** * Read LEGO color sensor extra. * This function lets you read the LEGO color sensor. It returns the color value, * and three arrays containing raw, normalized, and scaled color values for * red, green, blue, and none indices. * * \param port The sensor port. See \ref InPorts. * \param colorval The color value. See \ref InputColorValueConstants. * \param raw An array containing four raw color values. See \ref InputColorIdxConstants. * \param norm An array containing four normalized color values. See \ref InputColorIdxConstants. * \param scaled An array containing four scaled color values. See \ref InputColorIdxConstants. * \return The function call result. * \warning This function requires an NXT 2.0 compatible firmware. */ inline int ReadSensorColorEx(const byte & port, int & colorval, unsigned int & raw[], unsigned int & norm[], int & scaled[]); /** * Read LEGO color sensor raw values. * This function lets you read the LEGO color sensor. It returns an array * containing raw color values for red, green, blue, and none indices. * * \param port The sensor port. See \ref InPorts. * \param rawVals An array containing four raw color values. See \ref InputColorIdxConstants. * \return The function call result. * \warning This function requires an NXT 2.0 compatible firmware. */ inline int ReadSensorColorRaw(const byte & port, unsigned int & rawVals[]); /** * Read a LEGO color sensor AD raw value. * This function lets you directly access a specific LEGO color sensor AD raw value. Both the * port and the color index must be constants. * * \param port The sensor port. See \ref InPorts. * \param color The color index. See \ref InputColorIdxConstants. * \return The AD raw value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline unsigned int ColorADRaw(byte port, byte color); /** * Read a LEGO color sensor boolean value. * This function lets you directly access a specific LEGO color sensor boolean value. Both the * port and the color index must be constants. * * \param port The sensor port. See \ref InPorts. * \param color The color index. See \ref InputColorIdxConstants. * \return The boolean value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline bool ColorBoolean(byte port, byte color); /** * Read a LEGO color sensor calibration point value. * This function lets you directly access a specific LEGO color calibration point value. * The port, point, and color index must be constants. * * \param port The sensor port. See \ref InPorts. * \param point The calibration point. See \ref InputColorCalibrationConstants. * \param color The color index. See \ref InputColorIdxConstants. * \return The calibration point value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline long ColorCalibration(byte port, byte point, byte color); /** * Read LEGO color sensor calibration state. * This function lets you directly access the LEGO color calibration state. * The port must be a constant. * * \param port The sensor port. See \ref InPorts. * \return The calibration state. * \warning This function requires an NXT 2.0 compatible firmware. */ inline byte ColorCalibrationState(byte port); /** * Read a LEGO color sensor calibration limit value. * This function lets you directly access a specific LEGO color calibration limit value. * The port and the point must be constants. * * \param port The sensor port. See \ref InPorts. * \param point The calibration point. See \ref InputColorCalibrationConstants. * \return The calibration limit value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline unsigned int ColorCalLimits(byte port, byte point); /** * Read a LEGO color sensor raw value. * This function lets you directly access a specific LEGO color sensor raw value. Both the * port and the color index must be constants. * * \param port The sensor port. See \ref InPorts. * \param color The color index. See \ref InputColorIdxConstants. * \return The raw value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline unsigned int ColorSensorRaw(byte port, byte color); /** * Read a LEGO color sensor scaled value. * This function lets you directly access a specific LEGO color sensor scaled value. Both the * port and the color index must be constants. * * \param port The sensor port. See \ref InPorts. * \param color The color index. See \ref InputColorIdxConstants. * \return The scaled value. * \warning This function requires an NXT 2.0 compatible firmware. */ inline unsigned int ColorSensorValue(byte port, byte color); #endif #else enum InputFieldNames { Type, InputMode, RawValue, NormalizedValue, ScaledValue, InvalidData }; enum OutputFieldNames { UpdateFlags, OutputMode, Power, ActualSpeed, TachoCount, TachoLimit, RunState, TurnRatio, RegMode, Overload, RegPValue, RegIValue, RegDValue, BlockTachoCount, RotationCount, OutputOptions, MaxSpeed, MaxAcceleration }; // input fields #define Sensor(_p) asm { ReadSensor(_p, __RETVAL__) } #define SensorValue(_p) Sensor(_p) #define SensorType(_p) GetInput(_p, TypeField) #define SensorMode(_p) GetInput(_p, InputModeField) #define SensorRaw(_p) GetInput(_p, RawValueField) #define SensorNormalized(_p) GetInput(_p, NormalizedValueField) #define SensorScaled(_p) GetInput(_p, ScaledValueField) #define SensorInvalid(_p) GetInput(_p, InvalidDataField) #define SensorValueBool(_p) SensorBoolean(_p) #define SensorValueRaw(_p) SensorRaw(_p) #define CustomSensorZeroOffset(_p) asm { GetInCustomZeroOffset(_p, __TMPWORD__) __RETURN__ __TMPWORD__ } #define CustomSensorPercentFullScale(_p) asm { GetInCustomPercentFullScale(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define CustomSensorActiveStatus(_p) asm { GetInCustomActiveStatus(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SensorBoolean(_p) asm { GetInSensorBoolean(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SensorDigiPinsDirection(_p) asm { GetInDigiPinsDirection(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SensorDigiPinsStatus(_p) asm { GetInDigiPinsStatus(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SensorDigiPinsOutputLevel(_p) asm { GetInDigiPinsOutputLevel(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetCustomSensorZeroOffset(_p, _n) asm { __setInCustomZeroOffset(_p, _n) } #define SetCustomSensorPercentFullScale(_p, _n) asm { __setInCustomPercentFullScale(_p, _n) } #define SetCustomSensorActiveStatus(_p, _n) asm { __setInCustomActiveStatus(_p, _n) } #define SetSensorBoolean(_p, _n) asm { __setInSensorBoolean(_p, _n) } #define SetSensorDigiPinsDirection(_p, _n) asm { __setInDigiPinsDirection(_p, _n) } #define SetSensorDigiPinsStatus(_p, _n) asm { __setInDigiPinsStatus(_p, _n) } #define SetSensorDigiPinsOutputLevel(_p, _n) asm { __setInDigiPinsOutputLevel(_p, _n) } #if __FIRMWARE_VERSION > 107 #define SysColorSensorRead(_args) asm { \ compchktype _args, ColorSensorReadType \ syscall ColorSensorRead, _args \ } #define ReadSensorColorRaw(_port, _rawVals) asm { __ReadSensorColorRaw(_port, _rawVals, __RETVAL__) } #define ReadSensorColorEx(_port, _colorval, _raw, _norm, _scaled) asm { __ReadSensorColorEx(_port, _colorval, _raw, _norm, _scaled, __RETVAL__) } #define ColorCalibration(_p, _np, _nc) asm { GetInColorCalibration(_p, _np, _nc, __TMPLONG__) __RETURN__ __TMPLONG__ } #define ColorCalLimits(_p, _np) asm { GetInColorCalLimits(_p, _np, __TMPWORD__) __RETURN__ __TMPWORD__ } #define ColorADRaw(_p, _nc) asm { GetInColorADRaw(_p, _nc, __TMPWORD__) __RETURN__ __TMPWORD__ } #define ColorSensorRaw(_p, _nc) asm { GetInColorSensorRaw(_p, _nc, __TMPWORD__) __RETURN__ __TMPWORD__ } #define ColorSensorValue(_p, _nc) asm { GetInColorSensorValue(_p, _nc, __TMPWORD__) __RETURN__ __TMPWORD__ } #define ColorBoolean(_p, _nc) asm { GetInColorBoolean(_p, _nc, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ColorCalibrationState(_p) asm { GetInColorCalibrationState(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #endif #endif /** @} */ // end of InputModuleFunctions group /** @} */ // end of InputModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// OUTPUT MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup OutputModule * @{ */ /** @defgroup OutputModuleTypes Output module types * Types used by various output module functions. * @{ */ #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Parameters for the \ref RemoteGetOutputState function. * This structure is used when calling the \ref RemoteGetOutputState function. * Choose the sensor port (\ref OutputPortConstants) and after calling the function * read the output status values from the various structure fields. */ struct OutputStateType { byte Port; /*!< The output port. See the \ref OutputPortConstants group. */ char Power; /*!< The output power level (-100..100). */ byte Mode; /*!< The output mode. See \ref OutModeConstants group. */ byte RegMode; /*!< The output regulation mode. See \ref OutRegModeConstants group. */ char TurnRatio; /*!< The output turning ratio (-100..100). */ byte RunState; /*!< The output run state. See \ref OutRunStateConstants group. */ unsigned long TachoLimit; /*!< The tachometer limit. */ long TachoCount; /*!< The current tachometer count. */ long BlockTachoCount; /*!< The current block tachometer count. */ long RotationCount; /*!< The current rotation count. */ }; #endif /** @} */ // end of OutputModuleTypes group /** @defgroup OutputModuleFunctions Output module functions * Functions for accessing and modifying output module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Set motor regulation frequency. * Set the motor regulation frequency in milliseconds. By default this is set * to 100ms. * \param n The motor regulation frequency. */ inline void SetMotorPwnFreq(byte n); /** * Set regulation time. * Set the motor regulation time in milliseconds. By default this is set * to 100ms. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+ * * \param n The motor regulation time. */ inline void SetMotorRegulationTime(byte n); /** * Set regulation options. * Set the motor regulation options. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+ * * \param n The motor regulation options. */ inline void SetMotorRegulationOptions(byte n); /** * Run motors forward synchronised with PID factors. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnFwdSyncPID(byte outputs, char pwr, char turnpct, byte p, byte i, byte d); /** * Run motors forward synchronised and reset counters with PID factors. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnFwdSyncExPID(byte outputs, char pwr, char turnpct, const byte reset, byte p, byte i, byte d); /** * Run motors backward synchronised with PID factors. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnRevSyncPID(byte outputs, char pwr, char turnpct, byte p, byte i, byte d); /** * Run motors backward synchronised and reset counters with PID factors. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnRevSyncExPID(byte outputs, char pwr, char turnpct, const byte reset, byte p, byte i, byte d); /** * Run motors forward regulated with PID factors. * Run the specified outputs forward using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnFwdRegPID(byte outputs, char pwr, byte regmode, byte p, byte i, byte d); /** * Run motors forward regulated and reset counters with PID factors. * Run the specified outputs forward using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnFwdRegExPID(byte outputs, char pwr, byte regmode, const byte reset, byte p, byte i, byte d); /** * Run motors reverse regulated with PID factors. * Run the specified outputs in reverse using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnRevRegPID(byte outputs, char pwr, byte regmode, byte p, byte i, byte d); /** * Run motors backward regulated and reset counters with PID factors. * Run the specified outputs in reverse using the specified regulation mode. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void OnRevRegExPID(byte outputs, char pwr, byte regmode, const byte reset, byte p, byte i, byte d); /** * Turn motors off. * Turn the specified outputs off (with braking). * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ inline void Off(byte outputs); /** * Turn motors off and reset counters. * Turn the specified outputs off (with braking). * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OffEx(byte outputs, const byte reset); /** * Coast motors. * Turn off the specified outputs, making them coast to a stop. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ inline void Coast(byte outputs); /** * Coast motors and reset counters. * Turn off the specified outputs, making them coast to a stop. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void CoastEx(byte outputs, const byte reset); /** * Float motors. * Make outputs float. Float is an alias for Coast. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. */ inline void Float(byte outputs); /** * Run motors forward. * Set outputs to forward direction and turn them on. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. */ inline void OnFwd(byte outputs, char pwr); /** * Run motors forward and reset counters. * Set outputs to forward direction and turn them on. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnFwdEx(byte outputs, char pwr, const byte reset); /** * Run motors backward. * Set outputs to reverse direction and turn them on. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. */ inline void OnRev(byte outputs, char pwr); /** * Run motors backward and reset counters. * Set outputs to reverse direction and turn them on. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnRevEx(byte outputs, char pwr, const byte reset); /** * Run motors forward regulated. * Run the specified outputs forward using the specified regulation mode. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. */ inline void OnFwdReg(byte outputs, char pwr, byte regmode); /** * Run motors forward regulated and reset counters. * Run the specified outputs forward using the specified regulation mode. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnFwdRegEx(byte outputs, char pwr, byte regmode, const byte reset); /** * Run motors forward regulated. * Run the specified outputs in reverse using the specified regulation mode. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. */ inline void OnRevReg(byte outputs, char pwr, byte regmode); /** * Run motors backward regulated and reset counters. * Run the specified outputs in reverse using the specified regulation mode. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param regmode Regulation mode, see \ref OutRegModeConstants. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnRevRegEx(byte outputs, char pwr, byte regmode, const byte reset); /** * Run motors forward synchronised. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. */ inline void OnFwdSync(byte outputs, char pwr, char turnpct); /** * Run motors forward synchronised and reset counters. * Run the specified outputs forward with regulated synchronization using the * specified turn ratio. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnFwdSyncEx(byte outputs, char pwr, char turnpct, const byte reset); /** * Run motors backward synchronised. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. */ inline void OnRevSync(byte outputs, char pwr, char turnpct); /** * Run motors backward synchronised and reset counters. * Run the specified outputs in reverse with regulated synchronization using * the specified turn ratio. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param reset Position counters reset control. It must be a constant, see * \ref TachoResetConstants. */ inline void OnRevSyncEx(byte outputs, char pwr, char turnpct, const byte reset); /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param angle Angle limit, in degree. Can be negative to reverse direction. */ inline void RotateMotor(byte outputs, char pwr, long angle); /** * Rotate motor with PID factors. * Run the specified outputs forward for the specified number of degrees. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param angle Angle limit, in degree. Can be negative to reverse direction. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void RotateMotorPID(byte outputs, char pwr, long angle, byte p, byte i, byte d); /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param angle Angle limit, in degree. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param sync Synchronise two motors. Should be set to true if a non-zero * turn percent is specified or no turning will occur. * \param stop Specify whether the motor(s) should brake at the end of the * rotation. */ inline void RotateMotorEx(byte outputs, char pwr, long angle, char turnpct, bool sync, bool stop); /** * Rotate motor. * Run the specified outputs forward for the specified number of degrees. * Specify proportional, integral, and derivative factors. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. If you use a variable and want to control multiple * outputs in a single call you need to use a byte array rather than a byte and * store the output port values in the byte array before passing it into this function. * \param pwr Output power, 0 to 100. Can be negative to reverse direction. * \param angle Angle limit, in degree. Can be negative to reverse direction. * \param turnpct Turn ratio, -100 to 100. The direction of your vehicle will * depend on its construction. * \param sync Synchronise two motors. Should be set to true if a non-zero * turn percent is specified or no turning will occur. * \param stop Specify whether the motor(s) should brake at the end of the * rotation. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. */ inline void RotateMotorExPID(byte outputs, char pwr, long angle, char turnpct, bool sync, bool stop, byte p, byte i, byte d); /** * Reset tachometer counter. * Reset the tachometer count and tachometer limit goal for the specified * outputs. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ inline void ResetTachoCount(byte outputs); /** * Reset block-relative counter. * Reset the block-relative position counter for the specified outputs. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ inline void ResetBlockTachoCount(byte outputs); /** * Reset program-relative counter. * Reset the program-relative position counter for the specified outputs. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ inline void ResetRotationCount(byte outputs); /** * Reset all tachometer counters. * Reset all three position counters and reset the current tachometer limit * goal for the specified outputs. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. */ inline void ResetAllTachoCounts(byte outputs); /** * Set output fields. * Set the specified field of the outputs to the value provided. The field * must be a valid output field constant. This function takes a variable * number of field/value pairs. * * \param outputs Desired output ports. Can be a constant or a variable, see * \ref OutputPortConstants. For multiple outputs at the same time * you need to add single output port values into a byte array and pass the array * instead of a single numeric value. * \param field1 The 1st output port field to access, this should be a constant, see * \ref OutputFieldConstants. * \param val1 Value to set for the 1st field. * \param fieldN The Nth output port field to access, this should be a constant, see * \ref OutputFieldConstants. * \param valN The value to set for the Nth field. */ inline void SetOutput(byte outputs, byte field1, variant val1, ..., byte fieldN, variant valN); /** * Get output field value. * Get the value of the specified field for the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \param field Output port field to access, this should be a constant, see * \ref OutputFieldConstants. * \return The requested output field value. */ inline variant GetOutput(byte output, const byte field); /** * Get motor mode. * Get the mode of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The mode of the specified output. */ inline byte MotorMode(byte output); /** * Get motor power level. * Get the power level of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The power level of the specified output. */ inline char MotorPower(byte output); /** * Get motor actual speed. * Get the actual speed value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The actual speed value of the specified output. */ inline char MotorActualSpeed(byte output); /** * Get motor tachometer counter. * Get the tachometer count value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The tachometer count value of the specified output. */ inline long MotorTachoCount(byte output); /** * Get motor tachometer limit. * Get the tachometer limit value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The tachometer limit value of the specified output. */ inline long MotorTachoLimit(byte output); /** * Get motor run state. * Get the RunState value of the specified output, see \ref * OutRunStateConstants. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The RunState value of the specified output. */ inline byte MotorRunState(byte output); /** * Get motor turn ratio. * Get the turn ratio value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The turn ratio value of the specified output. */ inline char MotorTurnRatio(byte output); /** * Get motor regulation mode. * Get the regulation value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The regulation value of the specified output. */ inline byte MotorRegulation(byte output); /** * Get motor overload status. * Get the overload value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The overload value of the specified output. */ inline bool MotorOverload(byte output); /** * Get motor P value. * Get the proportional PID value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The proportional PID value of the specified output. */ inline byte MotorRegPValue(byte output); /** * Get motor I value. * Get the integral PID value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The integral PID value of the specified output. */ inline byte MotorRegIValue(byte output); /** * Get motor D value. * Get the derivative PID value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The derivative PID value of the specified output. */ inline byte MotorRegDValue(byte output); /** * Get motor block-relative counter. * Get the block-relative position counter value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The block-relative position counter value of the specified output. */ inline long MotorBlockTachoCount(byte output); /** * Get motor program-relative counter. * Get the program-relative position counter value of the specified output. * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The program-relative position counter value of the specified output. */ inline long MotorRotationCount(byte output); /** * Get motor options. * Get the options value of the specified output. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+ * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The options value of the specified output. */ inline byte MotorOutputOptions(byte output); /** * Get motor max speed. * Get the max speed value of the specified output. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+ * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The max speed value of the specified output. */ inline byte MotorMaxSpeed(byte output); /** * Get motor max acceleration. * Get the max acceleration value of the specified output. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+ * * \param output Desired output port. Can be \ref OUT_A, \ref OUT_B, \ref * OUT_C or a variable containing one of these values, see \ref * OutputPortConstants. * \return The max acceleration value of the specified output. */ inline byte MotorMaxAcceleration(byte output); /** * Get motor regulation frequency. * Get the current motor regulation frequency in milliseconds. * \return The motor regulation frequency. */ inline byte MotorPwnFreq(); /** * Get motor regulation time. * Get the current motor regulation time in milliseconds. * \return The motor regulation time. */ inline byte MotorRegulationTime(); /** * Get motor regulation options. * Get the current motor regulation options. * \return The motor regulation options. */ inline byte MotorRegulationOptions(); #else // output fields #define MotorMode(_p) GetOutput(_p, OutputMode) #define MotorPower(_p) GetOutput(_p, Power) #define MotorActualSpeed(_p) GetOutput(_p, ActualSpeed) #define MotorTachoCount(_p) GetOutput(_p, TachoCount) #define MotorTachoLimit(_p) GetOutput(_p, TachoLimit) #define MotorRunState(_p) GetOutput(_p, RunState) #define MotorTurnRatio(_p) GetOutput(_p, TurnRatio) #define MotorRegulation(_p) GetOutput(_p, RegMode) #define MotorOverload(_p) GetOutput(_p, Overload) #define MotorRegPValue(_p) GetOutput(_p, RegPValue) #define MotorRegIValue(_p) GetOutput(_p, RegIValue) #define MotorRegDValue(_p) GetOutput(_p, RegDValue) #define MotorBlockTachoCount(_p) GetOutput(_p, BlockTachoCount) #define MotorRotationCount(_p) GetOutput(_p, RotationCount) #define MotorPwnFreq() asm { GetOutPwnFreq(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetMotorPwnFreq(_n) asm { __setOutPwnFreq(_n) } #define MotorRegulationTime() asm { GetOutRegulationTime(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetMotorRegulationTime(_n) asm { __setOutRegulationTime(_n) } #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define MotorOutputOptions(_p) GetOutput(_p, OutputOptions) #define MotorMaxSpeed(_p) GetOutput(_p, MaxSpeed) #define MotorMaxAcceleration(_p) GetOutput(_p, MaxAcceleration) #define MotorRegulationOptions() asm { GetOutRegulationOptions(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetMotorRegulationOptions(_n) asm { __setOutRegulationOptions(_n) } #endif #endif /** @} */ // end of OutputModuleFunctions group /** @} */ // end of OutputModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// DISPLAY MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup DisplayModule * @{ */ /** @defgroup DisplayModuleTypes Display module types * Types used by various display module functions. * @{ */ /** * A point on the NXT LCD screen. * This structure is by other system call structures to specify an X, Y * LCD screen coordinate. * \sa DrawTextType, DrawPointType, DrawLineType, DrawCircleType, DrawRectType, * DrawGraphicType, DrawGraphicArrayType, DrawPolygonType, DrawEllipseType, * DrawFontType */ struct LocationType { int X; /*!< The X coordinate. Valid range is from 0 to 99 inclusive. */ int Y; /*!< The Y coordinate. Valid range is from 0 to 63 inclusive. For text drawing this value must be a multiple of 8. */ }; /** * Width and height dimensions for the DrawRect system call. * This structure is by the \ref DrawRectType to specify a width and * height for a rectangle. * \sa DrawRectType */ struct SizeType { int Width; /*!< The rectangle width. */ int Height; /*!< The rectangle height. */ }; /** * Parameters for the DrawText system call. * This structure is used when calling the \ref SysDrawText system call function. * It lets you specify the text to draw, the LCD line and horizontal position using the * \ref LocationType structure member, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawText() */ struct DrawTextType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Location; /*!< The location in X, LCD line number coordinates. */ string Text; /*!< The text to draw on the LCD. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawPoint system call. * This structure is used when calling the \ref SysDrawPoint system call * function. * It lets you specify the pixel to draw using the * \ref LocationType structure member, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawPoint() */ struct DrawPointType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Location; /*!< The point location on screen. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawLine system call. * This structure is used when calling the \ref SysDrawLine system call * function. * It lets you specify the end points of the line to draw using two * \ref LocationType structure member, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawLine() */ struct DrawLineType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType StartLoc; /*!< The location of the starting point. */ LocationType EndLoc; /*!< The location of the ending point. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawCircle system call. * This structure is used when calling the \ref SysDrawCircle system call * function. * It lets you specify the center of the circle to draw using the * \ref LocationType structure member, the radius, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawCircle() */ struct DrawCircleType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Center; /*!< The location of the circle center. */ byte Size; /*!< The circle radius. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawRect system call. * This structure is used when calling the \ref SysDrawRect system call * function. * It lets you specify the corner of the rectangle using the \ref LocationType structure member, * the width and height of the rectangle using the \ref SizeType structure member, * as well as drawing options defined in the \ref DisplayDrawOptionConstants group. * \sa SysDrawRect() */ struct DrawRectType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Location; /*!< The top left corner location. */ SizeType Size; /*!< The width and height of the rectangle. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawGraphic system call. * This structure is used when calling the \ref SysDrawGraphic system call * function. * It lets you specify the screen location at which to draw the image using the * \ref LocationType structure member, the filename of the graphic image, the * image parameters (if needed), as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawGraphic() */ struct DrawGraphicType { char Result; /*!< The function call result. Possible values include \ref LoaderErrors, \ref ERR_FILE, and \ref NO_ERR. */ LocationType Location; /*!< The location on screen. */ string Filename; /*!< The RIC file name. */ long Variables[]; /*!< The variables passed as RIC arguments. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the SetScreenMode system call. * This structure is used when calling the \ref SysSetScreenMode system call * function. * \sa SysSetScreenMode() */ struct SetScreenModeType { char Result; /*!< The function call result, always \ref NO_ERR. */ unsigned long ScreenMode; /*!< The requested screen mode. The standard NXT firmware only supports setting the ScreenMode to \ref SCREEN_MODE_RESTORE. If you install the NBC/NXC enhanced standard NXT firmware this system function also supports setting the ScreenMode to \ref SCREEN_MODE_CLEAR. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the DisplayExecuteFunction system call. * This structure is used when calling the \ref SysDisplayExecuteFunction * system call function. * * The fields usage depends on the requested command and are documented in the * table below. If a field member is shown as 'x' it is ignored by the * specified display command. * * * * * * * * * * * * * * * * * * * * *
CmdMeaningExpected parameters
DISPLAY_ERASE_ALLerase entire screen()
DISPLAY_PIXELset pixel (on/off)(true/false,X1,Y1,x,x)
DISPLAY_HORIZONTAL_LINEdraw horizontal line(true/false,X1,Y1,X2,x)
DISPLAY_VERTICAL_LINEdraw vertical line(true/false,X1,Y1,x,Y2)
DISPLAY_CHARdraw char (actual font)(true/false,X1,Y1,Char,x)
DISPLAY_ERASE_LINEerase a single line(x,LINE,x,x,x)
DISPLAY_FILL_REGIONfill screen region(true/false,X1,Y1,X2,Y2)
DISPLAY_FILLED_FRAMEdraw a frame (on / off)(true/false,X1,Y1,X2,Y2)
* * \sa SysDisplayExecuteFunction() */ struct DisplayExecuteFunctionType { byte Status; /*!< The function call result, always \ref NO_ERR. */ byte Cmd; /*!< The command to execute. */ bool On; /*!< The On parameter, see table. */ byte X1; /*!< The X1 parameter, see table. */ byte Y1; /*!< The Y1 parameter, see table. */ byte X2; /*!< The X2 parameter, see table. */ byte Y2; /*!< The Y2 parameter, see table. */ }; #if __FIRMWARE_VERSION > 107 /** * Parameters for the DrawGraphicArray system call. * This structure is used when calling the \ref SysDrawGraphicArray system call * function. * It lets you specify the screen location at which to draw the image using the * \ref LocationType structure member, the graphic image data array, the * image parameters (if needed), as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawGraphicArray() */ struct DrawGraphicArrayType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Location; /*!< The location on screen. */ byte Data[]; /*!< A byte array containing the RIC opcodes. \ref RICMacros */ long Variables[]; /*!< The variables passed as RIC arguments. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawPolygon system call. * This structure is used when calling the \ref SysDrawPolygon system call * function. * It lets you specify the points of the polygon to draw using the * \ref LocationType array structure member, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawPolygon() */ struct DrawPolygonType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Points[]; /*!< An array of LocationType structures which define the polygon's shape. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawEllipse system call. * This structure is used when calling the \ref SysDrawEllipse system call * function. * It lets you specify the center of the ellipse using the * \ref LocationType structure member, the x and y axis radii, * as well as drawing options defined in the \ref DisplayDrawOptionConstants group. * \sa SysDrawEllipse() */ struct DrawEllipseType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Center; /*!< The location of the ellipse center. */ byte SizeX; /*!< The horizontal ellipse radius. */ byte SizeY; /*!< The vertical ellipse radius. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; /** * Parameters for the DrawFont system call. * This structure is used when calling the \ref SysDrawFont system call function. * It lets you specify the text to draw, the LCD line and horizontal position using the * \ref LocationType structure member, as well as drawing options defined * in the \ref DisplayDrawOptionConstants group. * \sa SysDrawFont() */ struct DrawFontType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ LocationType Location; /*!< The location in X, LCD line number coordinates. */ string Filename; /*!< The filename of the RIC-based font file. */ string Text; /*!< The text to draw on the LCD. */ unsigned long Options; /*!< The options to use when writing to the LCD. \ref DisplayDrawOptionConstants */ }; #endif #endif /** @} */ // end of DisplayModuleTypes group /** @defgroup DisplayModuleFunctions Display module functions * Functions for accessing and modifying display module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Reset LCD screen. * This function lets you restore the standard NXT running program screen. */ inline void ResetScreen(); /** * Draw a circle. * This function lets you draw a circle on the screen with its center at the * specified x and y location, using the specified radius. Optionally specify * drawing options. If this argument is not specified it defaults to \ref DRAW_OPT_NORMAL. * Valid display option constants are listed in the \ref DisplayDrawOptionConstants group. * \sa SysDrawCircle, DrawCircleType * * \param x The x value for the center of the circle. * \param y The y value for the center of the circle. * \param radius The radius of the circle. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char CircleOut(int x, int y, byte radius, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a line. * This function lets you draw a line on the screen from x1, y1 to x2, y2. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawLine, DrawLineType * * \param x1 The x value for the start of the line. * \param y1 The y value for the start of the line. * \param x2 The x value for the end of the line. * \param y2 The y value for the end of the line. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char LineOut(int x1, int y1, int x2, int y2, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a point. * This function lets you draw a point on the screen at x, y. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawPoint, DrawPointType * * \param x The x value for the point. * \param y The y value for the point. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char PointOut(int x, int y, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a rectangle. * This function lets you draw a rectangle on the screen at x, y with the * specified width and height. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawRect, DrawRectType * * \param x The x value for the top left corner of the rectangle. * \param y The y value for the top left corner of the rectangle. * \param width The width of the rectangle. * \param height The height of the rectangle. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char RectOut(int x, int y, int width, int height, unsigned long options=DRAW_OPT_NORMAL); /** * Draw text. * Draw a text value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawText, DrawTextType * * \param x The x value for the start of the text output. * \param y The text line number for the text output. * \param str The text to output to the LCD screen. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char TextOut(int x, int y, string str, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a number. * Draw a numeric value on the screen at the specified x and y location. The y * value must be a multiple of 8. Valid line number constants are listed in * the \ref LineConstants group. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawText, DrawTextType * * \param x The x value for the start of the number output. * \param y The text line number for the number output. * \param value The value to output to the LCD screen. Any numeric type is supported. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char NumOut(int x, int y, variant value, unsigned long options=DRAW_OPT_NORMAL); /** * Draw an ellipse. * This function lets you draw an ellipse on the screen with its center at the * specified x and y location, using the specified radii. Optionally specify * drawing options. If this argument is not specified it defaults to \ref DRAW_OPT_NORMAL. * Valid display option constants are listed in the \ref DisplayDrawOptionConstants group. * \sa SysDrawEllipse, DrawEllipseType * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param x The x value for the center of the ellipse. * \param y The y value for the center of the ellipse. * \param radiusX The x axis radius. * \param radiusY The y axis radius. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char EllipseOut(int x, int y, byte radiusX, byte radiusY, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a polygon. * This function lets you draw a polygon on the screen using an array of points. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. * \sa SysDrawPolygon, DrawPolygonType * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param points An array of LocationType points that define the polygon. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char PolyOut(LocationType points[], unsigned long options=DRAW_OPT_NORMAL); /** * Draw text with font. * Draw a text value on the screen at the specified x and y location using * a custom RIC font. Optionally specify drawing options. If this argument is * not specified it defaults to \ref DRAW_OPT_NORMAL. Valid display option * constants are listed in the \ref DisplayDrawOptionConstants group. See the * \ref DisplayFontDrawOptionConstants for options specific to the font * drawing functions. * \sa FontNumOut, SysDrawFont, DrawFontType * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param x The x value for the start of the text output. * \param y The y value for the start of the text output. * \param filename The filename of the RIC font. * \param str The text to output to the LCD screen. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char FontTextOut(int x, int y, string filename, string str, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a number with font. * Draw a numeric value on the screen at the specified x and y location using * a custom RIC font. Optionally specify drawing options. If this argument is * not specified it defaults to \ref DRAW_OPT_NORMAL. Valid display option * constants are listed in the \ref DisplayDrawOptionConstants group. See the * \ref DisplayFontDrawOptionConstants for options specific to the font * drawing functions. * \sa FontTextOut, SysDrawFont, DrawFontType * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param x The x value for the start of the number output. * \param y The y value for the start of the number output. * \param filename The filename of the RIC font. * \param value The value to output to the LCD screen. Any numeric type is supported. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char FontNumOut(int x, int y, string filename, variant value, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a graphic image. * Draw a graphic image file on the screen at the specified x and y location. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa SysDrawGraphic, DrawGraphicType * * \param x The x value for the position of the graphic image. * \param y The y value for the position of the graphic image. * \param filename The filename of the RIC graphic image. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char GraphicOut(int x, int y, string filename, unsigned long options=DRAW_OPT_NORMAL); /** * Draw a graphic image from byte array. * Draw a graphic image byte array on the screen at the specified x and y location. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa SysDrawGraphicArray, DrawGraphicArrayType * * \param x The x value for the position of the graphic image. * \param y The y value for the position of the graphic image. * \param data The byte array of the RIC graphic image. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char GraphicArrayOut(int x, int y, byte data[], unsigned long options=DRAW_OPT_NORMAL); /** * Draw a graphic image with parameters. * Draw a graphic image file on the screen at the specified x and y location using * an array of parameters. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa SysDrawGraphic, DrawGraphicType * * \param x The x value for the position of the graphic image. * \param y The y value for the position of the graphic image. * \param filename The filename of the RIC graphic image. * \param vars The byte array of parameters. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char GraphicOutEx(int x, int y, string filename, byte vars[], unsigned long options=DRAW_OPT_NORMAL); /** * Draw a graphic image from byte array with parameters. * Draw a graphic image byte array on the screen at the specified x and y location * using an array of parameters. * Optionally specify drawing options. If this argument is not specified it * defaults to \ref DRAW_OPT_NORMAL. Valid display option constants are listed in * the \ref DisplayDrawOptionConstants group. If the file cannot be found then * nothing will be drawn and no errors will be reported. * \sa SysDrawGraphicArray, DrawGraphicArrayType * * \param x The x value for the position of the graphic image. * \param y The y value for the position of the graphic image. * \param data The byte array of the RIC graphic image. * \param vars The byte array of parameters. * \param options The optional drawing options. * \return The result of the drawing operation. */ inline char GraphicArrayOutEx(int x, int y, byte data[], byte vars[], unsigned long options=DRAW_OPT_NORMAL); /** * Read pixel data from the normal display buffer. * Read "cnt" bytes from the normal display memory into the data array. Start * reading from the specified x, line coordinate. Each byte of data read from * screen memory is a vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param x The desired x position from which to read pixel data. * \param line The desired line from which to read pixel data. * \param cnt The number of bytes of pixel data to read. * \param data The array of bytes into which pixel data is read. */ inline void GetDisplayNormal(const byte x, const byte line, unsigned int cnt, byte & data[]); /** * Write pixel data to the normal display buffer. * Write "cnt" bytes to the normal display memory from the data array. Start * writing at the specified x, line coordinate. Each byte of data is a * vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param x The desired x position where you wish to write pixel data. * \param line The desired line where you wish to write pixel data. * \param cnt The number of bytes of pixel data to write. * \param data The array of bytes from which pixel data is read. */ inline void SetDisplayNormal(const byte x, const byte line, unsigned int cnt, byte data[]); /** * Read pixel data from the popup display buffer. * Read "cnt" bytes from the popup display memory into the data array. Start * reading from the specified x, line coordinate. Each byte of data read from * screen memory is a vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param x The desired x position from which to read pixel data. * \param line The desired line from which to read pixel data. * \param cnt The number of bytes of pixel data to read. * \param data The array of bytes into which pixel data is read. */ inline void GetDisplayPopup(const byte x, const byte line, unsigned int cnt, byte & data[]); /** * Write pixel data to the popup display buffer. * Write "cnt" bytes to the popup display memory from the data array. Start * writing at the specified x, line coordinate. Each byte of data is a * vertical strip of 8 bits at the desired location. Each * bit represents a single pixel on the LCD screen. Use TEXTLINE_1 through * TEXTLINE_8 for the "line" parameter. * * \param x The desired x position where you wish to write pixel data. * \param line The desired line where you wish to write pixel data. * \param cnt The number of bytes of pixel data to write. * \param data The array of bytes from which pixel data is read. */ inline void SetDisplayPopup(const byte x, const byte line, unsigned int cnt, byte data[]); /** * Read the display erase mask value. * This function lets you read the current display erase mask value. * \return The current display erase mask value. */ inline unsigned long DisplayEraseMask(); /** * Read the display update mask value. * This function lets you read the current display update mask value. * \return The current display update mask. */ inline unsigned long DisplayUpdateMask(); /** * Read the display font memory address. * This function lets you read the current display font memory address. * \return The current display font memory address. */ inline unsigned long DisplayFont(); /** * Read the display memory address. * This function lets you read the current display memory address. * \return The current display memory address. */ inline unsigned long DisplayDisplay(); /** * Read the display flags. * This function lets you read the current display flags. * Valid flag values are listed in the \ref DisplayFlagsGroup group. * \return The current display flags. */ inline byte DisplayFlags(); /** * Read the display text lines center flags. * This function lets you read the current display text lines center flags. * \return The current display text lines center flags. */ inline byte DisplayTextLinesCenterFlags(); /** * Draw text. * This function lets you draw text on the NXT LCD given the parameters you * pass in via the \ref DrawTextType structure. * * \param args The DrawTextType structure containing the drawing parameters. */ inline void SysDrawText(DrawTextType & args); /** * Draw a point. * This function lets you draw a pixel on the NXT LCD given the parameters you * pass in via the \ref DrawPointType structure. * * \param args The DrawPointType structure containing the drawing parameters. */ inline void SysDrawPoint(DrawPointType & args); /** * Draw a line. * This function lets you draw a line on the NXT LCD given the parameters you * pass in via the \ref DrawLineType structure. * * \param args The DrawLineType structure containing the drawing parameters. */ inline void SysDrawLine(DrawLineType & args); /** * Draw a circle. * This function lets you draw a circle on the NXT LCD given the parameters you pass * in via the \ref DrawCircleType structure. * * \param args The DrawCircleType structure containing the drawing parameters. */ inline void SysDrawCircle(DrawCircleType & args); /** * Draw a rectangle. * This function lets you draw a rectangle on the NXT LCD given the parameters * you pass in via the \ref DrawRectType structure. * * \param args The DrawRectType structure containing the drawing parameters. */ inline void SysDrawRect(DrawRectType & args); /** * Draw a graphic (RIC file). * This function lets you draw a graphic image (RIC file) on the NXT LCD given * the parameters you pass in via the \ref DrawGraphicType structure. * * \param args The DrawGraphicType structure containing the drawing parameters. */ inline void SysDrawGraphic(DrawGraphicType & args); /** * Set the screen mode. * This function lets you set the screen mode of the NXT LCD given the * parameters you pass in via the \ref DrawTextType structure. * * \param args The SetScreenModeType structure containing the screen mode parameters. */ inline void SysSetScreenMode(SetScreenModeType & args); #ifdef __ENHANCED_FIRMWARE /** * Execute any Display module command. * This function lets you directly execute the Display module's primary * drawing function using the values specified via the \ref * DisplayExecuteFunctionType structure. * * \param args The DisplayExecuteFunctionType structure containing the drawing parameters. */ inline void SysDisplayExecuteFunction(DisplayExecuteFunctionType & args); #if __FIRMWARE_VERSION > 107 /** * Read the display contrast setting. * This function lets you read the current display contrast setting. * \return The current display contrast (byte). * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline byte DisplayContrast(); /** * Draw a graphic image from a byte array. * This function lets you draw a graphic image on the NXT LCD given the parameters you pass * in via the \ref DrawGraphicArrayType structure. * * \param args The DrawGraphicArrayType structure containing the drawing parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SysDrawGraphicArray(DrawGraphicArrayType & args); /** * Draw a polygon. * This function lets you draw a polygon on the NXT LCD given the parameters you pass * in via the \ref DrawPolygonType structure. * * \param args The DrawPolygonType structure containing the drawing parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SysDrawPolygon(DrawPolygonType & args); /** * Draw an ellipse. * This function lets you draw an ellipse on the NXT LCD given the parameters you pass * in via the \ref DrawEllipseType structure. * * \param args The DrawEllipseType structure containing the drawing parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SysDrawEllipse(DrawEllipseType & args); /** * Draw text using a custom font. * This function lets you draw text on the NXT LCD using a custom font * with parameters you pass in via the \ref DrawFontType structure. * * \param args The DrawFontType structure containing the drawing parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SysDrawFont(DrawFontType & args); #endif #endif #else #define GetDisplayNormal(_x, _line, _cnt, _data) asm { __getDisplayNormal(_x, _line, _cnt, _data) } #define GetDisplayPopup(_x, _line, _cnt, _data) asm { __getDisplayPopup(_x, _line, _cnt, _data) } #define DisplayEraseMask() asm { GetDisplayEraseMask(__TMPLONG__) __RETURN__ __TMPLONG__ } #define DisplayUpdateMask() asm { GetDisplayUpdateMask(__TMPLONG__) __RETURN__ __TMPLONG__ } #define DisplayFont() asm { GetDisplayFont(__TMPLONG__) __RETURN__ __TMPLONG__ } #define DisplayDisplay() asm { GetDisplayDisplay(__TMPLONG__) __RETURN__ __TMPLONG__ } #define DisplayFlags() asm { GetDisplayFlags(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define DisplayTextLinesCenterFlags() asm { GetDisplayTextLinesCenterFlags(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetDisplayNormal(_x, _line, _cnt, _data) asm { __setDisplayNormal(_x, _line, _cnt, _data) } #define SetDisplayPopup(_x, _line, _cnt, _data) asm { __setDisplayPopup(_x, _line, _cnt, _data) } #define SysDrawText(_args) asm { \ compchktype _args, DrawTextType \ syscall DrawText, _args \ } #define SysDrawPoint(_args) asm { \ compchktype _args, DrawPointType \ syscall DrawPoint, _args \ } #define SysDrawLine(_args) asm { \ compchktype _args, DrawLineType \ syscall DrawLine, _args \ } #define SysDrawCircle(_args) asm { \ compchktype _args, DrawCircleType \ syscall DrawCircle, _args \ } #define SysDrawRect(_args) asm { \ compchktype _args, DrawRectType \ syscall DrawRect, _args \ } #define SysDrawGraphic(_args) asm { \ compchktype _args, DrawGraphicType \ syscall DrawGraphic, _args \ } #define SysSetScreenMode(_args) asm { \ compchktype _args, SetScreenModeType \ syscall SetScreenMode, _args \ } #ifdef __ENHANCED_FIRMWARE #define SysDisplayExecuteFunction(_args) asm { \ compchktype _args, DisplayExecuteFunctionType \ syscall DisplayExecuteFunction, _args \ } #if __FIRMWARE_VERSION > 107 #define DisplayContrast() asm { GetDisplayContrast(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SysDrawGraphicArray(_args) asm { \ compchktype _args, DrawGraphicArrayType \ syscall DrawGraphicArray, _args \ } #define SysDrawPolygon(_args) asm { \ compchktype _args, DrawPolygonType \ syscall DrawPolygon, _args \ } #define SysDrawEllipse(_args) asm { \ compchktype _args, DrawEllipseType \ syscall DrawEllipse, _args \ } #define SysDrawFont(_args) asm { \ compchktype _args, DrawFontType \ syscall DrawFont, _args \ } #endif #endif #endif /** * Clear LCD screen. * This function lets you clear the NXT LCD to a blank screen. */ inline void ClearScreen() { asm { PointOutEx(200, 200, TRUE) } } /** * Clear a line on the LCD screen. * This function lets you clear a single line on the NXT LCD. * \param line The line you want to clear. See \ref LineConstants. */ inline void ClearLine(byte line) { asm { TextOutEx(0, line, __BlankLine, 0) } } /** * Set the display font memory address. * This function lets you set the current display font memory address. * * \param fontaddr The new display font memory address. */ inline void SetDisplayFont(unsigned long fontaddr) { asm { __setDisplayFont(fontaddr) } } /** * Set the display memory address. * This function lets you set the current display memory address. * * \param dispaddr The new display memory address. */ inline void SetDisplayDisplay(unsigned long dispaddr) { asm { __setDisplayDisplay(dispaddr) } } /** * Set the display erase mask. * This function lets you set the current display erase mask. * * \param eraseMask The new display erase mask. */ inline void SetDisplayEraseMask(unsigned long eraseMask) { asm { __setDisplayEraseMask(eraseMask) } } /** * Set the display flags. * This function lets you set the current display flags. * * \param flags The new display flags. See \ref DisplayFlagsGroup. */ inline void SetDisplayFlags(byte flags) { asm { __setDisplayFlags(flags) } } /** * Set the display text lines center flags. * This function lets you set the current display text lines center flags. * * \param ctrFlags The new display text lines center flags. */ inline void SetDisplayTextLinesCenterFlags(byte ctrFlags) { asm { __setDisplayTextLinesCenterFlags(ctrFlags) } } /** * Set the display update mask. * This function lets you set the current display update mask. * * \param updateMask The new display update mask. */ inline void SetDisplayUpdateMask(unsigned long updateMask) { asm { __setDisplayUpdateMask(updateMask) } } #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) /** * Set the display contrast. * This function lets you set the display contrast setting. * * \param contrast The desired display contrast. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SetDisplayContrast(byte contrast) { asm { __setDisplayContrast(contrast) } } #endif /** @} */ // end of DisplayModuleFunctions group /** @} */ // end of DisplayModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// SOUND MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup SoundModule * @{ */ /** @defgroup SoundModuleTypes Sound module types * Types used by various sound module functions. * @{ */ /** * Type used with the PlayTones API function. * An array of this structure is used when calling the \ref PlayTones * API function. * \sa PlayTones() */ struct Tone { unsigned int Frequency; /*!< The tone frequency. See the \ref ToneConstants group. */ unsigned int Duration; /*!< The tone duration in milliseconds. See the \ref TimeConstants group. */ }; /** * Parameters for the SoundPlayFile system call. * This structure is used when calling the \ref SysSoundPlayFile system call * function. * \sa SysSoundPlayFile() */ struct SoundPlayFileType { char Result; /*!< The function call result, always \ref NO_ERR. */ string Filename; /*!< The name of the file to play. */ bool Loop; /*!< If true, loops at end of file. */ byte SoundLevel; /*!< The sound level. Valid values range from 0 to 4. */ }; /** * Parameters for the SoundPlayTone system call. * This structure is used when calling the \ref SysSoundPlayTone system call * function. * \sa SysSoundPlayTone() */ struct SoundPlayToneType { char Result; /*!< The function call result, always \ref NO_ERR. */ unsigned int Frequency; /*!< The tone frequency. See the \ref ToneConstants group. */ unsigned int Duration; /*!< The tone duration in milliseconds. See the \ref TimeConstants group. */ bool Loop; /*!< If true, loops forever. */ byte SoundLevel; /*!< The sound level. Valid values range from 0 to 4. */ }; /** * Parameters for the SoundGetState system call. * This structure is used when calling the \ref SysSoundGetState system call * function. * \sa SysSoundGetState() */ struct SoundGetStateType { byte State; /*!< The returned sound state. See the \ref SoundStateConstants group. */ byte Flags; /*!< The returned sound flags. See the \ref SoundFlagsConstants group. */ }; /** * Parameters for the SoundSetState system call. * This structure is used when calling the \ref SysSoundSetState system call * function. * \sa SysSoundSetState() */ struct SoundSetStateType { byte Result; /*!< The function call result, same as State. */ byte State; /*!< The new sound state. See the \ref SoundStateConstants group. */ byte Flags; /*!< The new sound flags. See the \ref SoundFlagsConstants group. */ }; /** @} */ // end of SoundModuleTypes group /** @defgroup SoundModuleFunctions Sound module functions * Functions for accessing and modifying sound module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Play a file. * Play the specified file. The filename may be any valid string expression. * The sound file can either be an RSO file containing PCM or compressed ADPCM * samples or it can be an NXT melody (RMD) file containing frequency and * duration values. * * \param filename The name of the sound or melody file to play. */ inline char PlayFile(string filename); /** * Play a file with extra options. * Play the specified file. The filename may be any valid string expression. * Volume should be a number from 0 (silent) to 4 (loudest). Play the file * repeatedly if loop is true. * The sound file can either be an RSO file containing PCM or compressed ADPCM * samples or it can be an NXT melody (RMD) file containing frequency and * duration values. * * \param filename The name of the sound or melody file to play. * \param volume The desired tone volume. * \param loop A boolean flag indicating whether to play the file repeatedly. */ inline char PlayFileEx(string filename, byte volume, bool loop); /** * Play a tone. * Play a single tone of the specified frequency and duration. The frequency is * in Hz (see the \ref ToneConstants group). The duration is in 1000ths of a * second (see the \ref TimeConstants group). The tone is played at the loudest * sound level supported by the firmware and it is not looped. * * \param frequency The desired tone frequency, in Hz. * \param duration The desired tone duration, in ms. */ inline char PlayTone(unsigned int frequency, unsigned int duration); /** * Play a tone with extra options. * Play a single tone of the specified frequency, duration, and volume. The * frequency is in Hz (see the \ref ToneConstants group). The duration is in * 1000ths of a second (see the \ref TimeConstants group). Volume should be a * number from 0 (silent) to 4 (loudest). Play the tone repeatedly if loop is * true. * * \param frequency The desired tone frequency, in Hz. * \param duration The desired tone duration, in ms. * \param volume The desired tone volume. * \param loop A boolean flag indicating whether to play the tone repeatedly. */ inline char PlayToneEx(unsigned int frequency, unsigned int duration, byte volume, bool loop); /** * Get sound module state. * Return the current sound module state. See the \ref SoundStateConstants group. * * \sa SetSoundModuleState(), SysSoundSetState(), SysSoundGetState() * \return The current sound module state. */ inline byte SoundState(); /** * Get sound module flags. * Return the current sound module flags. See the \ref SoundFlagsConstants group. * * \sa SetSoundFlags(), SysSoundSetState(), SysSoundGetState() * \return The current sound module flags. */ inline byte SoundFlags(); /** * Stop sound. * Stop playing of the current tone or file. * * \return The result \todo ?. */ inline byte StopSound(); /** * Get sound frequency. * Return the current sound frequency. * * \sa SetSoundFrequency() * \return The current sound frequency. */ inline unsigned int SoundFrequency(); /** * Get sound duration. * Return the current sound duration. * * \sa SetSoundDuration() * \return The current sound duration. */ inline unsigned int SoundDuration(); /** * Get sample rate. * Return the current sound sample rate. * * \sa SetSoundSampleRate() * \return The current sound sample rate. */ inline unsigned int SoundSampleRate(); /** * Get sound mode. * Return the current sound mode. See the \ref SoundModeConstants group. * * \sa SetSoundMode() * \return The current sound mode. */ inline byte SoundMode(); /** * Get volume. * Return the current sound volume. * * \sa SetSoundVolume() * \return The current sound volume. */ inline byte SoundVolume(); /** * Set sound duration. * Set the sound duration. * * \sa SoundDuration() * \param duration The new sound duration */ inline void SetSoundDuration(unsigned int duration); /** * Set sound module flags. * Set the sound module flags. See the \ref SoundFlagsConstants group. * * \sa SetSoundFlags(), SysSoundSetState(), SysSoundGetState() * \param flags The new sound module flags */ inline void SetSoundFlags(byte flags); /** * Set sound frequency. * Set the sound frequency. * * \sa SoundFrequency() * \param frequency The new sound frequency */ inline void SetSoundFrequency(unsigned int frequency); /** * Set sound mode. * Set the sound mode. See the \ref SoundModeConstants group. * * \sa SoundMode() * \param mode The new sound mode */ inline void SetSoundMode(byte mode); /** * Set sound module state. * Set the sound module state. See the \ref SoundStateConstants group. * * \sa SoundState(), SysSoundSetState(), SysSoundGetState() * \param state The new sound state */ inline void SetSoundModuleState(byte state); /** * Set sample rate. * Set the sound sample rate. * * \sa SoundSampleRate() * \param sampleRate The new sample rate */ inline void SetSoundSampleRate(unsigned int sampleRate); /** * Set sound volume. * Set the sound volume. * * \sa SoundVolume() * \param volume The new volume */ inline void SetSoundVolume(byte volume); /** * Play sound file. * This function lets you play a sound file given the parameters you pass in * via the \ref SoundPlayFileType structure. The sound file can either be an * RSO file containing PCM or compressed ADPCM samples or it can be an NXT * melody (RMD) file containing frequency and duration values. * * \param args The SoundPlayFileType structure containing the needed * parameters. */ inline void SysSoundPlayFile(SoundPlayFileType & args); /** * Play tone. * This function lets you play a tone given the parameters you pass in via the * \ref SoundPlayToneType structure. * * \param args The SoundPlayToneType structure containing the needed * parameters. */ inline void SysSoundPlayTone(SoundPlayToneType & args); /** * Get sound state. * This function lets you retrieve information about the sound module state * via the \ref SoundGetStateType structure. * * \param args The SoundGetStateType structure containing the needed * parameters. */ inline void SysSoundGetState(SoundGetStateType & args); /** * Set sound state. * This function lets you set sound module state settings via the \ref * SoundSetStateType structure. * * \param args The SoundSetStateType structure containing the needed * parameters. */ inline void SysSoundSetState(SoundSetStateType & args); #else #define PlayTone(_f, _d) PlayToneEx(_f, _d, 4, 0) #define PlayFile(_f) PlayFileEx(_f, 4, 0) #define SoundState() asm { GetSoundState(__RETVAL__, __TMPBYTE__) } #define SoundFlags() asm { GetSoundState(__TMPBYTE__, __RETVAL__) } #define StopSound() asm { __setSoundState(SOUND_STATE_STOP, 0, __RETVAL__) } #define SoundFrequency() asm { GetSoundFrequency(__TMPWORD__) __RETURN__ __TMPWORD__ } #define SoundDuration() asm { GetSoundDuration(__TMPWORD__) __RETURN__ __TMPWORD__ } #define SoundSampleRate() asm { GetSoundSampleRate(__TMPWORD__) __RETURN__ __TMPWORD__ } #define SoundMode() asm { GetSoundMode(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SoundVolume() asm { GetSoundVolume(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetSoundFrequency(_n) asm { __setSoundFrequency(_n) } #define SetSoundDuration(_n) asm { __setSoundDuration(_n) } #define SetSoundSampleRate(_n) asm { __setSoundSampleRate(_n) } #define SetSoundFlags(_n) asm { __setSoundFlags(_n) } #define SetSoundModuleState(_n) asm { __setSoundModuleState(_n) } #define SetSoundMode(_n) asm { __setSoundMode(_n) } #define SetSoundVolume(_n) asm { __setSoundVolume(_n) } #define SysSoundPlayFile(_args) asm { \ compchktype _args, SoundPlayFileType \ syscall SoundPlayFile, _args \ } #define SysSoundPlayTone(_args) asm { \ compchktype _args, SoundPlayToneType \ syscall SoundPlayTone, _args \ } #define SysSoundGetState(_args) asm { \ compchktype _args, SoundGetStateType \ syscall SoundGetState, _args \ } #define SysSoundSetState(_args) asm { \ compchktype _args, SoundSetStateType \ syscall SoundSetState, _args \ } #endif /** * Play a system sound. * Play a sound that mimics the RCX system sounds using one of the * \ref RCXSoundConstants. * * * * * * * * *
aCodeResulting Sound
\ref SOUND_CLICKkey click sound
\ref SOUND_DOUBLE_BEEPdouble beep
\ref SOUND_DOWNsweep down
\ref SOUND_UPsweep up
\ref SOUND_LOW_BEEPerror sound
\ref SOUND_FAST_UPfast sweep up
* \param aCode The system sound to play. See \ref RCXSoundConstants. */ void PlaySound(const int &aCode) { if (aCode == SOUND_CLICK) PlayTone(600, MS_200); else if (aCode == SOUND_DOUBLE_BEEP) { PlayTone(600, MS_150); asm { wait MS_200 }; PlayTone(600, MS_150); asm { wait MS_150 }; } else if (aCode == SOUND_UP) for (int i = 4; i < 8; i++) { PlayTone(TONE_C5 * i / 4, MS_100); asm { wait MS_100 }; } else if (aCode == SOUND_DOWN) for (int i = 7; i > 3; i--) { PlayTone(TONE_C5 * i / 4, MS_100); asm { wait MS_100 }; } else if (aCode == SOUND_LOW_BEEP) { PlayTone(100, MS_500); asm { wait MS_500 }; } else if (aCode == SOUND_FAST_UP) for (int i = 4; i < 8; i++) { PlayTone(TONE_C5 * i / 4, MS_50); asm { wait MS_50 }; } } /** * Play multiple tones. * Play a series of tones contained in the tones array. Each element * in the array is an instance of the \ref Tone structure, containing * a frequency and a duration. * * \param tones The array of tones to play. */ void PlayTones(Tone tones[]) { for (int i = 0; i < asm { arrsize __RETVAL__, tones }; i++) { Tone tmp = tones[i]; PlayTone(tmp.Frequency, tmp.Duration); asm { waitv tmp.Duration }; } } /** @} */ // end of SoundModuleFunctions group /** @} */ // end of SoundModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// LOWSPEED MODULE /////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup LowSpeedModule * @{ */ /** @defgroup LowSpeedModuleTypes LowSpeed module types * Types used by various low speed module functions. * @{ */ /** * Parameters for the CommLSWrite system call. * This structure is used when calling the \ref SysCommLSWrite system call * function. * \sa SysCommLSWrite() */ struct CommLSWriteType { char Result; /*!< The function call result. Possible values include \ref ERR_COMM_CHAN_INVALID, \ref ERR_COMM_CHAN_NOT_READY, \ref ERR_INVALID_SIZE, and \ref NO_ERR. */ byte Port; /*!< The port to which the I2C device is connected. */ byte Buffer[]; /*!< The buffer containing data to be written to the I2C device. */ byte ReturnLen; /*!< The number of bytes that you want to read from the I2C device after writing the data. If no read is planned set this to zero. */ }; /** * Parameters for the CommLSRead system call. * This structure is used when calling the \ref SysCommLSRead system call * function. * \sa SysCommLSRead() */ struct CommLSReadType { char Result; /*!< The function call result. Possible values include \ref ERR_COMM_BUS_ERR, \ref ERR_COMM_CHAN_INVALID, \ref ERR_COMM_CHAN_NOT_READY, \ref ERR_INVALID_SIZE, \ref STAT_COMM_PENDING, and \ref NO_ERR. */ byte Port; /*!< The port to which the I2C device is connected. */ byte Buffer[]; /*!< The buffer used to store the bytes read from the I2C device. */ byte BufferLen; /*!< The size of the output buffer on input. This field is not updated during the function call. */ }; /** * Parameters for the CommLSCheckStatus system call. * This structure is used when calling the \ref SysCommLSCheckStatus system * call function. * \sa SysCommLSCheckStatus() */ struct CommLSCheckStatusType { char Result; /*!< The function call result. Possible values include \ref ERR_COMM_BUS_ERR, \ref ERR_COMM_CHAN_INVALID, \ref ERR_COMM_CHAN_NOT_READY, \ref STAT_COMM_PENDING, and \ref NO_ERR. */ byte Port; /*!< The port to which the I2C device is connected. */ byte BytesReady; /*!< The number of bytes ready to read from the specified port. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the CommLSWriteEx system call. * This structure is used when calling the \ref SysCommLSWriteEx system call * function. * \sa SysCommLSWriteEx() */ struct CommLSWriteExType { char Result; /*!< The function call result. Possible values include \ref ERR_COMM_CHAN_INVALID, \ref ERR_COMM_CHAN_NOT_READY, \ref ERR_INVALID_SIZE, and \ref NO_ERR. */ byte Port; /*!< The port to which the I2C device is connected. */ byte Buffer[]; /*!< The buffer written to the I2C device. */ byte ReturnLen; /*!< The number of bytes that you want to read from the I2C device. */ bool NoRestartOnRead; /*!< Should a restart occur before reading from the device? */ }; #endif /** @} */ // end of LowSpeedModuleTypes group /** @defgroup LowSpeedModuleFunctions LowSpeed module functions * Functions for accessing and modifying low speed module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Read ultrasonic sensor value. * Return the ultrasonic sensor distance value. Since an * ultrasonic sensor is an I2C digital sensor its value cannot be read using * the standard Sensor(n) value. * The port must be configured as a Lowspeed port before using this function. * \param port The port to which the ultrasonic sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \return The ultrasonic sensor distance value (0..255) */ inline byte SensorUS(const byte port); /** * Read multiple ultrasonic sensor values. * Return eight ultrasonic sensor distance values. * \param port The port to which the ultrasonic sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param values An array of bytes that will contain the 8 distance values * read from the ultrasonic sensor. * \return A status code indicating whether the read completed successfully or not. * See \ref CommLSReadType for possible result values. */ inline char ReadSensorUSEx(const byte port, byte & values[]); /** * Read the LEGO EMeter values. * Read all the LEGO EMeter register values. * They must all be read at once to ensure data coherency. * * \param port The port to which the LEGO EMeter sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param vIn Input voltage * \param aIn Input current * \param vOut Output voltage * \param aOut Output current * \param joules The number of joules stored in the EMeter * \param wIn The number of watts generated * \param wOut The number of watts consumed * \return A status code indicating whether the read completed successfully or not. * See \ref CommLSReadType for possible result values. */ inline char ReadSensorEMeter(const byte & port, float &vIn, float &aIn, float &vOut, float &aOut, int &joules, float &wIn, float &wOut); /** * Configure LEGO Temperature sensor options. * Set various LEGO Temperature sensor options. * * \param port The port to which the temperature sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param config The temperature sensor configuration settings. See * \ref TempI2CConstants for configuration constants that can be ORed or added * together. * \return A status code indicating whether the read completed successfully or not. * See \ref CommLSReadType for possible Result values. */ inline char ConfigureTemperatureSensor(const byte & port, const byte & config); /** * Read the LEGO Temperature sensor value. * Return the temperature sensor value in degrees celcius. Since a * temperature sensor is an I2C digital sensor its value cannot be read using * the standard Sensor(n) value. * The port must be configured as a temperature sensor port before using this * function. Use \ref SetSensorTemperature to configure the port. * \param port The port to which the temperature sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \return The temperature sensor value in degrees celcius. */ inline float SensorTemperature(const byte & port); /** * Get lowspeed status. * This method checks the status of the I2C communication on the specified * port. If the last operation on this port was a successful LowspeedWrite * call that requested response data from the device then bytesready will * be set to the number of bytes in the internal read buffer. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param bytesready The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref LowspeedRead or \ref LowspeedWrite while LowspeedStatus returns * \ref STAT_COMM_PENDING. * \sa I2CStatus, I2CRead, I2CWrite, I2CCheckStatus, I2CBytesReady, LowspeedRead, * LowspeedWrite, and LowspeedCheckStatus */ inline long LowspeedStatus(const byte port, byte & bytesready); /** * Check lowspeed status. * This method checks the status of the I2C communication on the specified * port. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref LowspeedRead or \ref LowspeedWrite while LowspeedCheckStatus returns * \ref STAT_COMM_PENDING. * \sa I2CCheckStatus, I2CRead, I2CWrite, I2CStatus, I2CBytesReady, LowspeedRead, * LowspeedWrite, and LowspeedStatus */ inline long LowspeedCheckStatus(const byte port); /** * Get lowspeed bytes ready. * This method checks the number of bytes that are ready to be read on the * specified port. If the last operation on this port was a successful * LowspeedWrite call that requested response data from the device then the * return value will be the number of bytes in the internal read buffer. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \return The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \sa I2CCheckStatus, I2CRead, I2CWrite, I2CStatus, I2CBytesReady, LowspeedRead, * LowspeedWrite, and LowspeedStatus */ inline byte LowspeedBytesReady(const byte port); /** * Write lowspeed data. * This method starts a transaction to write the bytes contained in the array * buffer to the I2C device on the specified port. It also tells the I2C device * the number of bytes that should be included in the response. The maximum * number of bytes that can be written or read is 16. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param retlen The number of bytes that should be returned by the I2C device. * \param buffer A byte array containing the address of the I2C device, the I2C * device register at which to write data, and up to 14 bytes of data to be * written at the specified register. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSWriteType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa I2CCheckStatus, I2CRead, I2CWrite, I2CStatus, I2CBytesReady, LowspeedRead, * LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ inline long LowspeedWrite(const byte port, byte retlen, byte buffer[]); /** * Read lowspeed data. * Read the specified number of bytes from the I2C device on the specified * port and store the bytes read in the byte array buffer provided. The maximum * number of bytes that can be written or read is 16. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param buflen The initial size of the output buffer. * \param buffer A byte array that contains the data read from the internal I2C * buffer. If the return value is negative then the output buffer will be empty. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSReadType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa I2CCheckStatus, I2CRead, I2CWrite, I2CStatus, I2CBytesReady, LowspeedWrite, * LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ inline long LowspeedRead(const byte port, byte buflen, byte & buffer[]); /** * Get I2C status. * This method checks the status of the I2C communication on the specified * port. If the last operation on this port was a successful I2CWrite * call that requested response data from the device then bytesready will * be set to the number of bytes in the internal read buffer. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param bytesready The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible return values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref I2CRead or \ref I2CWrite while I2CStatus returns * \ref STAT_COMM_PENDING. * \sa I2CCheckStatus, I2CRead, I2CWrite, LowspeedStatus, LowspeedRead, * LowspeedWrite, and LowspeedCheckStatus */ inline long I2CStatus(const byte port, byte & bytesready); /** * Check I2C status. * This method checks the status of the I2C communication on the specified * port. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * Avoid calls to \ref I2CRead or \ref I2CWrite while this function returns * \ref STAT_COMM_PENDING. * \sa I2CStatus, I2CRead, I2CWrite, LowspeedStatus, LowspeedRead, * LowspeedWrite, and LowspeedCheckStatus */ inline long I2CCheckStatus(const byte port); /** * Get I2C bytes ready. * This method checks the number of bytes that are ready to be read on the * specified port. If the last operation on this port was a successful * I2CWrite call that requested response data from the device then the * return value will be the number of bytes in the internal read buffer. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \return The number of bytes available to be read from the internal I2C buffer. * The maximum number of bytes that can be read is 16. * \sa I2CCheckStatus, I2CRead, I2CWrite, I2CStatus, LowspeedBytesReady, LowspeedRead, * LowspeedWrite, and LowspeedStatus */ inline byte I2CBytesReady(const byte port); /** * Write I2C data. * This method starts a transaction to write the bytes contained in the array * buffer to the I2C device on the specified port. It also tells the I2C device * the number of bytes that should be included in the response. The maximum * number of bytes that can be written or read is 16. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param retlen The number of bytes that should be returned by the I2C device. * \param buffer A byte array containing the address of the I2C device, the I2C * device register at which to write data, and up to 14 bytes of data to be * written at the specified register. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSWriteType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa I2CCheckStatus, I2CRead, I2CStatus, I2CBytesReady, LowspeedRead, LowspeedWrite, * LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ inline long I2CWrite(const byte port, byte retlen, byte buffer[]); /** * Read I2C data. * Read the specified number of bytes from the I2C device on the specified * port and store the bytes read in the byte array buffer provided. The maximum * number of bytes that can be written or read is 16. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param buflen The initial size of the output buffer. * \param buffer A byte array that contains the data read from the internal I2C * buffer. If the return value is negative then the output buffer will be empty. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSReadType for possible result values. If the return * value is \ref NO_ERR then the last operation did not cause any errors. * \sa I2CCheckStatus, I2CWrite, I2CStatus, I2CBytesReady, LowspeedRead, LowspeedWrite, * LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ inline long I2CRead(const byte port, byte buflen, byte & buffer[]); /** * Perform an I2C write/read transaction. * This method writes the bytes contained in the input buffer (inbuf) to the * I2C device on the specified port, checks for the specified number of bytes * to be ready for reading, and then tries to read the specified number (count) * of bytes from the I2C device into the output buffer (outbuf). * * This is a higher-level wrapper around the three main I2C functions. It also * maintains a "last good read" buffer and returns values from that buffer if * the I2C communication transaction fails. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param inbuf A byte array containing the address of the I2C device, the I2C * device register at which to write data, and up to 14 bytes of data to be * written at the specified register. * \param count The number of bytes that should be returned by the I2C device. * On output count is set to the number of bytes in outbuf. * \param outbuf A byte array that contains the data read from the internal I2C * buffer. * \return Returns true or false indicating whether the I2C transaction * succeeded or failed. * \sa I2CCheckStatus, I2CWrite, I2CStatus, I2CBytesReady, I2CRead, LowspeedRead, LowspeedWrite, * LowspeedCheckStatus, LowspeedBytesReady, and LowspeedStatus */ inline long I2CBytes(const byte port, byte inbuf[], byte & count, byte & outbuf[]); /** * Read I2C register. * Read a single byte from an I2C device register. * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param i2caddr The I2C device address. * \param reg The I2C device register from which to read a single byte. * \param out The single byte read from the I2C device. * \return A status code indicating whether the read completed successfully or not. * See \ref CommLSReadType for possible result values. */ inline char ReadI2CRegister(byte port, byte i2caddr, byte reg, byte & out); /** * Write I2C register. * Write a single byte to an I2C device register. * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param i2caddr The I2C device address. * \param reg The I2C device register to which to write a single byte. * \param val The byte to write to the I2C device. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char WriteI2CRegister(byte port, byte i2caddr, byte reg, byte val); /** * Read I2C device information. * Read standard I2C device information: version, vendor, and device ID. The * I2C device uses the specified address. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param i2caddr The I2C device address. * \param info A value indicating the type of device information you are requesting. * See \ref GenericI2CConstants. * \return A string containing the requested device information. */ inline string I2CDeviceInfo(byte port, byte i2caddr, byte info); /** * Read I2C device version. * Read standard I2C device version. The I2C device uses the specified address. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param i2caddr The I2C device address. * \return A string containing the device version. */ inline string I2CVersion(byte port, byte i2caddr); /** * Read I2C device vendor. * Read standard I2C device vendor. The I2C device uses the specified address. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param i2caddr The I2C device address. * \return A string containing the device vendor. */ inline string I2CVendorId(byte port, byte i2caddr); /** * Read I2C device identifier. * Read standard I2C device identifier. The I2C device uses the specified address. * * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param i2caddr The I2C device address. * \return A string containing the device identifier. */ inline string I2CDeviceId(byte port, byte i2caddr); /** * Send an I2C command. * Send a command to an I2C device at the standard command register: \ref I2C_REG_CMD. * The I2C device uses the specified address. * \param port The port to which the I2C device is attached. See the * \ref InPorts group. You may use a constant or a variable. Constants should * be used where possible to avoid blocking access to I2C devices on other * ports by code running on other threads. * \param i2caddr The I2C device address. * \param cmd The command to send to the I2C device. * \return A status code indicating whether the write completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline long I2CSendCommand(byte port, byte i2caddr, byte cmd); /** @defgroup LowLevelLowSpeedModuleFunctions Low level LowSpeed module functions * Low level functions for accessing low speed module features. * @{ */ /** * Get I2C input buffer data. * This method reads count bytes of data from the I2C input buffer for the * specified port and writes it to the buffer provided. * \param port A constant port number (S1..S4). See \ref InPorts. * \param offset A constant offset into the I2C input buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the I2C input buffer. */ inline void GetLSInputBuffer(const byte port, const byte offset, byte cnt, byte & data[]); /** * Get I2C output buffer data. * This method reads cnt bytes of data from the I2C output buffer for the * specified port and writes it to the buffer provided. * \param port A constant port number (S1..S4). See \ref InPorts. * \param offset A constant offset into the I2C output buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the I2C output buffer. */ inline void GetLSOutputBuffer(const byte port, const byte offset, byte cnt, byte & data[]); /** * Get I2C input buffer in-pointer. * This method returns the value of the input pointer of the I2C input * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C input buffer's in-pointer value. */ inline byte LSInputBufferInPtr(const byte port); /** * Get I2C input buffer out-pointer. * This method returns the value of the output pointer of the I2C input * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C input buffer's out-pointer value. */ inline byte LSInputBufferOutPtr(const byte port); /** * Get I2C input buffer bytes to rx. * This method returns the value of the bytes to rx field of the I2C input * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C input buffer's bytes to rx value. */ inline byte LSInputBufferBytesToRx(const byte port); /** * Get I2C output buffer in-pointer. * This method returns the value of the input pointer of the I2C output * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C output buffer's in-pointer value. */ inline byte LSOutputBufferInPtr(const byte port); /** * Get I2C output buffer out-pointer. * This method returns the value of the output pointer of the I2C output * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C output buffer's out-pointer value. */ inline byte LSOutputBufferOutPtr(const byte port); /** * Get I2C output buffer bytes to rx. * This method returns the value of the bytes to rx field of the I2C output * buffer for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C output buffer's bytes to rx value. */ inline byte LSOutputBufferBytesToRx(const byte port); /** * Get I2C mode. * This method returns the value of the I2C mode for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C port mode. See \ref LowSpeedModeConstants. */ inline byte LSMode(const byte port); /** * Get I2C channel state. * This method returns the value of the I2C channel state for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C port channel state. See \ref LowSpeedChannelStateConstants. */ inline byte LSChannelState(const byte port); /** * Get I2C error type. * This method returns the value of the I2C error type for the specified port. * \param port A constant port number (S1..S4). See \ref InPorts. * \return The I2C port error type. See \ref LowSpeedErrorTypeConstants. */ inline byte LSErrorType(const byte port); /** * Get I2C state. * This method returns the value of the I2C state. * \return The I2C state. See \ref LowSpeedStateConstants. */ inline byte LSState(); /** * Get I2C speed. * This method returns the value of the I2C speed. * \return The I2C speed. * \warning This function is unimplemented within the firmware. */ inline byte LSSpeed(); #ifdef __ENHANCED_FIRMWARE /** * Get I2C no restart on read setting. * This method returns the value of the I2C no restart on read field. * \return The I2C no restart on read field. See \ref LowSpeedNoRestartConstants. */ inline byte LSNoRestartOnRead(); #endif /* // these low speed module IOMap fields are essentially read-only inline void SetLSInputBuffer(const byte port, const byte offset, byte cnt, byte data[]); inline void SetLSInputBufferInPtr(const byte port, byte n); inline void SetLSInputBufferOutPtr(const byte port, byte n); inline void SetLSInputBufferBytesToRx(const byte port, byte n); inline void SetLSOutputBuffer(const byte port, const byte offset, byte cnt, byte data[]); inline void SetLSOutputBufferInPtr(const byte port, byte n); inline void SetLSOutputBufferOutPtr(const byte port, n); inline void SetLSOutputBufferBytesToRx(const byte port, byte n); inline void SetLSMode(const byte port, const byte mode); inline void SetLSChannelState(const byte port, const byte chState); inline void SetLSErrorType(const byte port, const byte errType); inline void SetLSState(const byte lsState); inline void SetLSSpeed(const byte lsSpeed); #ifdef __ENHANCED_FIRMWARE inline void SetLSNoRestartOnRead(const byte lsNoRestart); #endif */ /** @} */ // end of LowLevelLowSpeedModuleFunctions group /** @defgroup LowSpeedModuleSystemCallFunctions LowSpeed module system call functions * System call functions for accessing low speed module features. * @{ */ /** * Write to a Lowspeed sensor. * This function lets you write to an I2C (Lowspeed) sensor using the values * specified via the \ref CommLSWriteType structure. * * \param args The CommLSWriteType structure containing the needed parameters. */ inline void SysCommLSWrite(CommLSWriteType & args); /** * Read from a Lowspeed sensor. * This function lets you read from an I2C (Lowspeed) sensor using the values * specified via the \ref CommLSReadType structure. * * \param args The CommLSReadType structure containing the needed parameters. */ inline void SysCommLSRead(CommLSReadType & args); /** * Check Lowspeed sensor status. * This function lets you check the status of an I2C (Lowspeed) sensor * transaction using the values specified via the \ref CommLSCheckStatusType * structure. * * \param args The CommLSCheckStatusType structure containing the needed * parameters. */ inline void SysCommLSCheckStatus(CommLSCheckStatusType & args); #ifdef __ENHANCED_FIRMWARE /** * Write to a Lowspeed sensor (extra). * This function lets you write to an I2C (Lowspeed) sensor using the values * specified via the \ref CommLSWriteExType structure. This is the same as the * SysCommLSWrite function except that you also can specify whether or not the * Lowspeed module should issue a restart command to the I2C device before * beginning to read data from the device. * * \param args The CommLSWriteExType structure containing the desired parameters. */ inline void SysCommLSWriteEx(CommLSWriteExType & args); #endif /** @} */ // end of LowSpeedModuleSystemCallFunctions group #else // ultrasonic sensor #define SensorUS(_p) asm { ReadSensorUS(_p, __RETVAL__) } #define ReadSensorUSEx(_port, _values) asm { __ReadSensorUSEx(_port, _values, __RETVAL__) } #define ReadSensorEMeter(_port, _vIn, _aIn, _vOut, _aOut, _joules, _wIn, _wOut) asm { __ReadSensorEMeter(_port, _vIn, _aIn, _vOut, _aOut, _joules, _wIn, _wOut, __RETVAL__) } #define ConfigureTemperatureSensor(_port, _config) asm { __TempSendCmd(_port, _config, __RETVAL__) } #if __FIRMWARE_VERSION > 107 #define SensorTemperature(_port) asm { __ReadSensorTemperature(_port, __FLTRETVAL__) } #else #define SensorTemperature(_port) asm { __ReadSensorTemperature(_port, __RETVAL__) } #endif #define ReadI2CRegister(_port, _i2caddr, _reg, _out) asm { __MSReadValue(_port, _i2caddr, _reg, 1, _out, __RETVAL__) } #define WriteI2CRegister(_port, _i2caddr, _reg, _val) asm { __MSWriteToRegister(_port, _i2caddr, _reg, _val, __RETVAL__) } #define LowspeedStatus(_port, _bready) asm { __lowspeedStatus(_port, _bready, __RETVAL__) } #define LowspeedCheckStatus(_port) asm { __lowspeedStatus(_port, __TMPBYTE__, __RETVAL__) } #define LowspeedBytesReady(_port) asm { __lowspeedStatus(_port, __RETVAL__, __TMPBYTE__) } #define LowspeedWrite(_port, _retlen, _buffer) asm { __lowspeedWrite(_port, _retlen, _buffer, __RETVAL__) } #define LowspeedRead(_port, _buflen, _buffer) asm { __lowspeedRead(_port, _buflen, _buffer, __RETVAL__) } #define I2CStatus(_port, _bready) LowspeedStatus(_port, _bready) #define I2CCheckStatus(_port) LowspeedCheckStatus(_port) #define I2CBytesReady(_port) LowspeedBytesReady(_port) #define I2CWrite(_port, _retlen, _buffer) LowspeedWrite(_port, _retlen, _buffer) #define I2CRead(_port, _buflen, _buffer) LowspeedRead(_port, _buflen, _buffer) #define I2CBytes(_port, _inbuf, _count, _outbuf) asm { ReadI2CBytes(_port, _inbuf, _count, _outbuf, __RETVAL__) } #define I2CDeviceInfo(_port, _i2caddr, _info) asm { ReadI2CDeviceInfo(_port, _i2caddr, _info, __STRRETVAL__) } #define I2CVersion(_port, _i2caddr) asm { ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_VERSION, __STRRETVAL__) } #define I2CVendorId(_port, _i2caddr) asm { ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_VENDOR_ID, __STRRETVAL__) } #define I2CDeviceId(_port, _i2caddr) asm { ReadI2CDeviceInfo(_port, _i2caddr, I2C_REG_DEVICE_ID, __STRRETVAL__) } #define I2CSendCommand(_port, _i2caddr, _cmd) asm { __I2CSendCmd(_port, _i2caddr, _cmd, __RETVAL__) } #define GetLSInputBuffer(_p, _offset, _cnt, _data) asm { __getLSInputBuffer(_p, _offset, _cnt, _data) } #define GetLSOutputBuffer(_p, _offset, _cnt, _data) asm { __getLSOutputBuffer(_p, _offset, _cnt, _data) } #define LSInputBufferInPtr(_p) asm { GetLSInputBufferInPtr(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSInputBufferOutPtr(_p) asm { GetLSInputBufferOutPtr(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSInputBufferBytesToRx(_p) asm { GetLSInputBufferBytesToRx(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSOutputBufferInPtr(_p) asm { GetLSOutputBufferInPtr(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSOutputBufferOutPtr(_p) asm { GetLSOutputBufferOutPtr(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSOutputBufferBytesToRx(_p) asm { GetLSOutputBufferBytesToRx(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSMode(_p) asm { GetLSMode(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSChannelState(_p) asm { GetLSChannelState(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSErrorType(_p) asm { GetLSErrorType(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSState() asm { GetLSState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LSSpeed() asm { GetLSSpeed(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #ifdef __ENHANCED_FIRMWARE #define LSNoRestartOnRead(_n) asm { GetLSNoRestartOnRead(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #endif #define SetLSInputBuffer(_p, _offset, _cnt, _data) asm { __setLSInputBuffer(_p, _offset, _cnt, _data) } #define SetLSInputBufferInPtr(_p, _n) asm { __setLSInputBufferInPtr(_p, _n) } #define SetLSInputBufferOutPtr(_p, _n) asm { __setLSInputBufferOutPtr(_p, _n) } #define SetLSInputBufferBytesToRx(_p, _n) asm { __setLSInputBufferBytesToRx(_p, _n) } #define SetLSOutputBuffer(_p, _offset, _cnt, _data) asm { __setLSOutputBuffer(_p, _offset, _cnt, _data) } #define SetLSOutputBufferInPtr(_p, _n) asm { __setLSOutputBufferInPtr(_p, _n) } #define SetLSOutputBufferOutPtr(_p, _n) asm { __setLSOutputBufferOutPtr(_p, _n) } #define SetLSOutputBufferBytesToRx(_p, _n) asm { __setLSOutputBufferBytesToRx(_p, _n) } #define SetLSMode(_p, _n) asm { __setLSMode(_p, _n) } #define SetLSChannelState(_p, _n) asm { __setLSChannelState(_p, _n) } #define SetLSErrorType(_p, _n) asm { __setLSErrorType(_p, _n) } #define SetLSState(_n) asm { __setLSState(_n) } #define SetLSSpeed(_n) asm { __setLSSpeed(_n) } #ifdef __ENHANCED_FIRMWARE #define SetLSNoRestartOnRead(_n) asm { __setLSNoRestartOnRead(_n) } #endif #define SysCommLSWrite(_args) asm { \ compchktype _args, CommLSWriteType \ syscall CommLSWrite, _args \ } #define SysCommLSRead(_args) asm { \ compchktype _args, CommLSReadType \ syscall CommLSRead, _args \ } #define SysCommLSCheckStatus(_args) asm { \ compchktype _args, CommLSCheckStatusType \ syscall CommLSCheckStatus, _args \ } #ifdef __ENHANCED_FIRMWARE #define SysCommLSWriteEx(_args) asm { \ compchktype _args, CommLSWriteExType \ syscall CommLSWriteEx, _args \ } #endif #endif /** @} */ // end of LowSpeedModuleFunctions group /** @} */ // end of LowSpeedModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// COMMAND MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup CommandModule * @{ */ /** @defgroup CommandModuleTypes Command module types * Types used by various Command module functions. * @{ */ /** * Parameters for the GetStartTick system call. * This structure is used when calling the \ref SysGetStartTick system call * function. * \sa SysGetStartTick() */ struct GetStartTickType { unsigned long Result; /*!< The returned tick value. */ }; /** * Parameters for the KeepAlive system call. * This structure is used when calling the \ref SysKeepAlive system call * function. * \sa SysKeepAlive() */ struct KeepAliveType { unsigned long Result; /*!< The current sleep timeout in milliseconds. */ }; /** * Parameters for the IOMapRead system call. * This structure is used when calling the \ref SysIOMapRead system call * function. * \sa SysIOMapRead() */ struct IOMapReadType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ string ModuleName; /*!< The name of the module to read from. See the \ref ModuleNameConstants group. */ unsigned int Offset; /*!< The offset in the module IOMap where to start reading. */ unsigned int Count; /*!< The number of bytes to read. */ byte Buffer[]; /*!< The buffer used to store read bytes. */ }; /** * Parameters for the IOMapWrite system call. * This structure is used when calling the \ref SysIOMapWrite system call * function. * \sa SysIOMapWrite() */ struct IOMapWriteType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ string ModuleName; /*!< The name of the module to write to. See the \ref ModuleNameConstants group. */ unsigned int Offset; /*!< The offset in the module IOMap where to start writing. */ byte Buffer[]; /*!< The buffer containing bytes to write. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the IOMapReadByID system call. * This structure is used when calling the \ref SysIOMapReadByID system call * function. * \sa SysIOMapReadByID() */ struct IOMapReadByIDType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ unsigned long ModuleID; /*!< The identifier of the module to read from. See the \ref ModuleIDConstants group. */ unsigned int Offset; /*!< The offset in the module IOMap where to start reading. */ unsigned int Count; /*!< The number of bytes to read. */ byte Buffer[]; /*!< The buffer used to store read bytes. */ }; /** * Parameters for the IOMapWriteByID system call. * This structure is used when calling the \ref SysIOMapWriteByID system call * function. * \sa SysIOMapWriteByID() */ struct IOMapWriteByIDType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ unsigned long ModuleID; /*!< The identifier of the module to write to. See the \ref ModuleIDConstants group. */ unsigned int Offset; /*!< The offset in the module IOMap where to start writing. */ byte Buffer[]; /*!< The buffer containing bytes to write. */ }; #endif #if __FIRMWARE_VERSION > 107 /** * Parameters for the DatalogWrite system call. * This structure is used when calling the \ref SysDatalogWrite system call * function. * \sa SysDatalogWrite() */ struct DatalogWriteType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ byte Message[]; /*!< A buffer containing data to write to the datalog. */ }; /** * Parameters for the DatalogGetTimes system call. * This structure is used when calling the \ref SysDatalogGetTimes system call * function. * \sa SysDatalogGetTimes() */ struct DatalogGetTimesType { unsigned long SyncTime; /*!< The datalog synchronized time. */ unsigned long SyncTick; /*!< The datalog synchronized tick. */ }; /** * Parameters for the ReadSemData system call. * This structure is used when calling the \ref SysReadSemData system call * function. * \sa SysReadSemData() */ struct ReadSemDataType { byte SemData; /*!< The semaphore data returned by the function call. */ bool Request; /*!< Which semaphore am I reading from, usage or request? */ }; /** * Parameters for the WriteSemData system call. * This structure is used when calling the \ref SysWriteSemData system call * function. * \sa SysWriteSemData() */ struct WriteSemDataType { byte SemData; /*!< The modified semaphore data returned by the function call. */ bool Request; /*!< Which semaphore am I writing to, usage or request? */ byte NewVal; /*!< The new semaphore data. */ bool ClearBits; /*!< Should I clear existing bits? */ }; /** * Parameters for the UpdateCalibCacheInfo system call. * This structure is used when calling the \ref SysUpdateCalibCacheInfo system call * function. * \sa SysUpdateCalibCacheInfo() */ struct UpdateCalibCacheInfoType { byte Result; /*!< The function call result. \todo ?. */ string Name; /*!< The name of the sensor calibration cache. \todo ?. */ unsigned int MinVal; /*!< The minimum calibrated value. */ unsigned int MaxVal; /*!< The maximum calibrated value. */ }; /** * Parameters for the ComputeCalibValue system call. * This structure is used when calling the \ref SysComputeCalibValue system call * function. * \sa SysComputeCalibValue() */ struct ComputeCalibValueType { byte Result; /*!< The function call result. \todo ?. */ string Name; /*!< The name of the sensor calibration cache. \todo ?. */ unsigned int RawVal; /*!< The raw value. \todo ?. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the MemoryManager system call. * This structure is used when calling the \ref SysMemoryManager system call * function. * \sa SysMemoryManager() */ struct MemoryManagerType { char Result; /*!< The returned status value. */ bool Compact; /*!< Should the dataspace be compacted or not. */ unsigned int PoolSize; /*!< The returned pool size. */ unsigned int DataspaceSize; /*!< The returned dataspace size. */ }; /** * Parameters for the ReadLastResponse system call. * This structure is used when calling the \ref SysReadLastResponse system call * function. * \sa SysReadLastResponse() */ struct ReadLastResponseType { char Result; /*!< The response packet status value. */ bool Clear; /*!< Clear the response after reading it or not. */ byte Length; /*!< The response packet length. */ byte Command; /*!< The response packet command byte. */ byte Buffer[]; /*!< The response packet buffer. */ }; #endif #endif /** @} */ // end of CommandModuleTypes group /** @defgroup CommandModuleFunctions Command module functions * Functions for accessing and modifying Command module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Read the current system tick. * This function lets you current system tick count. * * \return The current system tick count. */ inline unsigned long CurrentTick(); /** * Get the first tick. * Return an unsigned 32-bit value, which is the system timing value * (called a "tick") in milliseconds at the time that the program began * running. * * \return The tick count at the start of program execution. */ inline unsigned long FirstTick(); /** * Reset the sleep timer. * This function lets you reset the sleep timer. * * \return The result of resetting the sleep timer. */ inline long ResetSleepTimer(); //inline void SpawnProgram(string fname); // not ready to be documented /** * Call any system function. * This generic macro can be used to call any system function. No type * checking is performed so you need to make sure you use the correct * structure type given the selected system function ID. This is, however, the * fastest possible way to call a system function in NXC. * * Valid function ID constants are defined in the \ref SysCallConstants group. * * \param funcID The function ID constant corresponding to the function to be * called. * \param args The structure containing the needed parameters. */ inline void SysCall(byte funcID, variant & args); /** * Get start tick. * This function lets you obtain the tick value at the time your program began * executing via the \ref GetStartTickType structure. * * \param args The GetStartTickType structure receiving results. */ inline void SysGetStartTick(GetStartTickType & args); /** * Keep alive. * This function lets you reset the sleep timer via the \ref KeepAliveType * structure. * * \param args The KeepAliveType structure receiving results. */ inline void SysKeepAlive(KeepAliveType & args); /** * Read from IOMap by name. * This function lets you read data from a firmware module's IOMap using the * values specified via the \ref IOMapReadType structure. * * \param args The IOMapReadType structure containing the needed parameters. */ inline void SysIOMapRead(IOMapReadType & args); /** * Write to IOMap by name. * This function lets you write data to a firmware module's IOMap using the * values specified via the \ref IOMapWriteType structure. * * \param args The IOMapWriteType structure containing the needed parameters. */ inline void SysIOMapWrite(IOMapWriteType & args); #ifdef __ENHANCED_FIRMWARE /** * Read from IOMap by identifier. * This function lets you read data from a firmware module's IOMap using the * values specified via the \ref IOMapReadByIDType structure. This function * can be as much as three times faster than using SysIOMapRead since it does * not have to do a string lookup using the ModuleName. * * \param args The IOMapReadByIDType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysIOMapReadByID(IOMapReadByIDType & args); /** * Write to IOMap by identifier. * This function lets you write data to a firmware module's IOMap using the * values specified via the \ref IOMapWriteByIDType structure. This function * can be as much as three times faster than using SysIOMapWrite since it does * not have to do a string lookup using the ModuleName. * * \param args The IOMapWriteByIDType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysIOMapWriteByID(IOMapWriteByIDType & args); #endif #if __FIRMWARE_VERSION > 107 /** * Write to the datalog. * This function lets you write to the datalog using the * values specified via the \ref DatalogWriteType structure. * * \todo figure out what this function is intended for * \param args The DatalogWriteType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysDatalogWrite(DatalogWriteType & args); /** * Get datalog times. * This function lets you get datalog times using the * values specified via the \ref DatalogGetTimesType structure. * * \todo figure out what this function is intended for * \param args The DatalogGetTimesType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysDatalogGetTimes(DatalogGetTimesType & args); /** * Read semaphore data. * This function lets you read global motor semaphore data using the * values specified via the \ref ReadSemDataType structure. * * \param args The ReadSemDataType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysReadSemData(ReadSemDataType & args); /** * Write semaphore data. * This function lets you write global motor semaphore data using the * values specified via the \ref WriteSemDataType structure. * * \param args The WriteSemDataType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysWriteSemData(WriteSemDataType & args); /** * Update calibration cache information. * This function lets you update calibration cache information using the * values specified via the \ref UpdateCalibCacheInfoType structure. * * \todo figure out what this function is intended for * \param args The UpdateCalibCacheInfoType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysUpdateCalibCacheInfo(UpdateCalibCacheInfoType & args); /** * Compute calibration values. * This function lets you compute calibration values using the * values specified via the \ref ComputeCalibValueType structure. * * \todo figure out what this function is intended for * \param args The ComputeCalibValueType structure containing the needed parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysComputeCalibValue(ComputeCalibValueType & args); #endif #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Read memory information. * Read the current pool size and dataspace size. Optionally compact the * dataspace before returning the information. Running programs have a maximum * of 32k bytes of memory available. The amount of free RAM can be calculated * by subtracting the value returned by this function from \ref POOL_MAX_SIZE. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param Compact A boolean value indicating whether to compact the dataspace or not. * \param PoolSize The current pool size. * \param DataspaceSize The current dataspace size. * \return The function call result. It will be \ref NO_ERR if the compact * operation is not performed. Otherwise it will be the result of the compact * operation. */ inline char GetMemoryInfo(bool Compact, unsigned int & PoolSize, unsigned int & DataspaceSize); /** * Read memory information. * This function lets you read memory information using the * values specified via the \ref MemoryManagerType structure. * * \param args The MemoryManagerType structure containing the required parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SysMemoryManager(MemoryManagerType & args); /** * Read last response information. * Read the last direct or system command response packet received by the NXT. * Optionally clear the response after retrieving the information. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+. * * \param Clear A boolean value indicating whether to clear the response or not. * \param Length The response packet length. * \param Command The original command byte. * \param Buffer The response packet buffer. * \return The response status code. */ inline char GetLastResponseInfo(bool Clear, byte & Length, byte & Command, byte & Buffer[]); /** * Read last response information. * This function lets you read the last system or direct command response * received by the NXT using the values specified via the * \ref ReadLastResponseType structure. * * \param args The ReadLastResponseType structure containing the required parameters. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+. */ inline void SysReadLastResponse(ReadLastResponseType & args); #endif #else #define CurrentTick() asm { gettick __URETVAL__ } #define FirstTick() asm { GetFirstTick(__URETVAL__) } #define ResetSleepTimer() asm { acquire __KeepAliveMutex \ syscall KeepAlive, __KeepAliveArgs \ mov __RETVAL__, __KeepAliveArgs.Result \ release __KeepAliveMutex } #define SpawnProgram(_fname) asm { __spawnProgram(_fname) } #define SysCall(_func, _args) asm { syscall _func, _args } #define SysGetStartTick(_args) asm { \ compchktype _args, GetStartTickType \ syscall GetStartTick, _args \ } #define SysKeepAlive(_args) asm { \ compchktype _args, KeepAliveType \ syscall KeepAlive, _args \ } #define SysIOMapRead(_args) asm { \ compchktype _args, IOMapReadType \ syscall IOMapRead, _args \ } #define SysIOMapWrite(_args) asm { \ compchktype _args, IOMapWriteType \ syscall IOMapWrite, _args \ } #ifdef __ENHANCED_FIRMWARE #define SysIOMapReadByID(_args) asm { \ compchktype _args, IOMapReadByIDType \ syscall IOMapReadByID, _args \ } #define SysIOMapWriteByID(_args) asm { \ compchktype _args, IOMapWriteByIDType \ syscall IOMapWriteByID, _args \ } #endif #if __FIRMWARE_VERSION > 107 #define SysDatalogWrite(_args) asm { \ compchktype _args, DatalogWriteType \ syscall DatalogWrite, _args \ } #define SysDatalogGetTimes(_args) asm { \ compchktype _args, DatalogGetTimesType \ syscall DatalogGetTimes, _args \ } #define SysReadSemData(_args) asm { \ compchktype _args, ReadSemDataType \ syscall ReadSemData, _args \ } #define SysWriteSemData(_args) asm { \ compchktype _args, WriteSemDataType \ syscall WriteSemData, _args \ } #define SysUpdateCalibCacheInfo(_args) asm { \ compchktype _args, UpdateCalibCacheInfoType \ syscall UpdateCalibCacheInfo, _args \ } #define SysComputeCalibValue(_args) asm { \ compchktype _args, ComputeCalibValueType \ syscall ComputeCalibValue, _args \ } #endif #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) #define GetMemoryInfo(_Compact,_PoolSize,_DataspaceSize) asm { __GetMemoryInfo(_Compact,_PoolSize,_DataspaceSize,__RETVAL__) } #define SysMemoryManager(_args) asm { \ compchktype _args, MemoryManagerType \ syscall MemoryManager, _args \ } #define GetLastResponseInfo(_Clear,_Length,_Command,_Buffer) asm { __GetLastResponseInfo(_Clear,_Length,_Command,_Buffer,__RETVAL__) } #define SysReadLastResponse(_args) asm { \ compchktype _args, ReadLastResponseType \ syscall ReadLastResponse, _args \ } #endif #define until(_c) while(!(_c)) #endif /** * Wait some milliseconds. * Make a task sleep for specified amount of time (in 1000ths of a second). * * \param ms The number of milliseconds to sleep. */ inline void Wait(unsigned long ms) { asm { waitv ms } } /** * Yield to another task. * Make a task yield to another concurrently running task. */ inline void Yield() { asm { wait 1 } } /** * Stop all tasks. * Stop all currently running tasks. This will halt the program completely, * so any code following this command will be ignored. */ inline void StopAllTasks() { Stop(true); } #ifdef __DOXYGEN_DOCS /** * Stop the running program. * Stop the running program if bvalue is true. This will halt the program * completely, so any code following this command will be ignored. * \param bvalue If this value is true the program will stop executing. */ inline void Stop(bool bvalue); /** * Exit to another task. * Immediately exit the current task and start executing the specified task. * \param newTask The task to start executing after exiting the current task. */ inline void ExitTo(task newTask); /** * Declare tasks that this task precedes. * Schedule the listed tasks for execution once the current task has * completed executing. The tasks will all execute simultaneously unless other * dependencies prevent them from doing so. This statement should be used once * within a task - preferably at the start of the task definition. Any number * of tasks may be listed in the Precedes statement. * \param task1 The first task to start executing after the current task ends. * \param task2 The second task to start executing after the current task ends. * \param taskN The last task to start executing after the current task ends. */ inline void Precedes(task task1, task task2, ..., task taskN); /** * Declare tasks that this task follows. * Schedule this task to follow the specified tasks so that it will execute * once any of the specified tasks has completed executing. This statement * should occur once within a task - preferably at the start of the task * definition. If multiple tasks declare that they follow the same task then * they will all execute simultaneously unless other dependencies prevent them * from doing so. Any number of tasks may be listed in the Follows statement. * \param task1 The first task that this task follows. * \param task2 The second task that this task follows. * \param taskN The last task that this task follows. */ inline void Follows(task task1, task task2, ..., task taskN); /** * Acquire a mutex. * Acquire the specified mutex variable. If another task already has acquired * the mutex then the current task will be suspended until the mutex is * released by the other task. This function is used to ensure that the current * task has exclusive access to a shared resource, such as the display or a * motor. After the current task has finished using the shared resource the * program should call Release to allow other tasks to acquire the mutex. * \param m The mutex to acquire. */ inline void Acquire(mutex m); /** * Acquire a mutex. * Release the specified mutex variable. Use this to relinquish a mutex so * that it can be acquired by another task. Release should always be called * after a matching call to Acquire and as soon as possible after a shared * resource is no longer needed. * \param m The mutex to release. */ inline void Release(mutex m); /** * Start a task. * Start the specified task. * \param t The task to start. */ inline void StartTask(task t); /** * Stop a task. * Stop the specified task. * \param t The task to stop. * \warning This function requires the enhanced NBC/NXC firmware. */ inline void StopTask(task t); /** @defgroup ArrayFunctions Array API functions * Functions for use with NXC array types. * @{ */ /** * Build an array. * Build a new array from the specified source(s). The sources can be of any * type so long as the number of dimensions is equal to or one less than the * number of dimensions in the output array and the type is compatible with * the type of the output array. If a source is an array with the same number * of dimensions as the output array then all of its elements are added to * the output array. * \param aout The output array to build. * \param src1 The first source to build into the output array. * \param src2 The second source to build into the output array. * \param srcN The first source to build into the output array. */ inline void ArrayBuild(variant & aout[], variant src1, variant src2, ..., variant srcN); /** * Get array length. * Return the length of the specified array. Any type of array of up to four * dimensions can be passed into this function. * \param data The array whose length you need to read. * \return The length of the specified array. */ inline unsigned int ArrayLen(variant data[]); /** * Initialize an array. * Initialize the array to contain count elements with each element equal to * the value provided. To initialize a multi-dimensional array, the value * should be an array of N-1 dimensions, where N is the number of dimensions * in the array being initialized. * \param aout The output array to initialize. * \param value The value to initialize each element to. * \param count The number of elements to create in the output array. */ inline void ArrayInit(variant & aout[], variant value, unsigned int count); /** * Copy an array subset. * Copy a subset of the source array starting at the specified index and * containing the specified number of elements into the destination array. * \param aout The output array containing the subset. * \param asrc The input array from which to copy a subset. * \param idx The start index of the array subset. * \param len The length of the array subset. */ inline void ArraySubset(variant & aout[], variant asrc[], unsigned int idx, unsigned int len); #ifdef __ENHANCED_FIRMWARE /** * Calculate the sum of the elements in a numeric array. * This function calculates the sum of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The sum of len elements from the src numeric array (starting from idx). */ inline variant ArraySum(const variant & src[], unsigned int idx, unsigned int len); /** * Calculate the mean of the elements in a numeric array. * This function calculates the mean of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The mean value of len elements from the src numeric array (starting from idx). */ inline variant ArrayMean(const variant & src[], unsigned int idx, unsigned int len); /** * Calculate the sum of the squares of the elements in a numeric array. * This function calculates the sum of the squares of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The sum of the squares of len elements from the src numeric array (starting from idx). */ inline variant ArraySumSqr(const variant & src[], unsigned int idx, unsigned int len); /** * Calculate the standard deviation of the elements in a numeric array. * This function calculates the standard deviation of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The standard deviation of len elements from the src numeric array (starting from idx). */ inline variant ArrayStd(const variant & src[], unsigned int idx, unsigned int len); /** * Calculate the minimum of the elements in a numeric array. * This function calculates the minimum of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The minimum of len elements from the src numeric array (starting from idx). */ inline variant ArrayMin(const variant & src[], unsigned int idx, unsigned int len); /** * Calculate the maximum of the elements in a numeric array. * This function calculates the maximum of all or a subset of the elements in the * numeric src array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the calculation. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). * \return The maximum of len elements from the src numeric array (starting from idx). */ inline variant ArrayMax(const variant & src[], unsigned int idx, unsigned int len); /** * Sort the elements in a numeric array. * This function sorts all or a subset of the elements in the * numeric src array in ascending order and saves the results in the * numeric dest array. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param dest The destination numeric array. * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the sorting process. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). */ inline void ArraySort(variant & dest[], const variant & src[], unsigned int idx, unsigned int len); /** * Operate on numeric arrays. * This function lets you perform various operations on numeric arrays. * * \warning This function requires the enhanced NBC/NXC firmware. * * \param op The array operation. See \ref ArrayOpConstants. * \param dest The destination variant type (scalar or array, depending on the operation). * \param src The source numeric array. * \param idx The index of the start of the array subset to process. Pass * \ref NA to start with the first element. * \param len The number of elements to include in the specified process. Pass * \ref NA to include the rest of the elements in the src array (from idx to * the end of the array). */ inline void ArrayOp(const byte op, variant & dest, const variant & src[], unsigned int idx, unsigned int len); #endif /** @} */ // end of ArrayFunctions group #else #define StartTask(_t) start _t #define StopTask(_t) stop _t #if __FIRMWARE_VERSION <= 107 #define IOMA(_n) asm { mov __RETVAL__, _n } #define SetIOMA(_n, _val) asm { mov _n, _val } #endif #define ArrayBuild(_aout, ...) asm { arrbuild _aout, __VA_ARGS__ } #define ArrayLen(_asrc) asm { arrsize __RETVAL__, _asrc } #define ArrayInit(_aout, _val, _cnt) asm { arrinit _aout, _val, _cnt } #define ArraySubset(_aout, _asrc, _idx, _len) asm { arrsubset _aout, _asrc, _idx, _len } #ifdef __ENHANCED_FIRMWARE #define ArraySum(_src, _idx, _len) asm { arrop OPARR_SUM, __RETVAL__, _src, _idx, _len } #define ArrayMean(_src, _idx, _len) asm { arrop OPARR_MEAN, __RETVAL__, _src, _idx, _len } #define ArraySumSqr(_src, _idx, _len) asm { arrop OPARR_SUMSQR, __RETVAL__, _src, _idx, _len } #define ArrayStd(_src, _idx, _len) asm { arrop OPARR_STD, __RETVAL__, _src, _idx, _len } #define ArrayMin(_src, _idx, _len) asm { arrop OPARR_MIN, __RETVAL__, _src, _idx, _len } #define ArrayMax(_src, _idx, _len) asm { arrop OPARR_MAX, __RETVAL__, _src, _idx, _len } #define ArraySort(_dest, _src, _idx, _len) asm { arrop OPARR_SORT, _dest, _src, _idx, _len } #define ArrayOp(_op, _dest, _src, _idx, _len) asm { arrop _op, _dest, _src, _idx, _len } #endif #endif #ifdef __DOXYGEN_DOCS /** * Set IOMap bytes by name. * Modify one or more bytes of data in an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to start writing, the number of bytes to * write at that location, and a byte array containing the new data. * \param moduleName The module name of the IOMap to modify. See \ref ModuleNameConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the data should be written * \param count The number of bytes to write at the specified IOMap * offset. * \param data The byte array containing the data to write to the IOMap */ inline void SetIOMapBytes(string moduleName, unsigned int offset, unsigned int count, byte data[]); /** * Set IOMap value by name. * Set one of the fields of an IOMap structure to a new value. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to write the value along with a variable * containing the new value. * \param moduleName The module name of the IOMap to modify. See \ref ModuleNameConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the new value should be written * \param value A variable containing the new value to write to the IOMap */ inline void SetIOMapValue(string moduleName, unsigned int offset, variant value); /** * Get IOMap bytes by name. * Read one or more bytes of data from an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to start reading, the number of bytes to * read from that location, and a byte array where the data will be stored. * \param moduleName The module name of the IOMap. See \ref ModuleNameConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the data should be read * \param count The number of bytes to read from the specified IOMap * offset. * \param data A byte array that will contain the data read from the IOMap */ inline void GetIOMapBytes(string moduleName, unsigned int offset, unsigned int count, byte & data[]); /** * Get IOMap value by name. * Read a value from an IOMap structure. The IOMap * structure is specified by its module name. You also provide the offset into * the IOMap structure where you want to read the value along with a variable * that will contain the IOMap value. * \param moduleName The module name of the IOMap. See \ref ModuleNameConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read * \param value A variable that will contain the value read from the IOMap */ inline void GetIOMapValue(string moduleName, unsigned int offset, variant & value); /** * Get Lowspeed module IOMap bytes. * Read one or more bytes of data from Lowspeed module IOMap structure. * You provide the offset into the Lowspeed module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the data should be read. See \ref LowSpeedIOMAP. * \param count The number of bytes to read from the specified Lowspeed module * IOMap offset. * \param data A byte array that will contain the data read from the Lowspeed * module IOMap. */ inline void GetLowSpeedModuleBytes(unsigned int offset, unsigned int count, byte & data[]); /** * Get Display module IOMap bytes. * Read one or more bytes of data from Display module IOMap structure. * You provide the offset into the Display module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param offset The number of bytes offset from the start of the Display * module IOMap structure where the data should be read. See \ref DisplayIOMAP. * \param count The number of bytes to read from the specified Display module * IOMap offset. * \param data A byte array that will contain the data read from the Display * module IOMap. */ inline void GetDisplayModuleBytes(unsigned int offset, unsigned int count, byte & data[]); /** * Get Comm module IOMap bytes. * Read one or more bytes of data from Comm module IOMap structure. * You provide the offset into the Comm module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param offset The number of bytes offset from the start of the Comm module * IOMap structure where the data should be read. See \ref CommIOMAP. * \param count The number of bytes to read from the specified Comm module * IOMap offset. * \param data A byte array that will contain the data read from the Comm * module IOMap. */ inline void GetCommModuleBytes(unsigned int offset, unsigned int count, byte & data[]); /** * Get Command module IOMap bytes. * Read one or more bytes of data from Command module IOMap structure. * You provide the offset into the Command module IOMap structure where you * want to start reading, the number of bytes to read from that location, and * a byte array where the data will be stored. * \param offset The number of bytes offset from the start of the Command module * IOMap structure where the data should be read. See \ref CommandIOMAP. * \param count The number of bytes to read from the specified Command module * IOMap offset. * \param data A byte array that will contain the data read from the Command * module IOMap. */ inline void GetCommandModuleBytes(unsigned int offset, unsigned int count, byte & data[]); /** * Set Command module IOMap bytes. * Modify one or more bytes of data in the Command module IOMap structure. You * provide the offset into the Command module IOMap structure where you want * to start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param offset The number of bytes offset from the start of the Command module * IOMap structure where the data should be written. See \ref CommandIOMAP. * \param count The number of bytes to write at the specified Command module * IOMap offset. * \param data The byte array containing the data to write to the Command * module IOMap. */ inline void SetCommandModuleBytes(unsigned int offset, unsigned int count, byte data[]); /** * Set Lowspeed module IOMap bytes. * Modify one or more bytes of data in the Lowspeed module IOMap structure. You * provide the offset into the Lowspeed module IOMap structure where you want * to start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the data should be written. See \ref LowSpeedIOMAP. * \param count The number of bytes to write at the specified Lowspeed module * IOMap offset. * \param data The byte array containing the data to write to the Lowspeed * module IOMap. */ inline void SetLowSpeedModuleBytes(unsigned int offset, unsigned int count, byte data[]); /** * Set Display module IOMap bytes. * Modify one or more bytes of data in the Display module IOMap structure. You * provide the offset into the Display module IOMap structure where you want to * start writing, the number of bytes to write at that location, and a byte * array containing the new data. * \param offset The number of bytes offset from the start of the Display module * IOMap structure where the data should be written. See \ref DisplayIOMAP. * \param count The number of bytes to write at the specified Display module * IOMap offset. * \param data The byte array containing the data to write to the Display * module IOMap. */ inline void SetDisplayModuleBytes(unsigned int offset, unsigned int count, byte data[]); /** * Set Comm module IOMap bytes. * Modify one or more bytes of data in an IOMap structure. You provide the * offset into the Comm module IOMap structure where you want to start writing, * the number of bytes to write at that location, and a byte array containing * the new data. * \param offset The number of bytes offset from the start of the Comm module * IOMap structure where the data should be written. See \ref CommIOMAP. * \param count The number of bytes to write at the specified Comm module IOMap * offset. * \param data The byte array containing the data to write to the Comm module * IOMap. */ inline void SetCommModuleBytes(unsigned int offset, unsigned int count, byte data[]); #ifdef __ENHANCED_FIRMWARE /** * Set IOMap bytes by ID. * Modify one or more bytes of data in an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to start writing, the number of bytes to * write at that location, and a byte array containing the new data. * \param moduleId The module ID of the IOMap to modify. See \ref ModuleIDConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the data should be written. * \param count The number of bytes to write at the specified IOMap * offset. * \param data The byte array containing the data to write to the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SetIOMapBytesByID(unsigned long moduleId, unsigned int offset, unsigned int count, byte data[]); /** * Set IOMap value by ID. * Set one of the fields of an IOMap structure to a new value. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to write the value along with a variable * containing the new value. * \param moduleId The module ID of the IOMap to modify. See \ref ModuleIDConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the new value should be written. * \param value A variable containing the new value to write to the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SetIOMapValueByID(unsigned long moduleId, unsigned int offset, variant value); /** * Get IOMap bytes by ID. * Read one or more bytes of data from an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to start reading, the number of bytes to * read from that location, and a byte array where the data will be stored. * \param moduleId The module ID of the IOMap. See \ref ModuleIDConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the data should be read. * \param count The number of bytes to read from the specified IOMap * offset. * \param data A byte array that will contain the data read from the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ inline void GetIOMapBytesByID(unsigned long moduleId, unsigned int offset, unsigned int count, byte & data[]); /** * Get IOMap value by ID. * Read a value from an IOMap structure. The IOMap * structure is specified by its Module ID. You also provide the offset into * the IOMap structure where you want to read the value along with a variable * that will contain the IOMap value. * \param moduleId The module ID of the IOMap. See \ref ModuleIDConstants. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. * \param value A variable that will contain the value read from the IOMap. * \warning This function requires the enhanced NBC/NXC firmware. */ inline void GetIOMapValueByID(unsigned long moduleId, unsigned int offset, variant & value); #endif /** * Set Command module IOMap value. * Set one of the fields of the Command module IOMap structure to a new value. * You provide the offset into the Command module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Command * module IOMap structure where the new value should be written. See \ref CommandIOMAP. * \param value A variable containing the new value to write to the Command * module IOMap. */ inline void SetCommandModuleValue(unsigned int offset, variant value); /** * Set IOCtrl module IOMap value. * Set one of the fields of the IOCtrl module IOMap structure to a new value. * You provide the offset into the IOCtrl module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the IOCtrl * module IOMap structure where the new value should be written. See \ref IOCtrlIOMAP. * \param value A variable containing the new value to write to the IOCtrl * module IOMap. */ inline void SetIOCtrlModuleValue(unsigned int offset, variant value); /** * Set Loader module IOMap value. * Set one of the fields of the Loader module IOMap structure to a new value. * You provide the offset into the Loader module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Loader * module IOMap structure where the new value should be written. See \ref LoaderIOMAP. * \param value A variable containing the new value to write to the Loader * module IOMap. */ inline void SetLoaderModuleValue(unsigned int offset, variant value); /** * Set Ui module IOMap value. * Set one of the fields of the Ui module IOMap structure to a new value. * You provide the offset into the Ui module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Ui * module IOMap structure where the new value should be written. See \ref UiIOMAP. * \param value A variable containing the new value to write to the Ui * module IOMap. */ inline void SetUIModuleValue(unsigned int offset, variant value); /** * Set Sound module IOMap value. * Set one of the fields of the Sound module IOMap structure to a new value. * You provide the offset into the Sound module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Sound * module IOMap structure where the new value should be written. See \ref SoundIOMAP. * \param value A variable containing the new value to write to the Sound * module IOMap. */ inline void SetSoundModuleValue(unsigned int offset, variant value); /** * Set Button module IOMap value. * Set one of the fields of the Button module IOMap structure to a new value. * You provide the offset into the Button module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Button * module IOMap structure where the new value should be written. See \ref ButtonIOMAP. * \param value A variable containing the new value to write to the Button * module IOMap. */ inline void SetButtonModuleValue(unsigned int offset, variant value); /** * Set Input module IOMap value. * Set one of the fields of the Input module IOMap structure to a new value. * You provide the offset into the Input module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Input * module IOMap structure where the new value should be written. See \ref InputIOMAP. * \param value A variable containing the new value to write to the Input * module IOMap. */ inline void SetInputModuleValue(unsigned int offset, variant value); /** * Set Output module IOMap value. * Set one of the fields of the Output module IOMap structure to a new value. * You provide the offset into the Output module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Output * module IOMap structure where the new value should be written. See \ref OutputIOMAP. * \param value A variable containing the new value to write to the Output * module IOMap. */ inline void SetOutputModuleValue(unsigned int offset, variant value); /** * Set Lowspeed module IOMap value. * Set one of the fields of the Lowspeed module IOMap structure to a new value. * You provide the offset into the Lowspeed module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Lowspeed * module IOMap structure where the new value should be written. See \ref LowSpeedIOMAP. * \param value A variable containing the new value to write to the Lowspeed * module IOMap. */ inline void SetLowSpeedModuleValue(unsigned int offset, variant value); /** * Set Display module IOMap value. * Set one of the fields of the Display module IOMap structure to a new value. * You provide the offset into the Display module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Display * module IOMap structure where the new value should be written. See \ref DisplayIOMAP. * \param value A variable containing the new value to write to the Display * module IOMap. */ inline void SetDisplayModuleValue(unsigned int offset, variant value); /** * Set Comm module IOMap value. * Set one of the fields of the Comm module IOMap structure to a new value. * You provide the offset into the Comm module IOMap structure where you * want to write the value along with a variable containing the new value. * \param offset The number of bytes offset from the start of the Comm * module IOMap structure where the new value should be written. See \ref CommIOMAP. * \param value A variable containing the new value to write to the Comm * module IOMap. */ inline void SetCommModuleValue(unsigned int offset, variant value); /** * Get Command module IOMap value. * Read a value from the Command module IOMap structure. You provide the * offset into the Command module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref CommandIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetCommandModuleValue(unsigned int offset, variant & value); /** * Get Loader module IOMap value. * Read a value from the Loader module IOMap structure. You provide the * offset into the Loader module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref LoaderIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetLoaderModuleValue(unsigned int offset, variant & value); /** * Get Sound module IOMap value. * Read a value from the Sound module IOMap structure. You provide the * offset into the Sound module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref SoundIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetSoundModuleValue(unsigned int offset, variant & value); /** * Get Button module IOMap value. * Read a value from the Button module IOMap structure. You provide the * offset into the Button module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref ButtonIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetButtonModuleValue(unsigned int offset, variant & value); /** * Get Ui module IOMap value. * Read a value from the Ui module IOMap structure. You provide the * offset into the Ui module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref UiIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetUIModuleValue(unsigned int offset, variant & value); /** * Get Input module IOMap value. * Read a value from the Input module IOMap structure. You provide the * offset into the Input module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref InputIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetInputModuleValue(unsigned int offset, variant & value); /** * Get Output module IOMap value. * Read a value from the Output module IOMap structure. You provide the * offset into the Output module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref OutputIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetOutputModuleValue(unsigned int offset, variant & value); /** * Get LowSpeed module IOMap value. * Read a value from the LowSpeed module IOMap structure. You provide the * offset into the Command module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref LowSpeedIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetLowSpeedModuleValue(unsigned int offset, variant & value); /** * Get Display module IOMap value. * Read a value from the Display module IOMap structure. You provide the * offset into the Display module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref DisplayIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetDisplayModuleValue(unsigned int offset, variant & value); /** * Get Comm module IOMap value. * Read a value from the Comm module IOMap structure. You provide the * offset into the Comm module IOMap structure where you want to read * the value from along with a variable that will store the value. The type * of the variable determines how many bytes are read from the IOMap. * \param offset The number of bytes offset from the start of the IOMap * structure where the value should be read. See \ref CommIOMAP. * \param value A variable that will contain the value read from the IOMap. */ inline void GetCommModuleValue(unsigned int offset, variant & value); #else #define SetIOMapBytes(_modName, _offset, _cnt, _arrIn) asm { __SetIOMapBytes(_modName, _offset, _cnt, _arrIn) } #define SetIOMapValue(_modName, _offset, _n) asm { __SetIOMapValue(_modName, _offset, _n) } #define GetIOMapBytes(_modName, _offset, _cnt, _arrOut) asm { __getIOMapBytes(_modName, _offset, _cnt, _arrOut) } #define GetIOMapValue(_modName, _offset, _n) asm { __getIOMapValue(_modName, _offset, _n) } #define GetLowSpeedModuleBytes(_offset, _cnt, _arrOut) asm { __getLowSpeedModuleBytes(_offset, _cnt, _arrOut) } #define GetDisplayModuleBytes(_offset, _cnt, _arrOut) asm { __getDisplayModuleBytes(_offset, _cnt, _arrOut) } #define GetCommModuleBytes(_offset, _cnt, _arrOut) asm { __getCommModuleBytes(_offset, _cnt, _arrOut) } #ifdef __ENHANCED_FIRMWARE #define SetIOMapBytesByID(_modID, _offset, _cnt, _arrIn) asm { __SetIOMapBytesByID(_modID, _offset, _cnt, _arrIn) } #define SetIOMapValueByID(_modID, _offset, _n) asm { __SetIOMapValueByID(_modID, _offset, _n) } #define GetIOMapBytesByID(_modID, _offset, _cnt, _arrOut) asm { __getIOMapBytesByID(_modID, _offset, _cnt, _arrOut) } #define GetIOMapValueByID(_modID, _offset, _n) asm { __getIOMapValueByID(_modID, _offset, _n) } #define SetCommandModuleValue(_offset, _n) SetIOMapValueByID(CommandModuleID, _offset, _n) #define SetIOCtrlModuleValue(_offset, _n) SetIOMapValueByID(IOCtrlModuleID, _offset, _n) #define SetLoaderModuleValue(_offset, _n) SetIOMapValueByID(LoaderModuleID, _offset, _n) #define SetUIModuleValue(_offset, _n) SetIOMapValueByID(UIModuleID, _offset, _n) #define SetSoundModuleValue(_offset, _n) SetIOMapValueByID(SoundModuleID, _offset, _n) #define SetButtonModuleValue(_offset, _n) SetIOMapValueByID(ButtonModuleID, _offset, _n) #define SetInputModuleValue(_offset, _n) SetIOMapValueByID(InputModuleID, _offset, _n) #define SetOutputModuleValue(_offset, _n) SetIOMapValueByID(OutputModuleID, _offset, _n) #define SetLowSpeedModuleValue(_offset, _n) SetIOMapValueByID(LowSpeedModuleID, _offset, _n) #define SetDisplayModuleValue(_offset, _n) SetIOMapValueByID(DisplayModuleID, _offset, _n) #define SetCommModuleValue(_offset, _n) SetIOMapValueByID(CommModuleID, _offset, _n) #define SetCommandModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(CommandModuleID, _offset, _cnt, _arrIn) #define SetLowSpeedModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(LowSpeedModuleID, _offset, _cnt, _arrIn) #define SetDisplayModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(DisplayModuleID, _offset, _cnt, _arrIn) #define SetCommModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytesByID(CommModuleID, _offset, _cnt, _arrIn) #define GetCommandModuleValue(_offset, _n) GetIOMapValueByID(CommandModuleID, _offset, _n) #define GetLoaderModuleValue(_offset, _n) GetIOMapValueByID(LoaderModuleID, _offset, _n) #define GetSoundModuleValue(_offset, _n) GetIOMapValueByID(SoundModuleID, _offset, _n) #define GetButtonModuleValue(_offset, _n) GetIOMapValueByID(ButtonModuleID, _offset, _n) #define GetUIModuleValue(_offset, _n) GetIOMapValueByID(UIModuleID, _offset, _n) #define GetInputModuleValue(_offset, _n) GetIOMapValueByID(InputModuleID, _offset, _n) #define GetOutputModuleValue(_offset, _n) GetIOMapValueByID(OutputModuleID, _offset, _n) #define GetLowSpeedModuleValue(_offset, _n) GetIOMapValueByID(LowSpeedModuleID, _offset, _n) #define GetDisplayModuleValue(_offset, _n) GetIOMapValueByID(DisplayModuleID, _offset, _n) #define GetCommModuleValue(_offset, _n) GetIOMapValueByID(CommModuleID, _offset, _n) #else #define SetCommandModuleValue(_offset, _n) SetIOMapValue(CommandModuleName, _offset, _n) #define SetIOCtrlModuleValue(_offset, _n) SetIOMapValue(IOCtrlModuleName, _offset, _n) #define SetLoaderModuleValue(_offset, _n) SetIOMapValue(LoaderModuleName, _offset, _n) #define SetUIModuleValue(_offset, _n) SetIOMapValue(UIModuleName, _offset, _n) #define SetSoundModuleValue(_offset, _n) SetIOMapValue(SoundModuleName, _offset, _n) #define SetButtonModuleValue(_offset, _n) SetIOMapValue(ButtonModuleName, _offset, _n) #define SetInputModuleValue(_offset, _n) SetIOMapValue(InputModuleName, _offset, _n) #define SetOutputModuleValue(_offset, _n) SetIOMapValue(OutputModuleName, _offset, _n) #define SetLowSpeedModuleValue(_offset, _n) SetIOMapValue(LowSpeedModuleName, _offset, _n) #define SetDisplayModuleValue(_offset, _n) SetIOMapValue(DisplayModuleName, _offset, _n) #define SetCommModuleValue(_offset, _n) SetIOMapValue(CommModuleName, _offset, _n) #define SetCommandModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(CommandModuleName, _offset, _cnt, _arrIn) #define SetLowSpeedModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(LowSpeedModuleName, _offset, _cnt, _arrIn) #define SetDisplayModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(DisplayModuleName, _offset, _cnt, _arrIn) #define SetCommModuleBytes(_offset, _cnt, _arrIn) SetIOMapBytes(CommModuleName, _offset, _cnt, _arrIn) #define GetCommandModuleValue(_offset, _n) GetIOMapValue(CommandModuleName, _offset, _n) #define GetLoaderModuleValue(_offset, _n) GetIOMapValue(LoaderModuleName, _offset, _n) #define GetSoundModuleValue(_offset, _n) GetIOMapValue(SoundModuleName, _offset, _n) #define GetButtonModuleValue(_offset, _n) GetIOMapValue(ButtonModuleName, _offset, _n) #define GetUIModuleValue(_offset, _n) GetIOMapValue(UIModuleName, _offset, _n) #define GetInputModuleValue(_offset, _n) GetIOMapValue(InputModuleName, _offset, _n) #define GetOutputModuleValue(_offset, _n) GetIOMapValue(OutputModuleName, _offset, _n) #define GetLowSpeedModuleValue(_offset, _n) GetIOMapValue(LowSpeedModuleName, _offset, _n) #define GetDisplayModuleValue(_offset, _n) GetIOMapValue(DisplayModuleName, _offset, _n) #define GetCommModuleValue(_offset, _n) GetIOMapValue(CommModuleName, _offset, _n) #endif #endif /** @} */ // end of CommandModuleFunctions group /** @} */ // end of CommandModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// IOCTRL MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup IOCtrlModule * @{ */ /** @defgroup IOCtrlModuleTypes IOCtrl module types * Types used by various IOCtrl module functions. * @{ */ /** @} */ // end of IOCtrlModuleTypes group /** @defgroup IOCtrlModuleFunctions IOCtrl module functions * Functions for accessing and modifying IOCtrl module features. * @{ */ /** * Power down the NXT. * This function powers down the NXT. * The running program will terminate as a result of this action. */ inline void PowerDown() { SetIOCtrlModuleValue(IOCtrlOffsetPowerOn, IOCTRL_POWERDOWN); } /** * Put the brick to sleep immediately. * This function lets you immediately put the NXT to sleep. * The running program will terminate as a result of this action. */ inline void SleepNow() { SetIOCtrlModuleValue(IOCtrlOffsetPowerOn, IOCTRL_POWERDOWN); } /** * Reboot the NXT in firmware download mode. * This function lets you reboot the NXT into SAMBA or firmware download mode. * The running program will terminate as a result of this action. */ inline void RebootInFirmwareMode() { SetIOCtrlModuleValue(IOCtrlOffsetPowerOn, IOCTRL_BOOT); } /** @} */ // end of IOCtrlModuleFunctions group /** @} */ // end of IOCtrlModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// COMM MODULE ///////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup CommModule * @{ */ /** @defgroup CommModuleTypes Comm module types * Types used by various Comm module functions. * @{ */ /** * Parameters for the MessageWrite system call. * This structure is used when calling the \ref SysMessageWrite system call * function. * \sa SysMessageWrite() */ struct MessageWriteType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ byte QueueID; /*!< The queue identifier. See the \ref MailboxConstants group. */ string Message; /*!< The message to write. */ }; /** * Parameters for the MessageRead system call. * This structure is used when calling the \ref SysMessageRead system call * function. * \sa SysMessageRead() */ struct MessageReadType { char Result; /*!< The function call result. \ref NO_ERR means it succeeded. */ byte QueueID; /*!< The queue identifier. See the \ref MailboxConstants group. */ bool Remove; /*!< If true, remove the read message from the queue. */ string Message; /*!< The contents of the mailbox/queue. */ }; /** * Parameters for the CommBTCheckStatus system call. * This structure is used when calling the \ref SysCommBTCheckStatus system * call function. * \sa SysCommBTCheckStatus() */ struct CommBTCheckStatusType { char Result; /*!< The function call result. Possible values include \ref ERR_INVALID_PORT, \ref STAT_COMM_PENDING, \ref ERR_COMM_CHAN_NOT_READY, and \ref LDR_SUCCESS. */ byte Connection; /*!< The connection to check. */ }; /** * Parameters for the CommBTWrite system call. * This structure is used when calling the \ref SysCommBTWrite system call * function. * \sa SysCommBTWrite() */ struct CommBTWriteType { char Result; /*!< The function call result. Possible values include \ref ERR_COMM_CHAN_NOT_READY and \ref STAT_COMM_PENDING (write accepted). */ byte Connection; /*!< The connection to use. */ byte Buffer[]; /*!< The data to write to the connection. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the CommExecuteFunction system call. * This structure is used when calling the \ref SysCommExecuteFunction system * call function. * * The fields usage depends on the requested command and are documented in the * table below. If a field member is shown as 'x' it is ignored by the * specified command. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
CmdMeaning(Param1,Param2,Param3,Name)
INTF_SENDFILESend a file over a Bluetooth connection(Connection,x,x,Filename)
INTF_SEARCHSearch for Bluetooth devices(x,x,x,x)
INTF_STOPSEARCHStop searching for Bluetooth devices(x,x,x,x)
INTF_CONNECTConnect to a Bluetooth device(DeviceIndex,Connection,x,x)
INTF_DISCONNECTDisconnect a Bluetooth device(Connection,x,x,x)
INTF_DISCONNECTALLDisconnect all Bluetooth devices(x,x,x,x)
INTF_REMOVEDEVICERemove device from My Contacts(DeviceIndex,x,x,x)
INTF_VISIBILITYSet Bluetooth visibility(true/false,x,x,x)
INTF_SETCMDMODESet command mode(x,x,x,x)
INTF_OPENSTREAMOpen a stream(x,Connection,x,x)
INTF_SENDDATASend data(Length, Connection, WaitForIt, Buffer)
INTF_FACTORYRESETBluetooth factory reset(x,x,x,x)
INTF_BTONTurn Bluetooth on(x,x,x,x)
INTF_BTOFFTurn Bluetooth off(x,x,x,x)
INTF_SETBTNAMESet Bluetooth name(x,x,x,x)
INTF_EXTREADHandle external? read(x,x,x,x)
INTF_PINREQHandle Blueooth PIN request(x,x,x,x)
INTF_CONNECTREQHandle Bluetooth connect request(x,x,x,x)
* * \sa SysCommExecuteFunction() */ struct CommExecuteFunctionType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte Cmd; /*!< The command to execute. */ byte Param1; /*!< The first parameter, see table. */ byte Param2; /*!< The second parameter, see table. */ byte Param3; /*!< The third parameter, see table. */ string Name; /*!< The name parameter, see table. */ unsigned int RetVal; /*!< The function call return value. Possible values include \ref LoaderErrors. */ }; /** * Parameters for the CommHSControl system call. * This structure is used when calling the \ref SysCommHSControl system call * function. * \sa SysCommHSControl() */ struct CommHSControlType { char Result; /*!< The function call result. \todo values? */ byte Command; /*!< The hi-speed port configuration command. See \ref CommHiSpeedCtrlConstants. */ byte BaudRate; /*!< The hi-speed port baud rate. See \ref CommHiSpeedBaudConstants. */ #if __FIRMWARE_VERSION > 107 unsigned int Mode; /*!< The hi-speed port mode. See \ref CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, \ref CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. */ #endif }; /** * Parameters for the CommHSCheckStatus system call. * This structure is used when calling the \ref SysCommHSCheckStatus system call * function. * \sa SysCommHSCheckStatus() */ struct CommHSCheckStatusType { bool SendingData; /*!< Is data currently being sent? */ bool DataAvailable; /*!< Is data available for reading? */ }; /** * Parameters for the CommHSReadWrite system call. * This structure is used when calling the \ref SysCommHSRead and * \ref SysCommHSWrite system call functions. * \sa SysCommHSRead(), SysCommHSWrite() */ struct CommHSReadWriteType { char Status; /*!< The result of the function call. */ byte Buffer[]; /*!< The buffer of data to write or to contain the data read from the hi-speed port. */ }; #endif #if __FIRMWARE_VERSION > 107 /** * Parameters for the CommBTOnOff system call. * This structure is used when calling the \ref SysCommBTOnOff system call * function. * \sa SysCommBTOnOff() */ struct CommBTOnOffType { #ifdef __ENHANCED_FIRMWARE unsigned int Result; /*!< The function call result. */ #else char Result; /*!< The function call result. */ #endif bool PowerState; /*!< If true then turn on bluetooth, otherwise, turn it off. */ }; /** * Parameters for the CommBTConnection system call. * This structure is used when calling the \ref SysCommBTConnection system call * function. * \sa SysCommBTConnection() */ struct CommBTConnectionType { #ifdef __ENHANCED_FIRMWARE unsigned int Result; /*!< The function call result. */ #else char Result; /*!< The function call result. */ #endif byte Action; /*!< The connection action (connect or disconnect). */ string Name; /*!< The name of the device to connect or disconnect. */ byte ConnectionSlot; /*!< The connection slot to connect or disconnect. */ }; #endif /** @} */ // end of CommModuleTypes group /** @defgroup CommModuleFunctions Comm module functions * Functions for accessing and modifying Comm module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Send a message to a queue/mailbox. * Write a message into a local mailbox. * * \param queue The mailbox number. See \ref MailboxConstants. * \param msg The message to write to the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char SendMessage(byte queue, string msg); /** * Read a message from a queue/mailbox. * Read a message from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param queue The mailbox number. See \ref MailboxConstants. * \param clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param msg The message that is read from the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char ReceiveMessage(byte queue, bool clear, string & msg); /** * Check bluetooth status. * Check the status of the bluetooth subsystem for the specified connection slot. * * \param conn The connection slot (0..3). Connections 0 through 3 are for * bluetooth connections. See \ref CommConnectionConstants. * \return The bluetooth status for the specified connection. */ inline char BluetoothStatus(byte conn); /** * Write to a bluetooth connection. * This method tells the NXT firmware to write the data in the buffer to the * device on the specified Bluetooth connection. Use \ref BluetoothStatus to * determine when this write request is completed. * * \param conn The connection slot (0..3). Connections 0 through 3 are for * bluetooth connections. See \ref CommConnectionConstants. * \param buffer The data to be written (up to 128 bytes) * \return A char value indicating whether the function call succeeded or not. */ inline char BluetoothWrite(byte conn, byte buffer[]); /** * Write to a remote connection. * This method tells the NXT firmware to write the data in the buffer to the * device on the specified connection. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param buffer The data to be written (up to 128 bytes) * \return A char value indicating whether the function call succeeded or not. * * \warning Writing to the RS485 hi-speed connection requires the enhanced * NBC/NXC firmware */ inline char RemoteConnectionWrite(byte conn, byte buffer[]); /** * Check if remote connection is idle. * Check whether a Bluetooth or RS485 hi-speed port connection is idle, * i.e., not currently sending data. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A boolean value indicating whether the connection is idle or busy. * * \warning Checking the status of the RS485 hi-speed connection requires the * enhanced NBC/NXC firmware */ inline bool RemoteConnectionIdle(byte conn); /** * Send a boolean value to a remote mailbox. * Send a boolean value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param queue The mailbox number. See \ref MailboxConstants. * \param bval The boolean value to send. * \return A char value indicating whether the function call succeeded or not. */ inline char SendRemoteBool(byte conn, byte queue, bool bval); /** * Send a numeric value to a remote mailbox. * Send a numeric value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param queue The mailbox number. See \ref MailboxConstants. * \param val The numeric value to send. * \return A char value indicating whether the function call succeeded or not. */ inline char SendRemoteNumber(byte conn, byte queue, long val); /** * Send a string value to a remote mailbox. * Send a string value on the specified connection to the * specified remote mailbox number. Use \ref RemoteConnectionIdle to determine * when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param queue The mailbox number. See \ref MailboxConstants. * \param str The string value to send. * \return A char value indicating whether the function call succeeded or not. */ inline char SendRemoteString(byte conn, byte queue, string str); /** * Write a boolean value to a local response mailbox. * Write a boolean value to a response mailbox (the mailbox number + 10). * * \param queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param bval The boolean value to write. * \return A char value indicating whether the function call succeeded or not. */ inline char SendResponseBool(byte queue, bool bval); /** * Write a numeric value to a local response mailbox. * Write a numeric value to a response mailbox (the mailbox number + 10). * * \param queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param val The numeric value to write. * \return A char value indicating whether the function call succeeded or not. */ inline char SendResponseNumber(byte queue, long val); /** * Write a string value to a local response mailbox. * Write a string value to a response mailbox (the mailbox number + 10). * * \param queue The mailbox number. See \ref MailboxConstants. This function * shifts the specified value into the range of response mailbox numbers by * adding 10. * \param str The string value to write. * \return A char value indicating whether the function call succeeded or not. */ inline char SendResponseString(byte queue, string str); /** * Read a boolean value from a queue/mailbox. * Read a boolean value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param queue The mailbox number. See \ref MailboxConstants. * \param clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param bval The boolean value that is read from the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char ReceiveRemoteBool(byte queue, bool clear, bool & bval); /** * Read a value from a queue/mailbox. * Read a value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. Output the value in string, number, and * boolean form. * * \param queue The mailbox number. See \ref MailboxConstants. * \param clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param str The string value that is read from the mailbox. * \param val The numeric value that is read from the mailbox. * \param bval The boolean value that is read from the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char ReceiveRemoteMessageEx(byte queue, bool clear, string & str, long & val, bool & bval); /** * Read a numeric value from a queue/mailbox. * Read a numeric value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param queue The mailbox number. See \ref MailboxConstants. * \param clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param val The numeric value that is read from the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char ReceiveRemoteNumber(byte queue, bool clear, long & val); /** * Read a string value from a queue/mailbox. * Read a string value from a mailbox and optionally remove it. If the local mailbox * is empty and this NXT is the master then it attempts to poll one of its * slave NXTs for a message from the response mailbox that corresponds to the * specified local mailbox number. * * \param queue The mailbox number. See \ref MailboxConstants. * \param clear A flag indicating whether to remove the message from the mailbox * after it has been read. * \param str The string value that is read from the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char ReceiveRemoteString(byte queue, bool clear, string & str); /** @defgroup CommModuleDCFunctions Direct Command functions * Functions for sending direct commands to another NXT. * @{ */ /** * Send a KeepAlive message. * This method sends a KeepAlive direct command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteKeepAlive(byte conn); /** * Send a MessageRead message. * This method sends a MessageRead direct command to the device on the * specified connection. Use \ref RemoteConnectionIdle to determine when this write * request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param queue The mailbox to read. See \ref MailboxConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteMessageRead(byte conn, byte queue); /** * Send a MessageWrite message. * This method sends a MessageWrite direct command to the device on the * specified connection. Use \ref RemoteConnectionIdle to determine when this write * request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param queue The mailbox to write. See \ref MailboxConstants. * \param msg The message to write to the mailbox. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteMessageWrite(byte conn, byte queue, string msg); /** * Send a PlaySoundFile message. * Send the PlaySoundFile direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the sound file to play. * \param bloop A boolean value indicating whether to loop the sound file or not. * \return A char value indicating whether the function call succeeded or not. */ inline char RemotePlaySoundFile(byte conn, string filename, bool bloop); /** * Send a PlayTone message. * Send the PlayTone direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param frequency The frequency of the tone. * \param duration The duration of the tone. * \return A char value indicating whether the function call succeeded or not. */ inline char RemotePlayTone(byte conn, unsigned int frequency, unsigned int duration); /** * Send a ResetMotorPosition message. * Send the ResetMotorPosition direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The output port to reset. * \param brelative A flag indicating whether the counter to reset is relative. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteResetMotorPosition(byte conn, byte port, bool brelative); /** * Send a ResetScaledValue message. * Send the ResetScaledValue direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The input port to reset. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteResetScaledValue(byte conn, byte port); /** * Send a SetInputMode message. * Send the SetInputMode direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The input port to configure. See \ref InPorts. * \param type The sensor type. See \ref SensorTypes. * \param mode The sensor mode. See \ref SensorModes. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteSetInputMode(byte conn, byte port, byte type, byte mode); /** * Send a SetOutputMode message. * Send the SetOutputMode direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The output port to configure. See \ref OutputPortConstants. * \param speed The motor speed. (-100..100) * \param mode The motor mode. See \ref OutModeConstants. * \param regmode The motor regulation mode. See \ref OutRegModeConstants. * \param turnpct The motor synchronized turn percentage. (-100..100) * \param runstate The motor run state. See \ref OutRunStateConstants. * \param tacholimit The motor tachometer limit. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteSetOutputState(byte conn, byte port, char speed, byte mode, byte regmode, char turnpct, byte runstate, unsigned long tacholimit); /** * Send a StartProgram message. * Send the StartProgram direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the program to start running. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteStartProgram(byte conn, string filename); /** * Send a StopProgram message. * Send the StopProgram direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteStopProgram(byte conn); /** * Send a StopSound message. * Send the StopSound direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteStopSound(byte conn); #ifdef __ENHANCED_FIRMWARE /** * Send a GetOutputState message. * Send the GetOutputState direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param params The input and output parameters for the function call. See \ref OutputStateType. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetOutputState(byte conn, OutputStateType & params); /** * Send a GetInputValues message. * Send the GetInputValues direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param params The input and output parameters for the function call. See \ref InputValuesType. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetInputValues(byte conn, InputValuesType & params); /** * Send a GetBatteryLevel message. * Send the GetBatteryLevel direct command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param value The battery level value. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetBatteryLevel(byte conn, int & value); /** * Send a LowspeedGetStatus message. * This method sends a LowspeedGetStatus direct command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param value The count of available bytes to read. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteLowspeedGetStatus(byte conn, byte & value); /** * Send a LowspeedRead message. * Send the LowspeedRead direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The input port from which to read I2C data. See \ref InPorts. * \param bread The number of bytes read. * \param data A byte array containing the data read from the I2C device. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteLowspeedRead(byte conn, byte port, byte & bread, byte & data[]); /** * Send a GetCurrentProgramName message. * This method sends a GetCurrentProgramName direct command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param name The current program name. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetCurrentProgramName(byte conn, string & name); /** * Send a DatalogRead message. * Send the DatalogRead direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param remove Remove the datalog message from the queue after reading it (true or false). * \param cnt The number of bytes read from the datalog. * \param log A byte array containing the datalog contents. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteDatalogRead(byte conn, bool remove, byte & cnt, byte & log[]); /** * Send a GetContactCount message. * This method sends a GetContactCount direct command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param cnt The number of contacts. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetContactCount(byte conn, byte & cnt); /** * Send a GetContactName message. * Send the GetContactName direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param idx The index of the contact. * \param name The name of the specified contact. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetContactName(byte conn, byte idx, string & name); /** * Send a GetConnectionCount message. * This method sends a GetConnectionCount direct command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param cnt The number of connections. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetConnectionCount(byte conn, byte & cnt); /** * Send a GetConnectionName message. * Send the GetConnectionName direct command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param idx The index of the connection. * \param name The name of the specified connection. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetConnectionName(byte conn, byte idx, string & name); /** * Send a GetProperty message. * Send the GetProperty direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param property The property to read. See \ref RCPropertyConstants. * \param value The property value. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetProperty(byte conn, byte property, variant & value); #endif /** * Send a ResetTachoCount message. * Send the ResetTachoCount direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The output port to reset the tachometer count on. See \ref OutputPortConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteResetTachoCount(byte conn, byte port); /** * Send a DatalogSetTimes message. * Send the DatalogSetTimes direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param synctime The datalog sync time. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteDatalogSetTimes(byte conn, long synctime); /** * Send a SetProperty message. * Send the SetProperty direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param prop The property to set. See \ref RCPropertyConstants. * \param value The new property value. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteSetProperty(byte conn, byte prop, variant value); /** * Send a LowspeedWrite message. * Send the LowspeedWrite direct command on the specified connection slot. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param port The I2C port. See \ref InPorts. * \param txlen The number of bytes you are writing to the I2C device. * \param rxlen The number of bytes want to read from the I2C device. * \param data A byte array containing the data you are writing to the device. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteLowspeedWrite(byte conn, byte port, byte txlen, byte rxlen, byte data[]); /** @} */ // end of CommModuleDCFunctions group /** @defgroup CommModuleSCFunctions System Command functions * Functions for sending system commands to another NXT. * @{ */ #ifdef __ENHANCED_FIRMWARE /** * Send an OpenRead message. * Send the OpenRead system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to open for reading. * \param handle The handle of the file. * \param size The size of the file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteOpenRead(byte conn, string filename, byte & handle, long & size); /** * Send an OpenAppendData message. * Send the OpenAppendData system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to open for appending. * \param handle The handle of the file. * \param size The size of the file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteOpenAppendData(byte conn, string filename, byte & handle, long & size); /** * Send a DeleteFile message. * Send the DeleteFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to delete. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteDeleteFile(byte conn, string filename); /** * Send a FindFirstFile message. * Send the FindFirstFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param mask The filename mask for the files you want to find. * \param handle The handle of the found file. * \param name The name of the found file. * \param size The size of the found file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteFindFirstFile(byte conn, string mask, byte & handle, string & name, long & size); /** * Send a GetFirmwareVersion message. * This method sends a GetFirmwareVersion system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param pmin The protocol minor version byte. * \param pmaj The protocol major version byte. * \param fmin The firmware minor version byte. * \param fmaj The firmware major version byte. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetFirmwareVersion(byte conn, byte & pmin, byte & pmaj, byte & fmin, byte & fmaj); /** * Send a GetBluetoothAddress message. * This method sends a GetBluetoothAddress system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param btaddr The bluetooth address of the remote device. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetBluetoothAddress(byte conn, byte & btaddr[]); /** * Send a GetDeviceInfo message. * This method sends a GetDeviceInfo system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param name The name of the remote device. * \param btaddr The bluetooth address of the remote device. * \param btsignal The signal strength of each connection on the remote device. * \param freemem The number of bytes of free flash memory on the remote device. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteGetDeviceInfo(byte conn, string & name, byte & btaddr[], byte & btsignal[], long & freemem); /** * Send a DeleteUserFlash message. * This method sends a DeleteUserFlash system command to the device on the specified * connection. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteDeleteUserFlash(byte conn); /** * Send an OpenWrite message. * Send the OpenWrite system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to open for writing (i.e., create the file). * \param size The size for the new file. * \param handle The handle of the new file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteOpenWrite(byte conn, string filename, long size, byte & handle); /** * Send an OpenWriteLinear message. * Send the OpenWriteLinear system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to open for writing (i.e., create the file). * \param size The size for the new file. * \param handle The handle of the new file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteOpenWriteLinear(byte conn, string filename, long size, byte & handle); /** * Send an OpenWriteData message. * Send the OpenWriteData system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param filename The name of the file to open for writing (i.e., create the file). * \param size The size for the new file. * \param handle The handle of the new file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteOpenWriteData(byte conn, string filename, long size, byte & handle); /** * Send a CloseFile message. * Send the CloseFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param handle The handle of the file to close. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteCloseFile(byte conn, byte handle); /** * Send a FindNextFile message. * Send the FindNextFile system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param handle The handle returned by the last \ref FindFirstFile or FindNextFile call. * \param name The name of the next found file. * \param size The size of the next found file. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteFindNextFile(byte conn, byte & handle, string & name, long & size); /** * Send a PollCommandLength message. * Send the PollCommandLength system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param bufnum The poll buffer you want to query (0=USBPoll, 1=HiSpeed). * \param length The number of bytes available for polling. * \return A char value indicating whether the function call succeeded or not. */ inline char RemotePollCommandLength(byte conn, byte bufnum, byte & length); /** * Send a Write message. * Send the Write system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param handle The handle of the file you are writing to. * \param numbytes The number of bytes actually written. * \param data A byte array containing the data you are writing. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteWrite(byte conn, byte & handle, int & numbytes, byte data[]); /** * Send a Read message. * Send the Read system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param handle The handle of the file you are reading from. * \param numbytes The number of bytes you want to read. Returns the number of * bytes actually read. * \param data A byte array containing the response data. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteRead(byte conn, byte & handle, int & numbytes, byte & data[]); /** * Send an IOMapRead message. * Send the IOMapRead system command on the specified connection slot. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param id The ID of the module from which to read data. * \param offset The offset into the IOMap structure from which to read. * \param numbytes The number of bytes of data to read. Returns the number of * bytes actually read. * \param data A byte array containing the response data. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteIOMapRead(byte conn, long id, int offset, int & numbytes, byte & data[]); /** * Send a PollCommand message. * Send the PollCommand system command on the specified connection slot to * write the data provided. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param bufnum The buffer from which to read data (0=USBPoll, 1=HiSpeed). * \param len The number of bytes to read. Returns the number of * bytes actually read. * \param data A byte array containing the response data. * \return A char value indicating whether the function call succeeded or not. */ inline char RemotePollCommand(byte conn, byte bufnum, byte & len, byte & data[]); /** * Send a RenameFile message. * Send the RenameFile system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param oldname The old filename. * \param newname The new filename. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteRenameFile(byte conn, string oldname, string newname); #endif /** * Send a BluetoothFactoryReset message. * This method sends a BluetoothFactoryReset system command to the device on the specified * connection. Use \ref RemoteConnectionIdle to determine when this write request is * completed. This command cannot be sent over a bluetooth connection. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteBluetoothFactoryReset(byte conn); /** * Send an IOMapWrite value message. * Send the IOMapWrite system command on the specified connection slot to * write the value provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param id The ID of the module to which to write data. * \param offset The offset into the IOMap structure to which to write. * \param value A scalar variable containing the value you are writing to the IOMap structure. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteIOMapWriteValue(byte conn, long id, int offset, variant value); /** * Send an IOMapWrite bytes message. * Send the IOMapWrite system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param id The ID of the module to which to write data. * \param offset The offset into the IOMap structure to which to write. * \param data A byte array containing the data you are writing to the IOMap structure. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteIOMapWriteBytes(byte conn, long id, int offset, byte data[]); /** * Send a SetBrickName message. * Send the SetBrickName system command on the specified connection slot to * write the data provided. * Use \ref RemoteConnectionIdle to determine when this write request is completed. * * \param conn The connection slot (0..4). Connections 0 through 3 are for * bluetooth connections. Connection 4 refers to the RS485 hi-speed port. * See \ref CommConnectionConstants. * \param name The new brick name. * \return A char value indicating whether the function call succeeded or not. */ inline char RemoteSetBrickName(byte conn, string name); /** @} */ // end of CommModuleSCFunctions group /** * Use the RS485 port. * Configure port 4 for RS485 usage. * */ inline void UseRS485(void); #ifdef __ENHANCED_FIRMWARE /** * Control the RS485 port. * Control the RS485 hi-speed port using the specified parameters. * * \param cmd The control command to send to the port. See \ref CommHiSpeedCtrlConstants. * \param baud The baud rate for the RS485 port. See \ref CommHiSpeedBaudConstants. * \param mode The RS485 port mode (data bits, stop bits, parity). See \ref * CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, \ref * CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Control(byte cmd, byte baud, unsigned int mode); /** * Check for RS485 available data. * Check the RS485 hi-speed port for available data. * * \return A value indicating whether data is available or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline bool RS485DataAvailable(void); /** * Initialize RS485 port. * Initialize the RS485 UART port to its default values. The baud rate is * set to 921600 and the mode is set to 8N1 (8 data bits, no parity, 1 stop bit). * Data cannot be sent or received over the RS485 port until the port is * configured as as a hi-speed port, the port is turned on, and the UART is * initialized. * * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Initialize(void); /** * Disable RS485. * Turn off the RS485 port. * * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Disable(void); /** * Enable RS485. * Turn on the RS485 hi-speed port so that it can be used. * * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Enable(void); /** * Read RS485 data. * Read data from the RS485 hi-speed port. * * \param buffer A byte array that will contain the data read from the RS485 port. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Read(byte & buffer[]); /** * Is RS485 sending data. * Check whether the RS485 is actively sending data. * * \return A value indicating whether data is being sent or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline bool RS485SendingData(void); /** * Check RS485 status. * Check the status of the RS485 hi-speed port. * * \param sendingData A boolean value set to true on output if data is being sent. * \param dataAvail A boolean value set to true on output if data is available to be read. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void RS485Status(bool & sendingData, bool & dataAvail); /** * Configure RS485 UART. * Configure the RS485 UART parameters, including baud rate, data bits, * stop bits, and parity. * * \param baud The baud rate for the RS485 port. See \ref CommHiSpeedBaudConstants. * \param mode The RS485 port mode (data bits, stop bits, parity). See \ref * CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, \ref * CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Uart(byte baud, unsigned int mode); /** * Write RS485 data. * Write data to the RS485 hi-speed port. * * \param buffer A byte array containing the data to write to the RS485 port. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char RS485Write(byte buffer[]); /** * Write RS485 boolean. * Write a boolean value to the RS485 hi-speed port. * * \param bval A boolean value to write over the RS485 port. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char SendRS485Bool(bool bval); /** * Write RS485 numeric. * Write a numeric value to the RS485 hi-speed port. * * \param val A numeric value to write over the RS485 port. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char SendRS485Number(long val); /** * Write RS485 string. * Write a string value to the RS485 hi-speed port. * * \param str A string value to write over the RS485 port. * \return A char value indicating whether the function call succeeded or not. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline char SendRS485String(string str); #endif /** * Get bluetooth input buffer data. * This method reads count bytes of data from the Bluetooth input buffer and * writes it to the buffer provided. * * \param offset A constant offset into the bluetooth input buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the bluetooth input buffer. */ inline void GetBTInputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get bluetooth output buffer data. * This method reads count bytes of data from the Bluetooth output buffer and * writes it to the buffer provided. * * \param offset A constant offset into the bluetooth output buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the bluetooth output buffer. */ inline void GetBTOutputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get hi-speed port input buffer data. * This method reads count bytes of data from the hi-speed port input buffer and * writes it to the buffer provided. * * \param offset A constant offset into the hi-speed port input buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the hi-speed port input buffer. */ inline void GetHSInputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get hi-speed port output buffer data. * This method reads count bytes of data from the hi-speed port output buffer and * writes it to the buffer provided. * * \param offset A constant offset into the hi-speed port output buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the hi-speed port output buffer. */ inline void GetHSOutputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get usb input buffer data. * This method reads count bytes of data from the usb input buffer and * writes it to the buffer provided. * * \param offset A constant offset into the usb input buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the usb input buffer. */ inline void GetUSBInputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get usb output buffer data. * This method reads count bytes of data from the usb output buffer and * writes it to the buffer provided. * \param offset A constant offset into the usb output buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the usb output buffer. */ inline void GetUSBOutputBuffer(const byte offset, byte cnt, byte & data[]); /** * Get usb poll buffer data. * This method reads count bytes of data from the usb poll buffer and * writes it to the buffer provided. * \param offset A constant offset into the usb poll buffer. * \param cnt The number of bytes to read. * \param data The byte array reference which will contain the data read from * the usb poll buffer. */ inline void GetUSBPollBuffer(const byte offset, byte cnt, byte & data[]); /** * Get bluetooth device name. * This method returns the name of the device at the specified index in the * Bluetooth device table. * \param devidx The device table index. * \return The device name of the specified bluetooth device. */ inline string BTDeviceName(const byte devidx); /** * Get bluetooth device name. * This method returns the name of the device at the specified index in the * Bluetooth connection table. * \param conn The connection slot (0..3). * \return The name of the bluetooth device at the specified connection slot. */ inline string BTConnectionName(const byte conn); /** * Get bluetooth device pin code. * This method returns the pin code of the device at the specified index in the * Bluetooth connection table. * \param conn The connection slot (0..3). * \return The pin code for the bluetooth device at the specified connection slot. */ inline string BTConnectionPinCode(const byte conn); /** * Get NXT name. * This method returns the name of the NXT. * \return The NXT's bluetooth name. */ inline string BrickDataName(void); /** * Get bluetooth device address. * This method reads the address of the device at the specified index within * the Bluetooth device table and stores it in the data buffer provided. * \param devidx The device table index. * \param data The byte array reference that will contain the device address. */ inline void GetBTDeviceAddress(const byte devidx, byte & data[]); /** * Get bluetooth device address. * This method reads the address of the device at the specified index within * the Bluetooth connection table and stores it in the data buffer provided. * \param conn The connection slot (0..3). * \param data The byte array reference that will contain the device address. */ inline void GetBTConnectionAddress(const byte conn, byte & data[]); /** * Get NXT address. * This method reads the address of the NXT and stores it in the data buffer * provided. * \param data The byte array reference that will contain the device address. */ inline void GetBrickDataAddress(byte & data[]); /** * Get bluetooth device class. * This method returns the class of the device at the specified index within * the Bluetooth device table. * \param devidx The device table index. * \return The device class of the specified bluetooth device. */ inline long BTDeviceClass(const byte devidx); /** * Get bluetooth device status. * This method returns the status of the device at the specified index within * the Bluetooth device table. * \param devidx The device table index. * \return The status of the specified bluetooth device. */ inline byte BTDeviceStatus(const byte devidx); /** * Get bluetooth device class. * This method returns the class of the device at the specified index within * the Bluetooth connection table. * \param conn The connection slot (0..3). * \return The class of the bluetooth device at the specified connection slot. */ inline long BTConnectionClass(const byte conn); /** * Get bluetooth device handle number. * This method returns the handle number of the device at the specified index within * the Bluetooth connection table. * \param conn The connection slot (0..3). * \return The handle number of the bluetooth device at the specified connection slot. */ inline byte BTConnectionHandleNum(const byte conn); /** * Get bluetooth device stream status. * This method returns the stream status of the device at the specified index within * the Bluetooth connection table. * \param conn The connection slot (0..3). * \return The stream status of the bluetooth device at the specified connection slot. */ inline byte BTConnectionStreamStatus(const byte conn); /** * Get bluetooth device link quality. * This method returns the link quality of the device at the specified index within * the Bluetooth connection table. * \param conn The connection slot (0..3). * \return The link quality of the specified connection slot (unimplemented). * \warning This function is not implemented at the firmware level. */ inline byte BTConnectionLinkQuality(const byte conn); /** * Get NXT bluecore version. * This method returns the bluecore version of the NXT. * \return The NXT's bluecore version number. */ inline int BrickDataBluecoreVersion(void); /** * Get NXT bluetooth state status. * This method returns the Bluetooth state status of the NXT. * \return The NXT's bluetooth state status. */ inline byte BrickDataBtStateStatus(void); /** * Get NXT bluetooth hardware status. * This method returns the Bluetooth hardware status of the NXT. * \return The NXT's bluetooth hardware status. */ inline byte BrickDataBtHardwareStatus(void); /** * Get NXT bluetooth timeout value. * This method returns the Bluetooth timeout value of the NXT. * \return The NXT's bluetooth timeout value. */ inline byte BrickDataTimeoutValue(void); /** * Get bluetooth input buffer in-pointer. * This method returns the value of the input pointer of the Bluetooth input * buffer. * \return The bluetooth input buffer's in-pointer value. */ inline byte BTInputBufferInPtr(void); /** * Get bluetooth input buffer out-pointer. * This method returns the value of the output pointer of the Bluetooth input * buffer. * \return The bluetooth input buffer's out-pointer value. */ inline byte BTInputBufferOutPtr(void); /** * Get bluetooth output buffer in-pointer. * This method returns the value of the input pointer of the Bluetooth output * buffer. * \return The bluetooth output buffer's in-pointer value. */ inline byte BTOutputBufferInPtr(void); /** * Get bluetooth output buffer out-pointer. * This method returns the value of the output pointer of the Bluetooth output * buffer. * \return The bluetooth output buffer's out-pointer value. */ inline byte BTOutputBufferOutPtr(void); /** * Get hi-speed port input buffer in-pointer. * This method returns the value of the input pointer of the hi-speed port input * buffer. * \return The hi-speed port input buffer's in-pointer value. */ inline byte HSInputBufferInPtr(void); /** * Get hi-speed port input buffer out-pointer. * This method returns the value of the output pointer of the hi-speed port input * buffer. * \return The hi-speed port input buffer's out-pointer value. */ inline byte HSInputBufferOutPtr(void); /** * Get hi-speed port output buffer in-pointer. * This method returns the value of the input pointer of the hi-speed port output * buffer. * \return The hi-speed port output buffer's in-pointer value. */ inline byte HSOutputBufferInPtr(void); /** * Get hi-speed port output buffer out-pointer. * This method returns the value of the output pointer of the hi-speed port output * buffer. * \return The hi-speed port output buffer's out-pointer value. */ inline byte HSOutputBufferOutPtr(void); /** * Get usb port input buffer in-pointer. * This method returns the value of the input pointer of the usb port input * buffer. * \return The USB port input buffer's in-pointer value. */ inline byte USBInputBufferInPtr(void); /** * Get usb port input buffer out-pointer. * This method returns the value of the output pointer of the usb port input * buffer. * \return The USB port input buffer's out-pointer value. */ inline byte USBInputBufferOutPtr(void); /** * Get usb port output buffer in-pointer. * This method returns the value of the input pointer of the usb port output * buffer. * \return The USB port output buffer's in-pointer value. */ inline byte USBOutputBufferInPtr(void); /** * Get usb port output buffer out-pointer. * This method returns the value of the output pointer of the usb port output * buffer. * \return The USB port output buffer's out-pointer value. */ inline byte USBOutputBufferOutPtr(void); /** * Get usb port poll buffer in-pointer. * This method returns the value of the input pointer of the usb port poll * buffer. * \return The USB port poll buffer's in-pointer value. */ inline byte USBPollBufferInPtr(void); /** * Get usb port poll buffer out-pointer. * This method returns the value of the output pointer of the usb port poll * buffer. * \return The USB port poll buffer's out-pointer value. */ inline byte USBPollBufferOutPtr(void); /** * Get bluetooth device count. * This method returns the number of devices defined within the Bluetooth * device table. * \return The count of known bluetooth devices. */ inline byte BTDeviceCount(void); /** * Get bluetooth device name count. * This method returns the number of device names defined within the Bluetooth * device table. This usually has the same value as BTDeviceCount but it can * differ in some instances. * \return The count of known bluetooth device names. */ inline byte BTDeviceNameCount(void); /** * Get hi-speed port flags. * This method returns the value of the hi-speed port flags. * \return The hi-speed port flags. See \ref CommHiSpeedFlagsConstants. */ inline byte HSFlags(void); /** * Get hi-speed port speed. * This method returns the value of the hi-speed port speed (baud rate). * \return The hi-speed port speed (baud rate). See \ref CommHiSpeedBaudConstants. */ inline byte HSSpeed(void); /** * Get hi-speed port state. * This method returns the value of the hi-speed port state. * \return The hi-speed port state. See \ref CommHiSpeedStateConstants. */ inline byte HSState(void); #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) /** * Get hi-speed port mode. * This method returns the value of the hi-speed port mode. * \return The hi-speed port mode (data bits, stop bits, parity). See * \ref CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, * \ref CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline int HSMode(void); /** * Get Bluetooth data mode. * This method returns the value of the Bluetooth data mode. * \return The Bluetooth data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline int BTDataMode(void); /** * Get hi-speed port datamode. * This method returns the value of the hi-speed port data mode. * \return The hi-speed port data mode. See \ref CommDataModeConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline int HSDataMode(void); #endif /** * Get USB state. * This method returns the value of the USB state. * \return The USB state. */ inline byte USBState(void); /** * Set bluetooth input buffer data. * Write cnt bytes of data to the bluetooth input buffer at offset. * \param offset A constant offset into the input buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetBTInputBuffer(const byte offset, byte cnt, byte data[]); /** * Set bluetooth input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param n The new in-pointer value (0..127). */ inline void SetBTInputBufferInPtr(byte n); /** * Set bluetooth input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param n The new out-pointer value (0..127). */ inline void SetBTInputBufferOutPtr(byte n); /** * Set bluetooth output buffer data. * Write cnt bytes of data to the bluetooth output buffer at offset. * \param offset A constant offset into the output buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetBTOutputBuffer(const byte offset, byte cnt, byte data[]); /** * Set bluetooth output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param n The new in-pointer value (0..127). */ inline void SetBTOutputBufferInPtr(byte n); /** * Set bluetooth output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param n The new out-pointer value (0..127). */ inline void SetBTOutputBufferOutPtr(byte n); /** * Set hi-speed port input buffer data. * Write cnt bytes of data to the hi-speed port input buffer at offset. * \param offset A constant offset into the input buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetHSInputBuffer(const byte offset, byte cnt, byte data[]); /** * Set hi-speed port input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param n The new in-pointer value (0..127). */ inline void SetHSInputBufferInPtr(byte n); /** * Set hi-speed port input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param n The new out-pointer value (0..127). */ inline void SetHSInputBufferOutPtr(byte n); /** * Set hi-speed port output buffer data. * Write cnt bytes of data to the hi-speed port output buffer at offset. * \param offset A constant offset into the output buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetHSOutputBuffer(const byte offset, byte cnt, byte data[]); /** * Set hi-speed port output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param n The new in-pointer value (0..127). */ inline void SetHSOutputBufferInPtr(byte n); /** * Set hi-speed port output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param n The new out-pointer value (0..127). */ inline void SetHSOutputBufferOutPtr(byte n); /** * Set USB input buffer data. * Write cnt bytes of data to the USB input buffer at offset. * \param offset A constant offset into the input buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetUSBInputBuffer(const byte offset, byte cnt, byte data[]); /** * Set USB input buffer in-pointer. * Set the value of the input buffer in-pointer. * \param n The new in-pointer value (0..63). */ inline void SetUSBInputBufferInPtr(byte n); /** * Set USB input buffer out-pointer. * Set the value of the input buffer out-pointer. * \param n The new out-pointer value (0..63). */ inline void SetUSBInputBufferOutPtr(byte n); /** * Set USB output buffer data. * Write cnt bytes of data to the USB output buffer at offset. * \param offset A constant offset into the output buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetUSBOutputBuffer(const byte offset, byte cnt, byte data[]); /** * Set USB output buffer in-pointer. * Set the value of the output buffer in-pointer. * \param n The new in-pointer value (0..63). */ inline void SetUSBOutputBufferInPtr(byte n); /** * Set USB output buffer out-pointer. * Set the value of the output buffer out-pointer. * \param n The new out-pointer value (0..63). */ inline void SetUSBOutputBufferOutPtr(byte n); /** * Set USB poll buffer data. * Write cnt bytes of data to the USB poll buffer at offset. * \param offset A constant offset into the poll buffer * \param cnt The number of bytes to write * \param data A byte array containing the data to write */ inline void SetUSBPollBuffer(const byte offset, byte cnt, byte data[]); /** * Set USB poll buffer in-pointer. * Set the value of the poll buffer in-pointer. * \param n The new in-pointer value (0..63). */ inline void SetUSBPollBufferInPtr(byte n); /** * Set USB poll buffer out-pointer. * Set the value of the poll buffer out-pointer. * \param n The new out-pointer value (0..63). */ inline void SetUSBPollBufferOutPtr(byte n); /** * Set hi-speed port flags. * This method sets the value of the hi-speed port flags. * \param hsFlags The hi-speed port flags. See \ref CommHiSpeedFlagsConstants. */ inline void SetHSFlags(byte hsFlags); /** * Set hi-speed port speed. * This method sets the value of the hi-speed port speed (baud rate). * \param hsSpeed The hi-speed port speed (baud rate). See \ref CommHiSpeedBaudConstants. */ inline void SetHSSpeed(byte hsSpeed); /** * Set hi-speed port state. * This method sets the value of the hi-speed port state. * \param hsState The hi-speed port state. See \ref CommHiSpeedStateConstants. */ inline void SetHSState(byte hsState); #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) /** * Set hi-speed port mode. * This method sets the value of the hi-speed port mode. * \param hsMode The hi-speed port mode (data bits, stop bits, parity). See * \ref CommHiSpeedDataBitsConstants, \ref CommHiSpeedStopBitsConstants, * \ref CommHiSpeedParityConstants, and \ref CommHiSpeedCombinedConstants. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SetHSMode(unsigned int hsMode) { asm { __setHSMode(_n) } } /** * Set Bluetooth data mode. * This method sets the value of the Bluetooth data mode. * \param dataMode The Bluetooth data mode. See \ref CommDataModeConstants. Must be a constant. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SetBTDataMode(const byte dataMode); /** * Set hi-speed port data mode. * This method sets the value of the hi-speed port data mode. * \param dataMode The hi-speed port data mode. See \ref CommDataModeConstants. Must be a constant. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void SetHSDataMode(const byte dataMode); #endif /** * Set USB state. * This method sets the value of the USB state. * \param usbState The USB state. */ inline void SetUSBState(byte usbState); /** * Write message. * This function lets you write a message to a queue (aka mailbox) using the * values specified via the \ref MessageWriteType structure. * * \param args The MessageWriteType structure containing the needed parameters. */ void SysMessageWrite(MessageWriteType & args); /** * Read message. * This function lets you read a message from a queue (aka mailbox) using the * values specified via the \ref MessageReadType structure. * * \param args The MessageReadType structure containing the needed parameters. */ void SysMessageRead(MessageReadType & args); /** * Write data to a Bluetooth connection. * This function lets you write to a Bluetooth connection using the values * specified via the \ref CommBTWriteType structure. * * \param args The CommBTWriteType structure containing the needed parameters. */ void SysCommBTWrite(CommBTWriteType & args); /** * Check Bluetooth connection status. * This function lets you check the status of a Bluetooth connection using the * values specified via the \ref CommBTCheckStatusType structure. * * \param args The CommBTCheckStatusType structure containing the needed * parameters. */ void SysCommBTCheckStatus(CommBTCheckStatusType & args); #ifdef __ENHANCED_FIRMWARE /** * Execute any Comm module command. * This function lets you directly execute the Comm module's primary function * using the values specified via the \ref CommExecuteFunctionType structure. * * \param args The CommExecuteFunctionType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysCommExecuteFunction(CommExecuteFunctionType & args); /** * Control the hi-speed port. * This function lets you control the hi-speed port * using the values specified via the \ref CommHSControlType structure. * * \param args The CommHSControlType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysCommHSControl(CommHSControlType & args); /** * Check the hi-speed port status. * This function lets you check the hi-speed port status * using the values specified via the \ref CommHSCheckStatusType structure. * * \param args The CommHSCheckStatusType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysCommHSCheckStatus(CommHSCheckStatusType & args); /** * Read from the hi-speed port. * This function lets you read from the hi-speed port * using the values specified via the \ref CommHSReadWriteType structure. * * \param args The CommHSReadWriteType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysCommHSRead(CommHSReadWriteType & args); /** * Write to the hi-speed port. * This function lets you write to the hi-speed port * using the values specified via the \ref CommHSReadWriteType structure. * * \param args The CommHSReadWriteType structure containing the needed * parameters. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SysCommHSWrite(CommHSReadWriteType & args); #endif #if __FIRMWARE_VERSION > 107 /** * Turn on or off the bluetooth subsystem. * This function lets you turn on or off the bluetooth subsystem * using the values specified via the \ref CommBTOnOffType structure. * * \param args The CommBTOnOffType structure containing the needed * parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysCommBTOnOff(CommBTOnOffType & args); /** * Connect or disconnect a bluetooth device. * This function lets you connect or disconnect a bluetooth device * using the values specified via the \ref CommBTConnectionType structure. * * \param args The CommBTConnectionType structure containing the needed * parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysCommBTConnection(CommBTConnectionType & args); #endif /* // these functions really cannot be used for any useful purpose (read-only) inline void SetBTDeviceName(const byte devidx, string str); inline void SetBTDeviceAddress(const byte devidx, const byte btaddr[]); inline void SetBTConnectionName(const byte conn, string str); inline void SetBTConnectionPinCode(const byte conn, const byte code[]); inline void SetBTConnectionAddress(const byte conn, const byte btaddr[]); inline void SetBrickDataName(string str); inline void SetBrickDataAddress(const byte p, byte btaddr[]); inline void SetBTDeviceClass(const byte devidx, unsigned long class); inline void SetBTDeviceStatus(const byte devidx, const byte status); inline void SetBTConnectionClass(const byte conn, unsigned long class); inline void SetBTConnectionHandleNum(const byte conn, const byte handleNum); inline void SetBTConnectionStreamStatus(const byte conn, const byte status); inline void SetBTConnectionLinkQuality(const byte conn, const byte quality); inline void SetBrickDataBluecoreVersion(int version); inline void SetBrickDataBtStateStatus(byte status); inline void SetBrickDataBtHardwareStatus(byte status); inline void SetBrickDataTimeoutValue(const byte timeout); inline void SetBTDeviceCount(byte count); inline void SetBTDeviceNameCount(byte count); */ #else #define SendMessage(_queue, _msg) asm { __sendMessage(_queue, _msg, __RETVAL__) } #define ReceiveMessage(_queue, _clear, _msg) asm { __receiveMessage(_queue, _clear, _msg, __RETVAL__) } #define BluetoothStatus(_conn) asm { __bluetoothStatus(_conn, __RETVAL__) } #define BluetoothWrite(_conn, _buffer) asm { __bluetoothWrite(_conn, _buffer, __RETVAL__) } #define RemoteConnectionWrite(_conn, _buffer) asm { __connectionRawWrite(_conn, _buffer, __RETVAL__) } #define RemoteConnectionIdle(_conn) asm { __remoteConnectionIdle(_conn, __RETVAL__) } #define SendRemoteBool(_conn, _queue, _bval) asm { __sendRemoteBool(_conn, _queue, _bval, __RETVAL__) } #define SendRemoteNumber(_conn, _queue, _val) asm { __sendRemoteNumber(_conn, _queue, _val, __RETVAL__) } #define SendRemoteString(_conn, _queue, _str) asm { __sendRemoteString(_conn, _queue, _str, __RETVAL__) } #define SendResponseBool(_queue, _bval) asm { __sendResponseBool(_queue, _bval, __RETVAL__) } #define SendResponseNumber(_queue, _val) asm { __sendResponseNumber(_queue, _val, __RETVAL__) } #define SendResponseString(_queue, _msg) asm { __sendResponseString(_queue, _msg, __RETVAL__) } #define ReceiveRemoteBool(_queue, _clear, _bval) asm { __receiveRemoteBool(_queue, _clear, _bval, __RETVAL__) } #define ReceiveRemoteNumber(_queue, _clear, _val) asm { __receiveRemoteNumber(_queue, _clear, _val, __RETVAL__) } #define ReceiveRemoteString(_queue, _clear, _str) asm { __receiveMessage(_queue, _clear, _str, __RETVAL__) } #define ReceiveRemoteMessageEx(_queue, _clear, _str, _val, _bval) asm { __receiveRemoteMessageEx(_queue, _clear, _str, _val, _bval, __RETVAL__) } #define RemoteMessageRead(_conn, _queue) asm { __remoteMessageRead(_conn, _queue, __RETVAL__) } #define RemoteMessageWrite(_conn, _queue, _msg) asm { __sendRemoteString(_conn, _queue, _msg, __RETVAL__) } #define RemoteStartProgram(_conn, _filename) asm { __remoteStartProgram(_conn, _filename, __RETVAL__) } #define RemoteStopProgram(_conn) asm { __connectionWrite(_conn, __DCStopProgramPacket, __RETVAL__) } #define RemotePlaySoundFile(_conn, _filename, _bloop) asm { __remotePlaySoundFile(_conn, _filename, _bloop, __RETVAL__) } #define RemotePlayTone(_conn, _frequency, _duration) asm { __remotePlayTone(_conn, _frequency, _duration, __RETVAL__) } #define RemoteStopSound(_conn) asm { __connectionWrite(_conn, __DCStopSoundPacket, __RETVAL__) } #define RemoteKeepAlive(_conn) asm { __connectionWrite(_conn, __DCKeepAlivePacket, __RETVAL__) } #define RemoteResetScaledValue(_conn, _port) asm { __remoteResetScaledValue(_conn, _port, __RETVAL__) } #define RemoteResetMotorPosition(_conn, _port, _brelative) asm { __remoteResetMotorPosition(_conn, _port, _brelative, __RETVAL__) } #define RemoteSetInputMode(_conn, _port, _type, _mode) asm { __remoteSetInputMode(_conn, _port, _type, _mode, __RETVAL__) } #define RemoteSetOutputState(_conn, _port, _speed, _mode, _regmode, _turnpct, _runstate, _tacholimit) asm { __remoteSetOutputState(_conn, _port, _speed, _mode, _regmode, _turnpct, _runstate, _tacholimit, __RETVAL__) } #define RemoteResetTachoCount(_conn, _port) asm { __remoteResetTachoCount(_conn, _port, __RETVAL__) } #define RemoteDatalogSetTimes(_conn, _synctime) asm { __remoteDatalogSetTimes(_conn, _synctime, __RETVAL__) } #define RemoteSetProperty(_conn, _prop, _value) asm { __remoteSetProperty(_conn, _prop, _value, __RETVAL__) } #define RemoteLowspeedWrite(_conn, _port, _txlen, _rxlen, _data) asm { __remoteLowspeedWrite(_conn, _port, _txlen, _rxlen, _data, __RETVAL__) } #ifdef __ENHANCED_FIRMWARE #define RemoteGetOutputState(_conn, _params) asm { \ compchktype _params, OutputStateType \ __remoteGetOutputState(_conn, _params, __RETVAL__) \ } #define RemoteGetInputValues(_conn, _params) asm { \ compchktype _params, InputValuesType \ __remoteGetInputValues(_conn, _params, __RETVAL__) \ } #define RemoteGetBatteryLevel(_conn, _value) asm { __remoteGetBatteryLevel(_conn, _value, __RETVAL__) } #define RemoteLowspeedGetStatus(_conn, _value) asm { __remoteLowspeedGetStatus(_conn, _value, __RETVAL__) } #define RemoteLowspeedRead(_conn, _port, _bread, _data) asm { __remoteLowspeedRead(_conn, _port, _bread, _data, __RETVAL__) } #define RemoteGetCurrentProgramName(_conn, _name) asm { __remoteGetCurrentProgramName(_conn, _name, __RETVAL__) } #define RemoteDatalogRead(_conn, _remove, _cnt, _log) asm { __remoteDatalogRead(_conn, _remove, _cnt, _log, __RETVAL__) } #define RemoteGetContactCount(_conn, _cnt) asm { __remoteGetContactCount(_conn, _cnt, __RETVAL__) } #define RemoteGetContactName(_conn, _idx, _name) asm { __remoteGetContactName(_conn, _idx, _name, __RETVAL__) } #define RemoteGetConnectionCount(_conn, _cnt) asm { __remoteGetConnectionCount(_conn, _cnt, __RETVAL__) } #define RemoteGetConnectionName(_conn, _idx, _name) asm { __remoteGetConnectionName(_conn, _idx, _name, __RETVAL__) } #define RemoteGetProperty(_conn, _property, _value) asm { __remoteGetProperty(_conn, _property, _value, __RETVAL__) } #else #define RemoteGetOutputState(_conn, _port) asm { __remoteGetOutputState(_conn, _port, __RETVAL__) } #define RemoteGetInputValues(_conn, _port) asm { __remoteGetInputValues(_conn, _port, __RETVAL__) } #define RemoteGetBatteryLevel(_conn) asm { __remoteGetBatteryLevel(_conn, __RETVAL__) } #define RemoteLowspeedGetStatus(_conn) asm { __remoteLowspeedGetStatus(_conn, __RETVAL__) } #define RemoteLowspeedRead(_conn, _port) asm { __remoteLowspeedRead(_conn, _port, __RETVAL__) } #define RemoteGetCurrentProgramName(_conn) asm { __remoteGetCurrentProgramName(_conn, __RETVAL__) } #define RemoteDatalogRead(_conn, _remove) asm { __remoteDatalogRead(_conn, _remove, __RETVAL__) } #define RemoteGetContactCount(_conn) asm { __remoteGetContactCount(_conn, __RETVAL__) } #define RemoteGetContactName(_conn, _idx) asm { __remoteGetContactName(_conn, _idx, __RETVAL__) } #define RemoteGetConnectionCount(_conn) asm { __remoteGetConnectionCount(_conn, __RETVAL__) } #define RemoteGetConnectionName(_conn, _idx) asm { __remoteGetConnectionName(_conn, _idx, __RETVAL__) } #define RemoteGetProperty(_conn, _property) asm { __remoteGetProperty(_conn, _property, __RETVAL__) } #endif #ifdef __ENHANCED_FIRMWARE #define RemoteOpenRead(_conn, _filename, _handle, _size) asm { __remoteOpenRead(_conn, _filename, _handle, _size, __RETVAL__) } #define RemoteOpenWrite(_conn, _filename, _size, _handle) asm { __remoteOpenWrite(_conn, _filename, _size, _handle, __RETVAL__) } #define RemoteRead(_conn, _handle, _numbytes, _data) asm { __remoteRead(_conn, _handle, _numbytes, _data, __RETVAL__) } #define RemoteWrite(_conn, _handle, _numbytes, _data) asm { __remoteWrite(_conn, _handle, _numbytes, _data, __RETVAL__) } #define RemoteCloseFile(_conn, _handle) asm { __remoteCloseFile(_conn, _handle, __RETVAL__) } #define RemoteDeleteFile(_conn, _filename) asm { __remoteDeleteFile(_conn, _filename, __RETVAL__) } #define RemoteDeleteUserFlash(_conn) asm { __remoteDeleteUserFlash(_conn, __RETVAL__) } #define RemoteFindFirstFile(_conn, _mask, _handle, _name, _size) asm { __remoteFindFirstFile(_conn, _mask, _handle, _name, _size, __RETVAL__) } #define RemoteFindNextFile(_conn, _handle, _name, _size) asm { __remoteFindNextFile(_conn, _handle, _name, _size, __RETVAL__) } #define RemoteGetFirmwareVersion(_conn, _pmin, _pmaj, _fmin, _fmaj) asm { __remoteGetFirmwareVersion(_conn, _pmin, _pmaj, _fmin, _fmaj, __RETVAL__) } #define RemoteOpenWriteLinear(_conn, _filename, _size, _handle) asm { __remoteOpenWriteLinear(_conn, _filename, _size, _handle, __RETVAL__) } #define RemoteOpenWriteData(_conn, _filename, _size, _handle) asm { __remoteOpenWriteData(_conn, _filename, _size, _handle, __RETVAL__) } #define RemoteOpenAppendData(_conn, _filename, _handle, _size) asm { __remoteOpenAppendData(_conn, _filename, _handle, _size, __RETVAL__) } #define RemoteGetDeviceInfo(_conn, _name, _btaddr, _btsignal, _freemem) asm { __remoteGetDeviceInfo(_conn, _name, _btaddr, _btsignal, _freemem, __RETVAL__) } #define RemotePollCommandLength(_conn, _bufnum, _length) asm { __remotePollCommandLength(_conn, _bufnum, _length, __RETVAL__) } #define RemotePollCommand(_conn, _bufnum, _len, _data) asm { __remotePollCommand(_conn, _bufnum, _len, _data, __RETVAL__) } #define RemoteIOMapRead(_conn, _id, _offset, _numbytes, _data) asm { __remoteIOMapRead(_conn, _id, _offset, _numbytes, _data, __RETVAL__) } #define RemoteGetBluetoothAddress(_conn, _btaddr) asm { __remoteGetBluetoothAddress(_conn, _btaddr, __RETVAL__) } #define RemoteRenameFile(_conn, _oldname, _newname) asm { __remoteRenameFile(_conn, _oldname, _newname, __RETVAL__) } #else #define RemoteOpenRead(_conn, _filename) asm { __remoteOpenRead(_conn, _filename, __RETVAL__) } #define RemoteOpenWrite(_conn, _filename, _size) asm { __remoteOpenWrite(_conn, _filename, _size, __RETVAL__) } #define RemoteRead(_conn, _handle, _numbytes) asm { __remoteRead(_conn, _handle, _numbytes, __RETVAL__) } #define RemoteWrite(_conn, _handle, _data) asm { __remoteWrite(_conn, _handle, _data, __RETVAL__) } #define RemoteCloseFile(_conn, _handle) asm { __remoteCloseFile(_conn, _handle, __RETVAL__) } #define RemoteDeleteFile(_conn, _filename) asm { __remoteDeleteFile(_conn, _filename, __RETVAL__) } #define RemoteDeleteUserFlash(_conn) asm { __connectionWrite(_conn, __SCDeleteUserFlashPacket, __RETVAL__) } #define RemoteFindFirstFile(_conn, _mask) asm { __remoteFindFirstFile(_conn, _mask, __RETVAL__) } #define RemoteFindNextFile(_conn, _handle) asm { __remoteFindNextFile(_conn, _handle, __RETVAL__) } #define RemoteGetFirmwareVersion(_conn) asm { __connectionWrite(_conn, __SCGetFirmwareVerPacket, __RETVAL__) } #define RemoteOpenWriteLinear(_conn, _filename, _size) asm { __remoteOpenWriteLinear(_conn, _filename, _size, __RETVAL__) } #define RemoteOpenWriteData(_conn, _filename, _size) asm { __remoteOpenWriteData(_conn, _filename, _size, __RETVAL__) } #define RemoteOpenAppendData(_conn, _filename) asm { __remoteOpenAppendData(_conn, _filename, __RETVAL__) } #define RemoteGetDeviceInfo(_conn) asm { __connectionWrite(_conn, __SCGetDeviceInfoPacket, __RETVAL__) } #define RemotePollCommandLength(_conn, _bufnum) asm { __remotePollCommandLength(_conn, _bufnum, __RETVAL__) } #define RemotePollCommand(_conn, _bufnum, _len) asm { __remotePollCommand(_conn, _bufnum, _len, __RETVAL__) } #define RemoteIOMapRead(_conn, _id, _offset, _numbytes) asm { __remoteIOMapRead(_conn, _id, _offset, _numbytes, __RETVAL__) } #define RemoteGetBluetoothAddress(_conn) asm { __connectionWrite(_conn, __SCBTGetAddressPacket, __RETVAL__) } #endif #define RemoteBluetoothFactoryReset(_conn) asm { __connectionWrite(_conn, __SCBTFactoryResetPacket, __RETVAL__) } #define RemoteIOMapWriteValue(_conn, _id, _offset, _value) asm { __remoteIOMapWriteValue(_conn, _id, _offset, _value, __RETVAL__) } #define RemoteIOMapWriteBytes(_conn, _id, _offset, _data) asm { __remoteIOMapWriteBytes(_conn, _id, _offset, _data, __RETVAL__) } #define RemoteSetBrickName(_conn, _name) asm { __remoteSetBrickName(_conn, _name, __RETVAL__) } #define UseRS485() asm { __UseRS485() } #ifdef __ENHANCED_FIRMWARE #define RS485Status(_sendingData, _dataAvail) asm { __RS485Status(_sendingData, _dataAvail) } #define RS485SendingData() asm { __RS485Status(__RETVAL__, __TMPBYTE__) } #define RS485DataAvailable() asm { __RS485Status(__TMPBYTE__, __RETVAL__) } #define RS485Write(_buffer) asm { __RS485Write(_buffer, __RETVAL__) } #define RS485Read(_buffer) asm { __RS485Read(_buffer, __RETVAL__) } #if __FIRMWARE_VERSION > 107 #define RS485Control(_cmd, _baud, _mode) asm { __RS485Control(_cmd, _baud, _mode, __RETVAL__) } #define RS485Uart(_baud, _mode) asm { __RS485Control(HS_CTRL_UART, _baud, _mode, __RETVAL__) } #define RS485Initialize() asm { __RS485Control(HS_CTRL_UART, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, __RETVAL__) } #define RS485Enable() asm { __RS485Control(HS_CTRL_INIT, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, __RETVAL__) } #define RS485Disable() asm { __RS485Control(HS_CTRL_EXIT, HS_BAUD_DEFAULT, HS_MODE_DEFAULT, __RETVAL__) } #else #define RS485Control(_cmd, _baud) asm { __RS485Control(_cmd, _baud, __RETVAL__) } #define RS485Uart(_baud) asm { __RS485Control(HS_CTRL_UART, _baud, __RETVAL__) } #define RS485Initialize() asm { __RS485Control(HS_CTRL_UART, HS_BAUD_DEFAULT, __RETVAL__) } #define RS485Enable() asm { __RS485Control(HS_CTRL_INIT, HS_BAUD_DEFAULT, __RETVAL__) } #define RS485Disable() asm { __RS485Control(HS_CTRL_EXIT, HS_BAUD_DEFAULT, __RETVAL__) } #endif #define SendRS485Bool(_bval) asm { __sendRS485Bool(_bval, __RETVAL__) } #define SendRS485Number(_val) asm { __sendRS485Number(_val, __RETVAL__) } #define SendRS485String(_str) asm { __sendRS485String(_str, __RETVAL__) } #endif #define GetBTInputBuffer(_offset, _cnt, _data) asm { __getBTInputBuffer(_offset, _cnt, _data) } #define GetBTOutputBuffer(_offset, _cnt, _data) asm { __getBTOutputBuffer(_offset, _cnt, _data) } #define GetHSInputBuffer(_offset, _cnt, _data) asm { __getHSInputBuffer(_offset, _cnt, _data) } #define GetHSOutputBuffer(_offset, _cnt, _data) asm { __getHSOutputBuffer(_offset, _cnt, _data) } #define GetUSBInputBuffer(_offset, _cnt, _data) asm { __getUSBInputBuffer(_offset, _cnt, _data) } #define GetUSBOutputBuffer(_offset, _cnt, _data) asm { __getUSBOutputBuffer(_offset, _cnt, _data) } #define GetUSBPollBuffer(_offset, _cnt, _data) asm { __getUSBPollBuffer(_offset, _cnt, _data) } #define BTDeviceName(_p) asm { GetBTDeviceName(_p, __STRRETVAL__) } #define BTConnectionName(_p) asm { GetBTConnectionName(_p, __STRRETVAL__) } #define BTConnectionPinCode(_p) asm { GetBTConnectionPinCode(_p, __STRRETVAL__) } #define BrickDataName() asm { GetBrickDataName(__STRRETVAL__) } #define GetBTDeviceAddress(_p, _data) asm { __getBTDeviceAddress(_p, _data) } #define GetBTConnectionAddress(_p, _data) asm { __getBTConnectionAddress(_p, _data) } #define GetBrickDataAddress(_data) asm { __getCommModuleBytes(CommOffsetBrickDataBdAddr, 7, _data) } #define BTDeviceClass(_p) asm { GetBTDeviceClass(_p, __TMPLONG__) __RETURN__ __TMPLONG__ } #define BTDeviceStatus(_p) asm { GetBTDeviceStatus(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTConnectionClass(_p) asm { GetBTConnectionClass(_p, __TMPLONG__) __RETURN__ __TMPLONG__ } #define BTConnectionHandleNum(_p) asm { GetBTConnectionHandleNum(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTConnectionStreamStatus(_p) asm { GetBTConnectionStreamStatus(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTConnectionLinkQuality(_p) asm { GetBTConnectionLinkQuality(_p, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BrickDataBluecoreVersion() asm { GetBrickDataBluecoreVersion(__TMPWORD__) __RETURN__ __TMPWORD__ } #define BrickDataBtStateStatus() asm { GetBrickDataBtStateStatus(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BrickDataBtHardwareStatus() asm { GetBrickDataBtHardwareStatus(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BrickDataTimeoutValue() asm { GetBrickDataTimeoutValue(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTInputBufferInPtr() asm { GetBTInputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTInputBufferOutPtr() asm { GetBTInputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTOutputBufferInPtr() asm { GetBTOutputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTOutputBufferOutPtr() asm { GetBTOutputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSInputBufferInPtr() asm { GetHSInputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSInputBufferOutPtr() asm { GetHSInputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSOutputBufferInPtr() asm { GetHSOutputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSOutputBufferOutPtr() asm { GetHSOutputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBInputBufferInPtr() asm { GetUSBInputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBInputBufferOutPtr() asm { GetUSBInputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBOutputBufferInPtr() asm { GetUSBOutputBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBOutputBufferOutPtr() asm { GetUSBOutputBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBPollBufferInPtr() asm { GetUSBPollBufferInPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBPollBufferOutPtr() asm { GetUSBPollBufferOutPtr(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTDeviceCount() asm { GetBTDeviceCount(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BTDeviceNameCount() asm { GetBTDeviceNameCount(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSFlags() asm { GetHSFlags(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSSpeed() asm { GetHSSpeed(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSState() asm { GetHSState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define USBState() asm { GetUSBState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) #define HSMode() asm { GetHSMode(__TMPWORD__) __RETURN__ __TMPWORD__ } #define BTDataMode() asm { GetBTDataMode(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define HSDataMode() asm { GetHSDataMode(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #endif #define SetBTDeviceName(_p, _str) asm { __setBTDeviceName(_p, _str) } #define SetBTDeviceAddress(_p, _btaddr) asm { __setBTDeviceAddress(_p, _btaddr) } #define SetBTConnectionName(_p, _str) asm { __setBTConnectionName(_p, _str) } #define SetBTConnectionPinCode(_p, _code) asm { __setBTConnectionPinCode(_p, _code) } #define SetBTConnectionAddress(_p, _btaddr) asm { __setBTConnectionAddress(_p, _btaddr) } #define SetBrickDataName(_str) SetCommModuleBytes(CommOffsetBrickDataName, 16, _str) #define SetBrickDataAddress(_btaddr) SetCommModuleBytes(CommOffsetBrickDataBdAddr, 7, _btaddr) #define SetBTDeviceClass(_p, _n) asm { __setBTDeviceClass(_p, _n) } #define SetBTDeviceStatus(_p, _n) asm { __setBTDeviceStatus(_p, _n) } #define SetBTConnectionClass(_p, _n) asm { __setBTConnectionClass(_p, _n) } #define SetBTConnectionHandleNum(_p, _n) asm { __setBTConnectionHandleNum(_p, _n) } #define SetBTConnectionStreamStatus(_p, _n) asm { __setBTConnectionStreamStatus(_p, _n) } #define SetBTConnectionLinkQuality(_p, _n) asm { __setBTConnectionLinkQuality(_p, _n) } #define SetBrickDataBluecoreVersion(_n) asm { __setBrickDataBluecoreVersion(_n) } #define SetBrickDataBtStateStatus(_n) asm { __setBrickDataBtStateStatus(_n) } #define SetBrickDataBtHardwareStatus(_n) asm { __setBrickDataBtHardwareStatus(_n) } #define SetBrickDataTimeoutValue(_n) asm { __setBrickDataTimeoutValue(_n) } #define SetBTDeviceCount(_n) asm { __setBTDeviceCount(_n) } #define SetBTDeviceNameCount(_n) asm { __setBTDeviceNameCount(_n) } #define SetBTInputBuffer(_offset, _cnt, _data) asm { __setBTInputBuffer(_offset, _cnt, _data) } #define SetBTInputBufferInPtr(_n) asm { __setBTInputBufferInPtr(_n) } #define SetBTInputBufferOutPtr(_n) asm { __setBTInputBufferOutPtr(_n) } #define SetBTOutputBuffer(_offset, _cnt, _data) asm { __setBTOutputBuffer(_offset, _cnt, _data) } #define SetBTOutputBufferInPtr(_n) asm { __setBTOutputBufferInPtr(_n) } #define SetBTOutputBufferOutPtr(_n) asm { __setBTOutputBufferOutPtr(_n) } #define SetHSInputBuffer(_offset, _cnt, _data) asm { __setHSInputBuffer(_offset, _cnt, _data) } #define SetHSInputBufferInPtr(_n) asm { __setHSInputBufferInPtr(_n) } #define SetHSInputBufferOutPtr(_n) asm { __setHSInputBufferOutPtr(_n) } #define SetHSOutputBuffer(_offset, _cnt, _data) asm { __setHSOutputBuffer(_offset, _cnt, _data) } #define SetHSOutputBufferInPtr(_n) asm { __setHSOutputBufferInPtr(_n) } #define SetHSOutputBufferOutPtr(_n) asm { __setHSOutputBufferOutPtr(_n) } #define SetUSBInputBuffer(_offset, _cnt, _data) asm { __setUSBInputBuffer(_offset, _cnt, _data) } #define SetUSBInputBufferInPtr(_n) asm { __setUSBInputBufferInPtr(_n) } #define SetUSBInputBufferOutPtr(_n) asm { __setUSBInputBufferOutPtr(_n) } #define SetUSBOutputBuffer(_offset, _cnt, _data) asm { __setUSBOutputBuffer(_offset, _cnt, _data) } #define SetUSBOutputBufferInPtr(_n) asm { __setUSBOutputBufferInPtr(_n) } #define SetUSBOutputBufferOutPtr(_n) asm { __setUSBOutputBufferOutPtr(_n) } #define SetUSBPollBuffer(_offset, _cnt, _data) asm { __setUSBPollBuffer(_offset, _cnt, _data) } #define SetUSBPollBufferInPtr(_n) asm { __setUSBPollBufferInPtr(_n) } #define SetUSBPollBufferOutPtr(_n) asm { __setUSBPollBufferOutPtr(_n) } #define SetHSFlags(_n) asm { __setHSFlags(_n) } #define SetHSSpeed(_n) asm { __setHSSpeed(_n) } #define SetHSState(_n) asm { __setHSState(_n) } #define SetUSBState(_n) asm { __setUSBState(_n) } #if (__FIRMWARE_VERSION > 107) && defined(__ENHANCED_FIRMWARE) #define SetBTDataMode(_n) asm { __setBTDataMode(_n) } #define SetHSDataMode(_n) asm { __setHSDataMode(_n) } #endif #define SysMessageWrite(_args) asm { \ compchktype _args, MessageWriteType \ syscall MessageWrite, _args \ } #define SysMessageRead(_args) asm { \ compchktype _args, MessageReadType \ syscall MessageRead, _args \ } #define SysCommBTWrite(_args) asm { \ compchktype _args, CommBTWriteType \ syscall CommBTWrite, _args \ } #define SysCommBTCheckStatus(_args) asm { \ compchktype _args, CommBTCheckStatusType \ syscall CommBTCheckStatus, _args \ } #ifdef __ENHANCED_FIRMWARE #define SysCommExecuteFunction(_args) asm { \ compchktype _args, CommExecuteFunctionType \ syscall CommExecuteFunction, _args \ } #define SysCommHSControl(_args) asm { \ compchktype _args, CommHSControlType \ syscall CommHSControl, _args \ } #define SysCommHSCheckStatus(_args) asm { \ compchktype _args, CommHSCheckStatusType \ syscall CommHSCheckStatus, _args \ } #define SysCommHSRead(_args) asm { \ compchktype _args, CommHSReadWriteType \ syscall CommHSRead, _args \ } #define SysCommHSWrite(_args) asm { \ compchktype _args, CommHSReadWriteType \ syscall CommHSWrite, _args \ } #endif #if __FIRMWARE_VERSION > 107 #define SysCommBTOnOff(_args) asm { \ compchktype _args, CommBTOnOffType \ syscall CommBTOnOff, _args \ } #define SysCommBTConnection(_args) asm { \ compchktype _args, CommBTConnectionType \ syscall CommBTConnection, _args \ } #endif #endif /** @} */ // end of CommModuleFunctions group /** @} */ // end of CommModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// BUTTON MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup ButtonModule * @{ */ /** @defgroup ButtonModuleTypes Button module types * Types used by various Button module functions. * @{ */ /** * Parameters for the ReadButton system call. * This structure is used when calling the \ref SysReadButton system call * function. * \sa SysReadButton() */ struct ReadButtonType { char Result; /*!< The function call result, \ref ERR_INVALID_PORT or \ref NO_ERR. */ byte Index; /*!< The requested button index. See the \ref ButtonNameConstants group. */ bool Pressed; /*!< The returned button state. */ byte Count; /*!< The returned button pressed count. */ bool Reset; /*!< If true, the count is reset after reading. */ }; /** @} */ // end of ButtonModuleTypes group /** @defgroup ButtonModuleFunctions Button module functions * Functions for accessing and modifying Button module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Check for button press. * This function checks whether the specified button is pressed or not. You may * optionally reset the press count. * * \param btn The button to check. See \ref ButtonNameConstants. * \param resetCount Whether or not to reset the press counter. * \return A boolean value indicating whether the button is pressed or not. */ inline bool ButtonPressed(const byte btn, bool resetCount); /** * Get button press count. * Return the number of times the specified button has been pressed since * the last time the button press count was reset. Optionally clear the count * after reading it. * * \param btn The button to check. See \ref ButtonNameConstants. * \param resetCount Whether or not to reset the press counter. * \return The button press count. */ inline byte ButtonCount(const byte btn, bool resetCount); /** * Read button information. * Read the specified button. Set the pressed and count parameters with the * current state of the button. Optionally reset the press count after * reading it. * * \param btn The button to check. See \ref ButtonNameConstants. * \param reset Whether or not to reset the press counter. * \param pressed The button pressed state. * \param count The button press count. * \return The function call result. */ inline char ReadButtonEx(const byte btn, bool reset, bool & pressed, unsigned int & count); /** * Get button press count. * Return the press count of the specified button. * \param btn The button to check. See \ref ButtonNameConstants. * \return The button press count. */ inline byte ButtonPressCount(const byte btn); /** * Get button long press count. * Return the long press count of the specified button. * * \param btn The button to check. See \ref ButtonNameConstants. * \return The button long press count. */ inline byte ButtonLongPressCount(const byte btn); /** * Get button short release count. * Return the short release count of the specified button. * * \param btn The button to check. See \ref ButtonNameConstants. * \return The button short release count. */ inline byte ButtonShortReleaseCount(const byte btn); /** * Get button long release count. * Return the long release count of the specified button. * * \param btn The button to check. See \ref ButtonNameConstants. * \return The button long release count. */ inline byte ButtonLongReleaseCount(const byte btn); /** * Get button release count. * Return the release count of the specified button. * * \param btn The button to check. See \ref ButtonNameConstants. * \return The button release count. */ inline byte ButtonReleaseCount(const byte btn); /** * Get button state. * Return the state of the specified button. See \ref ButtonStateConstants. * * \param btn The button to check. See \ref ButtonNameConstants. * \return The button state. */ inline byte ButtonState(const byte btn); /** * Set button long press count. * Set the long press count of the specified button. * * \param btn The button number. See \ref ButtonNameConstants. * \param n The new long press count value. */ inline void SetButtonLongPressCount(const byte btn, const byte n); /** * Set button long release count. * Set the long release count of the specified button. * * \param btn The button number. See \ref ButtonNameConstants. * \param n The new long release count value. */ inline void SetButtonLongReleaseCount(const byte btn, const byte n); /** * Set button press count. * Set the press count of the specified button. * * \param btn The button number. See \ref ButtonNameConstants. * \param n The new press count value. */ inline void SetButtonPressCount(const byte btn, const byte n); /** * Set button release count. * Set the release count of the specified button. * * \param btn The button number. See \ref ButtonNameConstants. * \param n The new release count value. */ inline void SetButtonReleaseCount(const byte btn, const byte n); /** * Set button short release count. * Set the short release count of the specified button. * * \param btn The button number. See \ref ButtonNameConstants. * \param n The new short release count value. */ inline void SetButtonShortReleaseCount(const byte btn, const byte n); /** * Set button state. * Set the state of the specified button. * * \param btn The button to check. See \ref ButtonNameConstants. * \param state The new button state. See \ref ButtonStateConstants. */ inline void SetButtonState(const byte btn, const byte state); /** * Read button. * This function lets you read button state information via the \ref * ReadButtonType structure. * * \param args The ReadButtonType structure containing the needed parameters. */ inline void SysReadButton(ReadButtonType & args); #else #define ButtonPressCount(_b) asm { GetButtonPressCount(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ButtonLongPressCount(_b) asm { GetButtonLongPressCount(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ButtonShortReleaseCount(_b) asm { GetButtonShortReleaseCount(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ButtonLongReleaseCount(_b) asm { GetButtonLongReleaseCount(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ButtonReleaseCount(_b) asm { GetButtonReleaseCount(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define ButtonState(_b) asm { GetButtonState(_b, __TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SetButtonPressCount(_b, _n) asm { __setButtonPressCount(_b, _n) } #define SetButtonLongPressCount(_b, _n) asm { __setButtonLongPressCount(_b, _n) } #define SetButtonShortReleaseCount(_b, _n) asm { __setButtonShortReleaseCount(_b, _n) } #define SetButtonLongReleaseCount(_b, _n) asm { __setButtonLongReleaseCount(_b, _n) } #define SetButtonReleaseCount(_b, _n) asm { __setButtonReleaseCount(_b, _n) } #define SetButtonState(_b, _n) asm { __setButtonState(_b, _n) } #define SysReadButton(_args) asm { \ compchktype _args, ReadButtonType \ syscall ReadButton, _args \ } #endif /** @} */ // end of ButtonModuleFunctions group /** @} */ // end of ButtonModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// UI MODULE ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup UiModule * @{ */ /** @defgroup UiModuleTypes Ui module types * Types used by various Ui module functions. * @{ */ #if __FIRMWARE_VERSION > 107 /** * Parameters for the SetSleepTimeout system call. * This structure is used when calling the \ref SysSetSleepTimeout system call * function. * \sa SysSetSleepTimeout() */ struct SetSleepTimeoutType { char Result; /*!< The result of the system call function. */ unsigned long TheSleepTimeoutMS; /*!< The new sleep timeout value in milliseconds. */ }; #endif /** @} */ // end of UiModuleTypes group /** @defgroup UiModuleFunctions Ui module functions * Functions for accessing and modifying Ui module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Get command flags. * Return the command flags. * \return Command flags. See \ref UiFlagsConstants */ inline byte CommandFlags(void); /** * Get UI module state. * Return the user interface state. * \return The UI module state. See \ref UiStateConstants. */ inline byte UIState(void); /** * Read UI button. * Return user interface button information. * \return A UI button value. See \ref UiButtonConstants. */ inline byte UIButton(void); /** * Read VM run state. * Return VM run state information. * \return VM run state. See \ref UiVMRunStateConstants. */ inline byte VMRunState(void); /** * Get battery state. * Return battery state information (0..4). * \return The battery state (0..4) */ inline byte BatteryState(void); /** * Get bluetooth state. * Return the bluetooth state. * \return The bluetooth state. See \ref UiBluetoothStateConstants. */ inline byte BluetoothState(void); /** * Get UI module USB state. * This method returns the UI module USB state. * \return The UI module USB state. (0=disconnected, 1=connected, 2=working) */ inline byte UsbState(void); /** * Read sleep timeout. * Return the number of minutes that the NXT will remain on before * it automatically shuts down. * \return The sleep timeout value */ inline byte SleepTimeout(void); /** * Read sleep time. * Return the number of minutes that the NXT will remain on before * it automatically shuts down. * \return The sleep time value * \sa SleepTimeout */ inline byte SleepTime(void); /** * Read sleep timer. * Return the number of minutes left in the countdown to zero from the * original SleepTimeout value. When the SleepTimer value reaches zero the * NXT will shutdown. * \return The sleep timer value */ inline byte SleepTimer(void); /** * Read battery type. * Return whether the NXT has a rechargeable battery installed or not. * \return Whether the battery is rechargeable or not. (false = no, true = yes) */ inline bool RechargeableBattery(void); /** * Read volume. * Return the user interface volume level. Valid values are from 0 to 4. * \return The UI module volume. (0..4) */ inline byte Volume(void); /** * Read the on brick program pointer value. * Return the current OBP (on-brick program) step * * \return On brick program pointer (step). */ inline byte OnBrickProgramPointer(void); /** * Read abort flag. * Return the enhanced NBC/NXC firmware's abort flag. * * \return The current abort flag value. See \ref ButtonStateConstants. * \warning This function requires the enhanced NBC/NXC firmware. */ inline byte AbortFlag(void); /** * Read long abort setting. * Return the enhanced NBC/NXC firmware's long abort setting. * * \sa AbortFlag * \return The current abort flag value. See \ref ButtonStateConstants. * \warning This function requires the enhanced NBC/NXC firmware. */ inline byte LongAbort(void); /** * Get battery Level. * Return the battery level in millivolts. * \return The battery level */ inline unsigned int BatteryLevel(void); /** * Set command flags. * Set the command flags. * * \param cmdFlags The new command flags. See \ref UiFlagsConstants. */ inline void SetCommandFlags(const byte cmdFlags); /** * Set UI button. * Set user interface button information. * * \param btn A user interface button value. See \ref UiButtonConstants. */ inline void SetUIButton(byte btn); /** * Set UI state. * Set the user interface state. * * \param state A user interface state value. See \ref UiStateConstants. */ inline void SetUIState(byte state); /** * Set VM run state. * Set VM run state information. * * \param vmRunState The desired VM run state. See \ref UiVMRunStateConstants. * * \warning It is not a good idea to change the VM run state from within a * running program unless you know what you are doing. */ inline void SetVMRunState(const byte vmRunState); /** * Set battery state. * Set battery state information. * * \param state The desired battery state (0..4). */ inline void SetBatteryState(byte state); /** * Set bluetooth state. * Set the Bluetooth state. * * \param state The desired bluetooth state. See \ref UiBluetoothStateConstants. */ inline void SetBluetoothState(byte state); /** * Set sleep timeout. * Set the NXT sleep timeout value to the specified number of minutes. * * \param n The minutes to wait before sleeping. */ inline void SetSleepTimeout(const byte n); /** * Set sleep time. * Set the NXT sleep timeout value to the specified number of minutes. * * \param n The minutes to wait before sleeping. * \sa SetSleepTimeout, SleepTimeout */ inline void SetSleepTime(const byte n); /** * Set the sleep timer. * Set the system sleep timer to the specified number of minutes. * * \param n The minutes left on the timer. */ inline void SetSleepTimer(const byte n); /** * Set volume. * Set the user interface volume level. Valid values are from 0 to 4. * * \param volume The new volume level. */ inline void SetVolume(byte volume); /** * Set on-brick program pointer. * Set the current OBP (on-brick program) step. * * \param obpStep The new on-brick program step. */ inline void SetOnBrickProgramPointer(byte obpStep); /** * Turn off NXT. * Force the NXT to turn off if the specified value is greater than zero. * \param num If greater than zero the NXT will turn off. */ inline void ForceOff(byte num); /** * Set abort flag. * Set the enhanced NBC/NXC firmware's program abort flag. By default the * running program can be interrupted by a short press of the escape button. * You can change this to any other button state flag. * * \param abortFlag The new abort flag value. See \ref ButtonStateConstants * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SetAbortFlag(byte abortFlag); /** * Set long abort. * Set the enhanced NBC/NXC firmware's long abort setting (true or false). If * set to true then a program has access the escape button. Aborting a program * requires a long press of the escape button. * * \param longAbort If true then require a long press of the escape button * to abort a program, otherwise a short press will abort it. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void SetLongAbort(bool longAbort); #if __FIRMWARE_VERSION > 107 /** * Set system sleep timeout. * This function lets you set the system sleep timeout value given the parameters you * pass in via the \ref SetSleepTimeoutType structure. * * \param args The SetSleepTimeoutType structure containing the required parameters. * * \warning This function requires an NXT 2.0 compatible firmware. */ inline void SysSetSleepTimeout(SetSleepTimeoutType & args); #endif #else #define CommandFlags() asm { GetCommandFlags(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define UIState() asm { GetUIState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define UIButton() asm { GetUIButton(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define VMRunState() asm { GetVMRunState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BatteryState() asm { GetBatteryState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define BluetoothState() asm { GetBluetoothState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define UsbState() asm { GetUsbState(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SleepTimeout() asm { GetSleepTimeout(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define SleepTime() SleepTimeout() #define SleepTimer() asm { GetSleepTimer(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define RechargeableBattery() asm { GetRechargeableBattery(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define Volume() asm { GetVolume(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define OnBrickProgramPointer() asm { GetOnBrickProgramPointer(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define AbortFlag() asm { GetAbortFlag(__TMPBYTE__) __RETURN__ __TMPBYTE__ } #define LongAbort() AbortFlag() #define BatteryLevel() asm { GetBatteryLevel(__TMPWORD__) __RETURN__ __TMPWORD__ } #define SetCommandFlags(_n) asm { __setCommandFlags(_n) } #define SetUIState(_n) asm { __setUIState(_n) } #define SetUIButton(_n) asm { __setUIButton(_n) } #define SetVMRunState(_n) asm { __setVMRunState(_n) } #define SetBatteryState(_n) asm { __setBatteryState(_n) } #define SetBluetoothState(_n) asm { __setBluetoothState(_n) } #define SetUsbState(_n) asm { __setUsbState(_n) } #define SetSleepTimeout(_n) asm { __setSleepTimeout(_n) } #define SetSleepTime(_n) SetSleepTimeout(_n) #define SetSleepTimer(_n) asm { __setSleepTimer(_n) } #define SetVolume(_n) asm { __setVolume(_n) } #define SetOnBrickProgramPointer(_n) asm { __setOnBrickProgramPointer(_n) } #define ForceOff(_n) asm { __forceOff(_n) } #define SetAbortFlag(_n) asm { __setAbortFlag(_n) } #define SetLongAbort(_n) do { \ if (_n) { \ asm { __setAbortFlag(BTNSTATE_LONG_PRESSED_EV) } \ } else { \ asm { __setAbortFlag(BTNSTATE_PRESSED_EV) } \ } \ } while(false) #if __FIRMWARE_VERSION > 107 #define SysSetSleepTimeout(_args) asm { \ compchktype _args, SetSleepTimeoutType \ syscall SetSleepTimeoutVal, _args \ } #endif #endif /** @} */ // end of UiModuleFunctions group /** @} */ // end of UiModule group /** @} */ // end of NXTFirmwareModules group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// LOADER MODULE //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup LoaderModule * @{ */ /** @defgroup LoaderModuleTypes Loader module types * Types used by various Loader module functions. * @{ */ /** * Parameters for the FileOpen system call. * This structure is used when calling the \ref SysFileOpenAppend, \ref * SysFileOpenRead, \ref SysFileOpenWrite, \ref SysFileOpenReadLinear, * \ref SysFileOpenWriteLinear and \ref SysFileOpenWriteNonLinear system call * functions. * \sa SysFileOpenAppend(), SysFileOpenRead(), SysFileOpenWrite(), * SysFileOpenReadLinear(), SysFileOpenWriteLinear() */ struct FileOpenType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The returned file handle to use for subsequent file operations. */ string Filename; /*!< The name of the file to open or create. */ unsigned long Length; /*!< For SysFileOpenWrite(), SysFileOpenWriteLinear() and SysFileOpenWriteNonLinear(): the desired maximum file capacity. For SysFileOpenAppend(), SysFileOpenRead() and SysFileOpenReadLinear(): the returned available length in the file. */ }; /** * Parameters for the FileReadWrite system call. * This structure is used when calling the \ref SysFileRead and \ref SysFileWrite * system call functions. * \sa SysFileRead() and SysFileWrite() */ struct FileReadWriteType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The file handle to access. */ string Buffer; /*!< The buffer to store read bytes or containing bytes to write. */ unsigned long Length; /*!< The number of bytes to read or the returned number of bytes written. */ }; /** * Parameters for the FileClose system call. * This structure is used when calling the \ref SysFileClose system call function. * \sa SysFileClose() */ struct FileCloseType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The file handle to close. */ }; /** * Parameters for the FileResolveHandle system call. * This structure is used when calling the \ref SysFileResolveHandle system * call function. * \sa SysFileResolveHandle() */ struct FileResolveHandleType { unsigned int Result; /*!< The function call result. Possible values include \ref LDR_HANDLEALREADYCLOSED and \ref LDR_SUCCESS. */ byte FileHandle; /*!< The returned resolved file handle. */ bool WriteHandle; /*!< True if the returned handle is a write handle. */ string Filename; /*!< The name of the file for which to resolve a handle. */ }; /** * Parameters for the FileRename system call. * This structure is used when calling the \ref SysFileRename system call * function. * \sa SysFileRename() */ struct FileRenameType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ string OldFilename; /*!< The name of the file to be renamed. */ string NewFilename; /*!< The new name to give to the file. */ }; /** * Parameters for the FileDelete system call. * This structure is used when calling the \ref SysFileDelete system call * function. * \sa SysFileDelete() */ struct FileDeleteType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ string Filename; /*!< The name of the file to delete. */ }; #ifdef __ENHANCED_FIRMWARE /** * Parameters for the LoaderExecuteFunction system call. * This structure is used when calling the \ref SysLoaderExecuteFunction * system call function. * * The fields usage depends on the requested command and are documented in the * table below. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
CmdMeaningExpected Parameters
LDR_CMD_OPENREADOpen a file for reading(Filename, Length)
LDR_CMD_OPENWRITECreate a file(Filename, Length)
LDR_CMD_READRead from a file(Filename, Buffer, Length)
LDR_CMD_WRITEWrite to a file(Filename, Buffer, Length)
LDR_CMD_CLOSEClose a file(Filename)
LDR_CMD_DELETEDelete a file(Filename)
LDR_CMD_FINDFIRSTStart iterating files(Filename, Buffer, Length)
LDR_CMD_FINDNEXTContinue iterating files(Filename, Buffer, Length)
LDR_CMD_OPENWRITELINEARCreate a linear file(Filename, Length)
LDR_CMD_OPENREADLINEARRead a linear file(Filename, Buffer, Length)
LDR_CMD_OPENAPPENDDATAOpen a file for writing(Filename, Length)
LDR_CMD_FINDFIRSTMODULEStart iterating modules(Filename, Buffer)
LDR_CMD_FINDNEXTMODULEContinue iterating modules(Buffer)
LDR_CMD_CLOSEMODHANDLEClose module handle()
LDR_CMD_IOMAPREADRead IOMap data(Filename, Buffer, Length)
LDR_CMD_IOMAPWRITEWrite IOMap data(Filename, Buffer, Length)
LDR_CMD_DELETEUSERFLASHDelete all files()
LDR_CMD_RENAMEFILERename file(Filename, Buffer, Length)
* * \sa SysLoaderExecuteFunction() */ struct LoaderExecuteFunctionType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte Cmd; /*!< The command to execute. */ string Filename; /*!< The Filename parameter, see table. */ byte Buffer[]; /*!< The Buffer parameter, see table. */ unsigned long Length; /*!< The Length parameter, see table. */ }; /** * Parameters for the FileFind system call. * This structure is used when calling the \ref SysFileFindFirst and \ref * SysFileFindNext system call functions. * \sa SysFileFindFirst() and SysFileFindNext() */ struct FileFindType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The returned file handle to be used to continue iterations. Close it after usage. */ string Filename; /*!< The pattern to match file name, then the returned found file name. */ unsigned long Length; /*!< The found file length. */ }; #if __FIRMWARE_VERSION > 107 /** * Parameters for the FileSeek system call. * This structure is used when calling the \ref SysFileSeek system call function. * \sa SysFileSeek() */ struct FileSeekType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The handle of the file to seek in. */ byte Origin; /*!< The origin of the file seek operation. See \ref fseekConstants. */ long Length; /*!< The offset from the origin to seek to. */ }; /** * Parameters for the FileResize system call. * This structure is used when calling the \ref SysFileResize system call function. * \sa SysFileResize() */ struct FileResizeType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The handle of the file to resize. */ unsigned int NewSize; /*!< The new file size. */ }; /** * Parameters for the FileTell system call. * This structure is used when calling the \ref SysFileTell system call function. * \sa SysFileTell() */ struct FileTellType { unsigned int Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ byte FileHandle; /*!< The handle of the open file. */ unsigned long Position; /*!< The current file position in the open file. */ }; #endif #endif #if __FIRMWARE_VERSION > 107 /** * Parameters for the ListFiles system call. * This structure is used when calling the \ref SysListFiles system call function. * \sa SysListFiles() */ struct ListFilesType { char Result; /*!< The function call result. Possible values include \ref LoaderErrors. */ string Pattern; /*!< The file search pattern. */ string FileList[]; /*!< An array of strings containing the list of filenames that matched the file search pattern. */ }; #endif /** @} */ // end of LoaderModuleTypes group /** @defgroup LoaderModuleFunctions Loader module functions * Functions for accessing and modifying Loader module features. * @{ */ #ifdef __DOXYGEN_DOCS /** * Get free flash memory. * Get the number of bytes of flash memory that are available for use. * \return The number of bytes of unused flash memory. */ inline unsigned int FreeMemory(void); /** * Create a file. * Create a new file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param fname The name of the file to create. * \param fsize The size of the file. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int CreateFile(string fname, unsigned int fsize, byte & handle); /** * Open a file for appending. * Open an existing file with the specified filename for writing. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. * The filename parameter must be a constant or a variable. * * \param fname The name of the file to open. * \param fsize The size of the file returned by the function. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int OpenFileAppend(string fname, unsigned int & fsize, byte & handle); /** * Open a file for reading. * Open an existing file with the specified filename for reading. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param fname The name of the file to open. * \param fsize The size of the file returned by the function. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int OpenFileRead(string fname, unsigned int & fsize, byte & handle); /** * Close a file. * Close the file associated with the specified file handle. The loader * result code is returned as the value of the function call. The handle * parameter must be a constant or a variable. * * \param handle The file handle. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int CloseFile(byte handle); /** * Resolve a handle. * Resolve a file handle from the specified filename. The file handle is * returned in the second parameter, which must be a variable. A boolean * value indicating whether the handle can be used to write to the file or * not is returned in the last parameter, which must be a variable. The * loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param filename The name of the file for which to resolve a handle. * \param handle The file handle output from the function call. * \param writeable A boolean flag indicating whether the handle is * to a file open for writing (true) or reading (false). * \return The function call result. See \ref LoaderErrors. */ inline unsigned int ResolveHandle(string filename, byte & handle, bool & writeable); /** * Rename a file. * Rename a file from the old filename to the new filename. The loader * result code is returned as the value of the function call. The filename * parameters must be constants or variables. * * \param oldname The old filename. * \param newname The new filename. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int RenameFile(string oldname, string newname); /** * Delete a file. * Delete the specified file. The loader result code is returned as the * value of the function call. The filename parameter must be a constant or a * variable. * * \param fname The name of the file to delete. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int DeleteFile(string fname); /** * Resize a file. * Resize the specified file. The loader result code is returned as the * value of the function call. The filename parameter must be a constant or a * variable. * * \param fname The name of the file to resize. * \param newsize The new size for the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int ResizeFile(string fname, const unsigned int newsize); #ifdef __ENHANCED_FIRMWARE /** * Create a linear file. * Create a new linear file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param fname The name of the file to create. * \param fsize The size of the file. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ inline unsigned int CreateFileLinear(string fname, unsigned int fsize, byte & handle); /** * Create a non-linear file. * Create a new non-linear file with the specified filename and size and open it for * writing. The file handle is returned in the last parameter, which must be a * variable. The loader result code is returned as the value of the function * call. The filename and size parameters must be constants, constant * expressions, or variables. A file created with a size of zero bytes cannot * be written to since the NXC file writing functions do not grow the file if * its capacity is exceeded during a write attempt. * * \param fname The name of the file to create. * \param fsize The size of the file. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ inline unsigned int CreateFileNonLinear(string fname, unsigned int fsize, byte & handle); /** * Open a linear file for reading. * Open an existing linear file with the specified filename for reading. The file * size is returned in the second parameter, which must be a variable. The * file handle is returned in the last parameter, which must be a variable. * The loader result code is returned as the value of the function call. The * filename parameter must be a constant or a variable. * * \param fname The name of the file to open. * \param fsize The size of the file returned by the function. * \param handle The file handle output from the function call. * \return The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ inline unsigned int OpenFileReadLinear(string fname, unsigned int & fsize, byte & handle); /** * Start searching for files. * This function lets you begin iterating through files stored on the NXT. * * \param fname On input this contains the filename pattern you are searching * for. On output this contains the name of the first file found that matches * the pattern. * \param handle The search handle input to and output from the function call. * \return The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ inline unsigned int FindFirstFile(string & fname, byte & handle); /** * Continue searching for files. * This function lets you continue iterating through files stored on the NXT. * * \param fname On output this contains the name of the next file found that * matches the pattern used when the search began by calling \ref FindFirstFile. * \param handle The search handle input to and output from the function call. * \return The function call result. See \ref LoaderErrors. * \warning This function requires the enhanced NBC/NXC firmware. */ inline unsigned int FindNextFile(string & fname, byte & handle); #endif /** * Calculate the size of a variable. * Calculate the number of bytes required to store the contents of the * variable passed into the function. * * \param value The variable. * \return The number of bytes occupied by the variable. */ inline unsigned int SizeOf(variant & value); /** * Read a value from a file. * Read a value from the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * variable. The type of the value parameter determines the number of bytes of * data read. * * \param handle The file handle. * \param value The variable to store the data read from the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int Read(byte handle, variant & value); /** * Read a value from a file plus line ending. * Read a value from the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * variable. The type of the value parameter determines the number of bytes * of data read. The ReadLn function reads two additional bytes from the * file which it assumes are a carriage return and line feed pair. * * \param handle The file handle. * \param value The variable to store the data read from the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int ReadLn(byte handle, variant & value); /** * Read bytes from a file. * Read the specified number of bytes from the file associated with the * specified handle. The handle parameter must be a variable. The length * parameter must be a variable. The buf parameter must be an array or a * string variable. The actual number of bytes read is returned in the * length parameter. * * \param handle The file handle. * \param length The number of bytes to read. Returns the number of bytes actually read. * \param buf The byte array where the data is stored on output. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int ReadBytes(byte handle, unsigned int & length, byte & buf[]); /** * Read a string from a file plus line ending. * Read a string from the file associated with the specified handle. * The handle parameter must be a variable. The output parameter must be a * variable. Appends bytes to the output variable until a line ending (CRLF) * is reached. The line ending is also read but it is not appended to the * output parameter. * * \param handle The file handle. * \param output The variable to store the string read from the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int ReadLnString(byte handle, string & output); /** * Write value to file. * Write a value to the file associated with the specified handle. * The handle parameter must be a variable. The value parameter must be a * constant, a constant expression, or a variable. The type of the value * parameter determines the number of bytes of data written. * * \param handle The file handle. * \param value The value to write to the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int Write(byte handle, const variant & value); /** * Write bytes to file. * Write the contents of the data array to the file associated with the * specified handle. The handle parameter must be a variable. The cnt * parameter must be a variable. The data parameter must be a byte array. The * actual number of bytes written is returned in the cnt parameter. * * \param handle The file handle. * \param buf The byte array or string containing the data to write. * \param cnt The number of bytes actually written to the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int WriteBytes(byte handle, const byte & buf[], unsigned int & cnt); /** * Write bytes to a file with limit. * Write the specified number of bytes to the file associated with the * specified handle. The handle parameter must be a variable. The len * parameter must be a variable. The buf parameter must be a byte array or a * string variable or string constant. The actual number of bytes written is * returned in the len parameter. * * \param handle The file handle. * \param len The maximum number of bytes to write on input. Returns the * actual number of bytes written. * \param buf The byte array or string containing the data to write. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int WriteBytesEx(byte handle, unsigned int & len, const byte & buf[]); /** * Write a value and new line to a file. * Write a value to the file associated with the specified handle. The * handle parameter must be a variable. The value parameter must be a constant, * a constant expression, or a variable. The type of the value parameter * determines the number of bytes of data written. This function also * writes a carriage return and a line feed to the file following the numeric * data. * * \param handle The file handle. * \param value The value to write to the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int WriteLn(byte handle, const variant & value); /** * Write string and new line to a file. * Write the string to the file associated with the specified handle. The * handle parameter must be a variable. The count parameter must be a variable. * The str parameter must be a string variable or string constant. This * function also writes a carriage return and a line feed to the file following * the string data. The total number of bytes written is returned in the * cnt parameter. * * \param handle The file handle. * \param str The string to write to the file. * \param cnt The number of bytes actually written to the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int WriteLnString(byte handle, const string & str, unsigned int & cnt); /** * Write string to a file. * Write the string to the file associated with the specified handle. The * handle parameter must be a variable. The count parameter must be a variable. * The str parameter must be a string variable or string constant. The actual * number of bytes written is returned in the cnt parameter. * * \param handle The file handle. * \param str The string to write to the file. * \param cnt The number of bytes actually written to the file. * \return The function call result. See \ref LoaderErrors. */ inline unsigned int WriteString(byte handle, const string & str, unsigned int & cnt); /** * Open file for reading. * This function lets you open an existing file for reading using the values * specified via the \ref FileOpenType structure. * * The number of bytes that can be read from the file is returned via the * Length member. * * \param args The FileOpenType structure containing the needed parameters. */ inline void SysFileOpenRead(FileOpenType & args); /** * Open and create file for writing. * This function lets you create a file that you can write to using the values * specified via the \ref FileOpenType structure. * * The desired maximum file capacity in bytes is specified via the Length * member. * * \param args The FileOpenType structure containing the needed parameters. */ inline void SysFileOpenWrite(FileOpenType & args); /** * Open file for writing at end of file. * This function lets you open an existing file that you can write to using * the values specified via the \ref FileOpenType structure. * * The available length remaining in the file is returned via the Length * member. * * \param args The FileOpenType structure containing the needed parameters. */ inline void SysFileOpenAppend(FileOpenType & args); /** * Read from file. * This function lets you read from a file using the values specified via the * \ref FileReadWriteType structure. * * \param args The FileReadWriteType structure containing the needed * parameters. */ inline void SysFileRead(FileReadWriteType & args); /** * File write. * This function lets you write to a file using the values specified via the * \ref FileReadWriteType structure. * * \param args The FileReadWriteType structure containing the needed * parameters. */ inline void SysFileWrite(FileReadWriteType & args); /** * Close file handle. * This function lets you close a file using the values specified via the \ref * FileCloseType structure. * * \param args The FileCloseType structure containing the needed parameters. */ inline void SysFileClose(FileCloseType & args); /** * File resolve handle. * This function lets you resolve the handle of a file using the values * specified via the \ref FileResolveHandleType structure. This will find a * previously opened file handle. * * \param args The FileResolveHandleType structure containing the needed * parameters. */ inline void SysFileResolveHandle(FileResolveHandleType & args); /** * Rename file. * This function lets you rename a file using the values specified via the * \ref FileRenameType structure. * * \param args The FileRenameType structure containing the needed parameters. */ inline void SysFileRename(FileRenameType & args); /** * Delete file. * This function lets you delete a file using the values specified via the * \ref FileDeleteType structure. * * \param args The FileDeleteType structure containing the needed parameters. */ inline void SysFileDelete(FileDeleteType & args); #ifdef __ENHANCED_FIRMWARE /** * Execute any Loader module command. * This function lets you directly execute the Loader module's primary * function using the values specified via the \ref LoaderExecuteFunctionType * structure. * * \param args The LoaderExecuteFunctionType structure containing the needed * parameters. * * \warning This function requires the extended firmware. */ inline void SysLoaderExecuteFunction(LoaderExecuteFunctionType & args); /** * Start finding files. * This function lets you begin iterating through files stored on the NXT. * * \param args The FileFindType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileFindFirst(FileFindType & args); /** * Continue finding files. * This function lets you continue iterating through files stored on the NXT. * * \param args The FileFindType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileFindNext(FileFindType & args); /** * Open and create linear file for writing. * This function lets you create a linear file that you can write to using the * values specified via the \ref FileOpenType structure. * * \param args The FileOpenType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileOpenWriteLinear(FileOpenType & args); /** * Open and create non-linear file for writing. * This function lets you create a non-linear linear file that you can write * to using the values specified via the \ref FileOpenType structure. * * \param args The FileOpenType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileOpenWriteNonLinear(FileOpenType & args); /** * Open linear file for reading. * This function lets you open an existing linear file for reading using the * values specified via the \ref FileOpenType structure. * * \param args The FileOpenType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileOpenReadLinear(FileOpenType & args); #if __FIRMWARE_VERSION > 107 /** * Seek to file position. * This function lets you seek to a specific file position using the * values specified via the \ref FileSeekType structure. * * \param args The FileSeekType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileSeek(FileSeekType & args); /** * Resize a file. * This function lets you resize a file using the * values specified via the \ref FileResizeType structure. * * \param args The FileResizeType structure containing the needed parameters. * * \warning This function requires the extended firmware. * It has not yet been implemented at the firmware level. */ inline void SysFileResize(FileResizeType & args); /** * Return the file position. * This function returns the current file position in the open file * specified via the \ref FileTellType structure. * * \param args The FileTellType structure containing the needed parameters. * * \warning This function requires the extended firmware. */ inline void SysFileTell(FileTellType & args); #endif #endif #if __FIRMWARE_VERSION > 107 /** * List files. * This function lets you retrieve a list of files on the NXT using the * values specified via the \ref ListFilesType structure. * * \param args The ListFilesType structure containing the needed parameters. */ inline void SysListFiles(ListFilesType & args); #endif #else #define FreeMemory() asm { GetFreeMemory(__RETVAL__) } #define CreateFile(_fname, _fsize, _handle) asm { __createFile(_fname, _fsize, _handle, __RETVAL__) } #define OpenFileAppend(_fname, _fsize, _handle) asm { __openFileAppend(_fname, _fsize, _handle, __RETVAL__) } #define OpenFileRead(_fname, _fsize, _handle) asm { __openFileRead(_fname, _fsize, _handle, __RETVAL__) } #define CloseFile(_handle) asm { __closeFile(_handle, __RETVAL__) } #define ResolveHandle(_fname, _handle, _writeable) asm { __resolveHandle(_fname, _handle, _writeable, __RETVAL__) } #define RenameFile(_oldname, _newname) asm { __renameFile(_oldname, _newname, __RETVAL__) } #define DeleteFile(_fname) asm { __deleteFile(_fname, __RETVAL__) } #define ResizeFile(_fname, _newsize) asm { __fileResize(_fname, _newsize, __RETVAL__) } #ifdef __ENHANCED_FIRMWARE #define CreateFileLinear(_fname, _fsize, _handle) asm { __createFileLinear(_fname, _fsize, _handle, __RETVAL__) } #define CreateFileNonLinear(_fname, _fsize, _handle) asm { __createFileNonLinear(_fname, _fsize, _handle, __RETVAL__) } #define OpenFileReadLinear(_fname, _fsize, _handle) asm { __openFileReadLinear(_fname, _fsize, _handle, __RETVAL__) } #define FindFirstFile(_fname, _handle) asm { __findFirstFile(_fname, _handle, __RETVAL__) } #define FindNextFile(_fname, _handle) asm { __findNextFile(_fname, _handle, __RETVAL__) } #endif #define SizeOf(_n) asm { __sizeOF(_n, __RETVAL__) } #define Read(_handle, _n) asm { __readValue(_handle, _n, __RETVAL__) } #define ReadLn(_handle, _n) asm { __readLnValue(_handle, _n, __RETVAL__) } #define ReadBytes(_handle, _len, _buf) asm { __readBytes(_handle, _len, _buf, __RETVAL__) } #define ReadLnString(_handle, _output) asm { __readLnString(_handle, _output, __RETVAL__) } #define Write(_handle, _n) asm { __writeValue(_handle, _n, __RETVAL__) } #define WriteLn(_handle, _n) asm { __writeLnValue(_handle, _n, __RETVAL__) } #define WriteString(_handle, _str, _cnt) asm { __writeString(_handle, _str, _cnt, __RETVAL__) } #define WriteLnString(_handle, _str, _cnt) asm { __writeLnString(_handle, _str, _cnt, __RETVAL__) } #define WriteBytes(_handle, _buf, _cnt) asm { __writeBytes(_handle, _buf, _cnt, __RETVAL__) } #define WriteBytesEx(_handle, _len, _buf) asm { __writeBytesEx(_handle, _len, _buf, __RETVAL__) } #define SysFileOpenRead(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenRead, _args \ } #define SysFileOpenWrite(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenWrite, _args \ } #define SysFileOpenAppend(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenAppend, _args \ } #define SysFileRead(_args) asm { \ compchktype _args, FileReadWriteType \ syscall FileRead, _args \ } #define SysFileWrite(_args) asm { \ compchktype _args, FileReadWriteType \ syscall FileWrite, _args \ } #define SysFileClose(_args) asm { \ compchktype _args, FileCloseType \ syscall FileClose, _args \ } #define SysFileResolveHandle(_args) asm { \ compchktype _args, FileResolveHandleType \ syscall FileResolveHandle, _args \ } #define SysFileRename(_args) asm { \ compchktype _args, FileRenameType \ syscall FileRename, _args \ } #define SysFileDelete(_args) asm { \ compchktype _args, FileDeleteType \ syscall FileDelete, _args \ } #ifdef __ENHANCED_FIRMWARE #define SysLoaderExecuteFunction(_args) asm { \ compchktype _args, LoaderExecuteFunctionType \ syscall LoaderExecuteFunction, _args \ } #define SysFileFindFirst(_args) asm { \ compchktype _args, FileFindType \ syscall FileFindFirst, _args \ } #define SysFileFindNext(_args) asm { \ compchktype _args, FileFindType \ syscall FileFindNext, _args \ } #define SysFileOpenWriteLinear(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenWriteLinear, _args \ } #define SysFileOpenWriteNonLinear(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenWriteNonLinear, _args \ } #define SysFileOpenReadLinear(_args) asm { \ compchktype _args, FileOpenType \ syscall FileOpenReadLinear, _args \ } #if __FIRMWARE_VERSION > 107 #define SysFileSeek(_args) asm { \ compchktype _args, FileSeekType \ syscall FileSeek, _args \ } #define SysFileResize(_args) asm { \ compchktype _args, FileResizeType \ syscall FileResize, _args \ } #define SysFileTell(_args) asm { \ compchktype _args, FileTellType \ syscall FileTell, _args \ } #endif #endif #if __FIRMWARE_VERSION > 107 #define SysListFiles(_args) asm { \ compchktype _args, ListFilesType \ syscall ListFiles, _args \ } #endif #endif /** @} */ // end of LoaderModuleFunctions group /** @} */ // end of LoaderModule group /** @} */ // end of NXTFirmwareModules group /** @addtogroup ThirdPartyDevices * @{ */ /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// HiTechnic API //////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup HiTechnicAPI * @{ */ /** * Read HiTechnic Gyro sensor. * Read the HiTechnic Gyro sensor on the specified port. The offset value * should be calculated by averaging several readings with an offset of zero * while the sensor is perfectly still. * * \param port The sensor port. See \ref InPorts. * \param offset The zero offset. * \return The Gyro sensor reading. */ inline int SensorHTGyro(const byte & port, int offset = 0) { asm { getin __RETVAL__, port, RawValueField sub __RETVAL__, __RETVAL__, 600 sub __RETVAL__, __RETVAL__, offset } } /** * Read HiTechnic Magnet sensor. * Read the HiTechnic Magnet sensor on the specified port. The offset value * should be calculated by averaging several readings with an offset of zero * while the sensor is perfectly still. * * \param port The sensor port. See \ref InPorts. * \param offset The zero offset. * \return The Magnet sensor reading. */ inline int SensorHTMagnet(const byte & port, int offset = 0) { asm { getin __RETVAL__, port, RawValueField sub __RETVAL__, __RETVAL__, 600 sub __RETVAL__, __RETVAL__, offset } } /** * Read HiTechnic EOPD sensor. * Read the HiTechnic EOPD sensor on the specified port. * * \param port The sensor port. See \ref InPorts. * \return The EOPD sensor reading. */ inline int SensorHTEOPD(const byte & port) { asm { getin __RETVAL__, port, RawValueField sub __RETVAL__, 1023, __RETVAL__ } } /** * Set sensor as HiTechnic EOPD. * Configure the sensor on the specified port as a HiTechnic EOPD sensor. * * \param port The sensor port. See \ref InPorts. * \param bStandard Configure in standard or long-range mode. */ inline void SetSensorHTEOPD(const byte & port, bool bStandard) { SetSensorType(port, bStandard ? SENSOR_TYPE_LIGHT_INACTIVE : SENSOR_TYPE_LIGHT_ACTIVE); SetSensorMode(port, SENSOR_MODE_RAW); ResetSensor(port); } /** * Set sensor as HiTechnic Gyro. * Configure the sensor on the specified port as a HiTechnic Gyro sensor. * * \param port The sensor port. See \ref InPorts. */ inline void SetSensorHTGyro(const byte & port) { SetSensorType(port, SENSOR_TYPE_LIGHT_INACTIVE); SetSensorMode(port, SENSOR_MODE_RAW); ResetSensor(port); } /** * Set sensor as HiTechnic Magnet. * Configure the sensor on the specified port as a HiTechnic Magnet sensor. * * \param port The sensor port. See \ref InPorts. */ inline void SetSensorHTMagnet(const byte & port) { SetSensorType(port, SENSOR_TYPE_LIGHT_INACTIVE); SetSensorMode(port, SENSOR_MODE_RAW); ResetSensor(port); } #ifdef __DOXYGEN_DOCS /** * Read HiTechnic color sensor color number. * Read the color number from the HiTechnic Color sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \return The color number. */ inline int SensorHTColorNum(const byte & port); /** * Read HiTechnic compass. * Read the compass heading value of the HiTechnic Compass sensor on the * specified port. The port must be configured as a Lowspeed port before * using this function. * * \param port The sensor port. See \ref InPorts. * \return The compass heading. */ inline int SensorHTCompass(const byte & port); /** * Read HiTechnic IRSeeker direction. * Read the direction value of the HiTechnic IR Seeker on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \return The IRSeeker direction. */ inline int SensorHTIRSeekerDir(const byte & port); /** * Read HiTechnic IRSeeker2 register. * Read a register value from the HiTechnic IR Seeker2 on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \param reg The register address. See \ref HTIRSeeker2Constants. * \return The IRSeeker2 register value. */ inline int SensorHTIRSeeker2Addr(const byte & port, const byte reg); /** * Read HiTechnic IRSeeker2 DC direction. * Read the DC direction value from the HiTechnic IR Seeker2 on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \return The IRSeeker2 DC direction. */ inline int SensorHTIRSeeker2DCDir(const byte & port); /** * Read HiTechnic IRSeeker2 AC direction. * Read the AC direction value from the HiTechnic IR Seeker2 on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \return The IRSeeker2 AC direction. */ inline int SensorHTIRSeeker2ACDir(const byte & port); /** * Set HiTechnic Color2 mode. * Set the mode of the HiTechnic Color2 sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \param mode The Color2 mode. See \ref HTColor2Constants. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char SetHTColor2Mode(const byte & port, byte mode); /** * Set HiTechnic IRSeeker2 mode. * Set the mode of the HiTechnic IRSeeker2 sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \param mode The IRSeeker2 mode. See \ref HTIRSeeker2Constants. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char SetHTIRSeeker2Mode(const byte & port, const byte mode); /** * Read HiTechnic acceleration values. * Read X, Y, and Z axis acceleration values from the HiTechnic Accelerometer * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param x The output x-axis acceleration. * \param y The output y-axis acceleration. * \param z The output z-axis acceleration. * \return The function call result. */ inline bool ReadSensorHTAccel(const byte port, int & x, int & y, int & z); /** * Read HiTechnic Color values. * Read color number, red, green, and blue values from the HiTechnic Color * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param ColorNum The output color number. * \param Red The red color value. * \param Green The green color value. * \param Blue The blue color value. * \return The function call result. */ inline bool ReadSensorHTColor(const byte port, byte & ColorNum, byte & Red, byte & Green, byte & Blue); /** * Read HiTechnic IRSeeker values. * Read direction, and five signal strength values from the HiTechnic * IRSeeker sensor. Returns a boolean value indicating whether or not the * operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param dir The direction. * \param s1 The signal strength from sensor 1. * \param s3 The signal strength from sensor 3. * \param s5 The signal strength from sensor 5. * \param s7 The signal strength from sensor 7. * \param s9 The signal strength from sensor 9. * \return The function call result. */ inline bool ReadSensorHTIRSeeker(const byte port, byte & dir, byte & s1, byte & s3, byte & s5, byte & s7, byte & s9); /** * Read HiTechnic Color normalized values. * Read the color index and the normalized red, green, and blue values from * the HiTechnic Color sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param ColorIdx The output color index. * \param Red The normalized red color value. * \param Green The normalized green color value. * \param Blue The normalized blue color value. * \return The function call result. */ inline bool ReadSensorHTNormalizedColor(const byte port, byte & ColorIdx, byte & Red, byte & Green, byte & Blue); /** * Read HiTechnic Color raw values. * Read the raw red, green, and blue values from the HiTechnic Color sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param Red The raw red color value. * \param Green The raw green color value. * \param Blue The raw blue color value. * \return The function call result. */ inline bool ReadSensorHTRawColor(const byte port, unsigned int & Red, unsigned int & Green, unsigned int & Blue); /** * Read HiTechnic Color2 active values. * Read color number, red, green, and blue values from the HiTechnic Color2 * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param ColorNum The output color number. * \param Red The red color value. * \param Green The green color value. * \param Blue The blue color value. * \param White The white color value. * \return The function call result. */ inline bool ReadSensorHTColor2Active(byte port, byte & ColorNum, byte & Red, byte & Green, byte & Blue, byte & White); /** * Read HiTechnic Color2 normalized active values. * Read the color index and the normalized red, green, and blue values from * the HiTechnic Color2 sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param ColorIdx The output color index. * \param Red The normalized red color value. * \param Green The normalized green color value. * \param Blue The normalized blue color value. * \return The function call result. */ inline bool ReadSensorHTNormalizedColor2Active(const byte port, byte & ColorIdx, byte & Red, byte & Green, byte & Blue); /** * Read HiTechnic Color2 raw values. * Read the raw red, green, and blue values from the HiTechnic Color2 sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param Red The raw red color value. * \param Green The raw green color value. * \param Blue The raw blue color value. * \param White The raw white color value. * \return The function call result. */ inline bool ReadSensorHTRawColor2(const byte port, unsigned int & Red, unsigned int & Green, unsigned int & Blue, unsigned int & White); /** * Read HiTechnic IRReceiver Power Function bytes. * Read Power Function bytes from the HiTechnic IRReceiver sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param pfdata Eight bytes of power function remote IR data. * \return The function call result. */ inline bool ReadSensorHTIRReceiver(const byte port, char & pfdata[]); /** * Read HiTechnic IRReceiver Power Function value. * Read a Power Function byte from the HiTechnic IRReceiver sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param offset The power function data offset. See \ref HTIRReceiverConstants. * \param pfchar A single byte of power function remote IR data. * \return The function call result. */ inline bool ReadSensorHTIRReceiverEx(const byte port, const byte offset, char & pfchar); /** * Read HiTechnic IRSeeker2 AC values. * Read direction, and five signal strength values from the HiTechnic * IRSeeker2 sensor in AC mode. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param dir The direction. * \param s1 The signal strength from sensor 1. * \param s3 The signal strength from sensor 3. * \param s5 The signal strength from sensor 5. * \param s7 The signal strength from sensor 7. * \param s9 The signal strength from sensor 9. * \return The function call result. */ inline bool ReadSensorHTIRSeeker2AC(const byte port, byte & dir, byte & s1, byte & s3, byte & s5, byte & s7, byte & s9); /** * Read HiTechnic IRSeeker2 DC values. * Read direction, five signal strength, and average strength values from the * HiTechnic IRSeeker2 sensor. Returns a boolean value indicating whether or * not the operation completed successfully. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param dir The direction. * \param s1 The signal strength from sensor 1. * \param s3 The signal strength from sensor 3. * \param s5 The signal strength from sensor 5. * \param s7 The signal strength from sensor 7. * \param s9 The signal strength from sensor 9. * \param avg The average signal strength. * \return The function call result. */ inline bool ReadSensorHTIRSeeker2DC(const byte port, byte & dir, byte & s1, byte & s3, byte & s5, byte & s7, byte & s9, byte & avg); /** * Reset HiTechnic Angle sensor. * Reset the HiTechnic Angle sensor on the specified * port. The port must be configured as a Lowspeed port before using this * function. * * \param port The sensor port. See \ref InPorts. * \param mode The Angle reset mode. See \ref HTAngleConstants. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char ResetSensorHTAngle(const byte port, const byte mode); /** * Read HiTechnic Angle sensor values. * Read values from the HiTechnic Angle sensor. * Returns a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param Angle Current angle in degrees (0-359). * \param AccAngle Accumulated angle in degrees (-2147483648 to 2147483647). * \param RPM rotations per minute (-1000 to 1000). * \return The function call result. */ inline bool ReadSensorHTAngle(const byte port, int & Angle, long & AccAngle, int & RPM); /** * Read HiTechnic touch multiplexer. * Read touch sensor values from the HiTechnic touch multiplexer device. * * \param port The sensor port. See \ref InPorts. * \param t1 The value of touch sensor 1. * \param t2 The value of touch sensor 2. * \param t3 The value of touch sensor 3. * \param t4 The value of touch sensor 4. */ inline void ReadSensorHTTouchMultiplexer(const byte port, byte & t1, byte & t2, byte & t3, byte & t4); /** * HTIRTrain function. * Control an IR Train receiver set to the specified channel using the * HiTechnic iRLink device. Valid func values are \ref TRAIN_FUNC_STOP, * \ref TRAIN_FUNC_INCR_SPEED, \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. * Valid channel values are \ref TRAIN_CHANNEL_1 through \ref TRAIN_CHANNEL_3 and * \ref TRAIN_CHANNEL_ALL. The port must be configured as a Lowspeed port before * using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The IR Train channel. See \ref IRTrainChannels. * \param func The IR Train function. See \ref IRTrainFuncs * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTIRTrain(const byte port, const byte channel, const byte func); /** * HTPFComboDirect function. * Execute a pair of Power Function motor commands on the specified channel * using the HiTechnic iRLink device. Commands for outa and outb are * \ref PF_CMD_STOP, \ref PF_CMD_REV, \ref PF_CMD_FWD, and \ref PF_CMD_BRAKE. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param outa The Power Function command for output A. See \ref PFCmdConstants. * \param outb The Power Function command for output B. See \ref PFCmdConstants. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFComboDirect(const byte port, const byte channel, const byte outa, const byte outb); /** * HTPFComboPWM function. * Control the speed of both outputs on a Power Function receiver set to the * specified channel using the HiTechnic iRLink device. Valid output values * are \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param outa The Power Function PWM command for output A. See \ref PFPWMOptions. * \param outb The Power Function PWM command for output B. See \ref PFPWMOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFComboPWM(const byte port, const byte channel, const byte outa, const byte outb); /** * HTPFRawOutput function. * Control a Power Function receiver set to the specified channel using the * HiTechnic iRLink device. Build the raw data stream using the 3 nibbles * (4 bit values). The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param nibble0 The first raw data nibble. * \param nibble1 The second raw data nibble. * \param nibble2 The third raw data nibble. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFRawOutput(const byte port, const byte nibble0, const byte nibble1, const byte nibble2); /** * HTPFRepeat function. * Repeat sending the last Power Function command using the HiTechnic * IRLink device. Specify the number of times to repeat the command and the * number of milliseconds of delay between each repetition. The port must be * configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param count The number of times to repeat the command. * \param delay The number of milliseconds to delay between each repetition. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFRepeat(const byte port, const byte count, const unsigned int delay); /** * HTPFSingleOutputCST function. * Control a single output on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are \ref PF_CST_CLEAR1_CLEAR2, * \ref PF_CST_SET1_CLEAR2, \ref PF_CST_CLEAR1_SET2, \ref PF_CST_SET1_SET2, * \ref PF_CST_INCREMENT_PWM, \ref PF_CST_DECREMENT_PWM, \ref PF_CST_FULL_FWD, * \ref PF_CST_FULL_REV, and \ref PF_CST_TOGGLE_DIR. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param func The Power Function CST function. See \ref PFCSTOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFSingleOutputCST(const byte port, const byte channel, const byte out, const byte func); /** * HTPFSingleOutputPWM function. * Control the speed of a single output on a Power Function receiver set to * the specified channel using the HiTechnic iRLink device. Select the * desired output using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are * \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param func The Power Function PWM function. See \ref PFPWMOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFSingleOutputPWM(const byte port, const byte channel, const byte out, const byte func); /** * HTPFSinglePin function. * Control a single pin on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Select the desired pin using \ref PF_PIN_C1 or * \ref PF_PIN_C2. Valid functions are \ref PF_FUNC_NOCHANGE, \ref PF_FUNC_CLEAR, * \ref PF_FUNC_SET, and \ref PF_FUNC_TOGGLE. Valid channels are \ref PF_CHANNEL_1 through * \ref PF_CHANNEL_4. Specify whether the mode by passing true (continuous) or * false (timeout) as the final parameter. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param pin The Power Function pin. See \ref PFPinConstants. * \param func The Power Function single pin function. See \ref PFPinFuncs. * \param cont Control whether the mode is continuous or timeout. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFSinglePin(const byte port, const byte channel, const byte out, const byte pin, const byte func, bool cont); /** * HTPFTrain function. * Control both outputs on a Power Function receiver set to the specified * channel using the HiTechnic iRLink device as if it were an IR Train * receiver. Valid function values are \ref TRAIN_FUNC_STOP, \ref TRAIN_FUNC_INCR_SPEED, * \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param func The Power Function train function. See \ref IRTrainFuncs. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char HTPFTrain(const byte port, const byte channel, const byte func); /** * HTRCXSetIRLinkPort function. * Set the global port in advance of using the HTRCX* and HTScout* API * functions for sending RCX and Scout messages over the HiTechnic iRLink * device. The port must be configured as a Lowspeed port before using any of * the HiTechnic RCX and Scout iRLink functions. * * \param port The sensor port. See \ref InPorts. */ inline void HTRCXSetIRLinkPort(const byte port); /** * HTRCXBatteryLevel function. * Send the BatteryLevel command to an RCX to read the current battery level. * * \return The RCX battery level. */ inline int HTRCXBatteryLevel(void); /** * HTRCXPoll function * Send the Poll command to an RCX to read a signed 2-byte value at the * specified source and value combination. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. * \return The value read from the specified port and value. */ inline int HTRCXPoll(const byte src, const byte value); /** * HTRCXPollMemory function. * Send the PollMemory command to an RCX. * * \param address The RCX memory address. * \return The value read from the specified address. */ inline int HTRCXPollMemory(const unsigned int address); /** * HTRCXAddToDatalog function. * Send the AddToDatalog command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void HTRCXAddToDatalog(const byte src, const unsigned int value); /** * HTRCXClearAllEvents function. * Send the ClearAllEvents command to an RCX. */ inline void HTRCXClearAllEvents(void); /** * HTRCXClearCounter function. * Send the ClearCounter command to an RCX. * * \param counter The counter to clear. */ inline void HTRCXClearCounter(const byte counter); /** * HTRCXClearMsg function. * Send the ClearMsg command to an RCX. */ inline void HTRCXClearMsg(void); /** * HTRCXClearSensor function. * Send the ClearSensor command to an RCX. * * \param port The RCX port number. */ inline void HTRCXClearSensor(const byte port); /** * HTRCXClearSound function. * Send the ClearSound command to an RCX. */ inline void HTRCXClearSound(void); /** * HTRCXClearTimer function. * Send the ClearTimer command to an RCX. * * \param timer The timer to clear. */ inline void HTRCXClearTimer(const byte timer); /** * HTRCXCreateDatalog function. * Send the CreateDatalog command to an RCX. * * \param size The new datalog size. */ inline void HTRCXCreateDatalog(const unsigned int size); /** * HTRCXDecCounter function. * Send the DecCounter command to an RCX. * * \param counter The counter to decrement. */ inline void HTRCXDecCounter(const byte counter); /** * HTRCXDeleteSub function. * Send the DeleteSub command to an RCX. * * \param s The subroutine number to delete. */ inline void HTRCXDeleteSub(const byte s); /** * HTRCXDeleteSubs function. * Send the DeleteSubs command to an RCX. */ inline void HTRCXDeleteSubs(void); /** * HTRCXDeleteTask function. * Send the DeleteTask command to an RCX. * * \param t The task number to delete. */ inline void HTRCXDeleteTask(const byte t); /** * HTRCXDeleteTasks function. * Send the DeleteTasks command to an RCX. */ inline void HTRCXDeleteTasks(void); /** * HTRCXDisableOutput function. * Send the DisableOutput command to an RCX. * * \param outputs The RCX output(s) to disable. See \ref RCXOutputConstants. */ inline void HTRCXDisableOutput(const byte outputs); /** * HTRCXEnableOutput function. * Send the EnableOutput command to an RCX. * * \param outputs The RCX output(s) to enable. See \ref RCXOutputConstants. */ inline void HTRCXEnableOutput(const byte outputs); /** * HTRCXEvent function. * Send the Event command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void HTRCXEvent(const byte src, const unsigned int value); /** * HTRCXFloat function. * Send commands to an RCX to float the specified outputs. * * \param outputs The RCX output(s) to float. See \ref RCXOutputConstants. */ inline void HTRCXFloat(const byte outputs); /** * HTRCXFwd function. * Send commands to an RCX to set the specified outputs to the forward direction. * * \param outputs The RCX output(s) to set forward. See \ref RCXOutputConstants. */ inline void HTRCXFwd(const byte outputs); /** * HTRCXIncCounter function. * Send the IncCounter command to an RCX. * * \param counter The counter to increment. */ inline void HTRCXIncCounter(const byte counter); /** * HTRCXInvertOutput function. * Send the InvertOutput command to an RCX. * * \param outputs The RCX output(s) to invert. See \ref RCXOutputConstants. */ inline void HTRCXInvertOutput(const byte outputs); /** * HTRCXMuteSound function. * Send the MuteSound command to an RCX. */ inline void HTRCXMuteSound(void); /** * HTRCXObvertOutput function. * Send the ObvertOutput command to an RCX. * * \param outputs The RCX output(s) to obvert. See \ref RCXOutputConstants. */ inline void HTRCXObvertOutput(const byte outputs); /** * HTRCXOff function. * Send commands to an RCX to turn off the specified outputs. * * \param outputs The RCX output(s) to turn off. See \ref RCXOutputConstants. */ inline void HTRCXOff(const byte outputs); /** * HTRCXOn function. * Send commands to an RCX to turn on the specified outputs. * * \param outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. */ inline void HTRCXOn(const byte outputs); /** * HTRCXOnFor function. * Send commands to an RCX to turn on the specified outputs in the forward * direction for the specified duration. * * \param outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. * \param ms The number of milliseconds to leave the outputs on */ inline void HTRCXOnFor(const byte outputs, const unsigned int ms); /** * HTRCXOnFwd function. * Send commands to an RCX to turn on the specified outputs in the forward * direction. * * \param outputs The RCX output(s) to turn on in the forward direction. See \ref RCXOutputConstants. */ inline void HTRCXOnFwd(const byte outputs); /** * HTRCXOnRev function. * Send commands to an RCX to turn on the specified outputs in the reverse direction. * * \param outputs The RCX output(s) to turn on in the reverse direction. See \ref RCXOutputConstants. */ inline void HTRCXOnRev(const byte outputs); /** * HTRCXPBTurnOff function. * Send the PBTurnOff command to an RCX. */ inline void HTRCXPBTurnOff(void); /** * HTRCXPing function. * Send the Ping command to an RCX. */ inline void HTRCXPing(void); /** * HTRCXPlaySound function. * Send the PlaySound command to an RCX. * * \param snd The sound number to play. */ inline void HTRCXPlaySound(const byte snd); /** * HTRCXPlayTone function. * Send the PlayTone command to an RCX. * * \param freq The frequency of the tone to play. * \param duration The duration of the tone to play. */ inline void HTRCXPlayTone(const unsigned int freq, const byte duration); /** * HTRCXPlayToneVar function. * Send the PlayToneVar command to an RCX. * * \param varnum The variable containing the tone frequency to play. * \param duration The duration of the tone to play. */ inline void HTRCXPlayToneVar(const byte varnum, const byte duration); /** * HTRCXRemote function. * Send the Remote command to an RCX. * * \param cmd The RCX IR remote command to send. See \ref RCXRemoteConstants. */ inline void HTRCXRemote(unsigned int cmd); /** * HTRCXRev function. * Send commands to an RCX to set the specified outputs to the reverse direction. * * \param outputs The RCX output(s) to reverse direction. See \ref RCXOutputConstants. */ inline void HTRCXRev(const byte outputs); /** * HTRCXSelectDisplay function. * Send the SelectDisplay command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void HTRCXSelectDisplay(const byte src, const unsigned int value); /** * HTRCXSelectProgram function. * Send the SelectProgram command to an RCX. * * \param prog The program number to select. */ inline void HTRCXSelectProgram(const byte prog); /** * HTRCXSendSerial function. * Send the SendSerial command to an RCX. * * \param first The first byte address. * \param count The number of bytes to send. */ inline void HTRCXSendSerial(const byte first, const byte count); /** * HTRCXSetDirection function. * Send the SetDirection command to an RCX to configure the direction of the specified outputs. * * \param outputs The RCX output(s) to set direction. See \ref RCXOutputConstants. * \param dir The RCX output direction. See \ref RCXOutputDirection. */ inline void HTRCXSetDirection(const byte outputs, const byte dir); /** * HTRCXSetEvent function. * Send the SetEvent command to an RCX. * * \param evt The event number to set. * \param src The RCX source. See \ref RCXSourceConstants. * \param type The event type. */ inline void HTRCXSetEvent(const byte evt, const byte src, const byte type); /** * HTRCXSetGlobalDirection function. * Send the SetGlobalDirection command to an RCX. * * \param outputs The RCX output(s) to set global direction. See \ref RCXOutputConstants. * \param dir The RCX output direction. See \ref RCXOutputDirection. */ inline void HTRCXSetGlobalDirection(const byte outputs, const byte dir); /** * HTRCXSetGlobalOutput function. * Send the SetGlobalOutput command to an RCX. * * \param outputs The RCX output(s) to set global mode. See \ref RCXOutputConstants. * \param mode The RCX output mode. See \ref RCXOutputMode. */ inline void HTRCXSetGlobalOutput(const byte outputs, const byte mode); /** * HTRCXSetMaxPower function. * Send the SetMaxPower command to an RCX. * * \param outputs The RCX output(s) to set max power. See \ref RCXOutputConstants. * \param pwrsrc The RCX source. See \ref RCXSourceConstants. * \param pwrval The RCX value. */ inline void HTRCXSetMaxPower(const byte outputs, const byte pwrsrc, const byte pwrval); /** * HTRCXSetMessage function. * Send the SetMessage command to an RCX. * * \param msg The numeric message to send. */ inline void HTRCXSetMessage(const byte msg); /** * HTRCXSetOutput function. * Send the SetOutput command to an RCX to configure the mode of the specified outputs * * \param outputs The RCX output(s) to set mode. See \ref RCXOutputConstants. * \param mode The RCX output mode. See \ref RCXOutputMode. */ inline void HTRCXSetOutput(const byte outputs, const byte mode); /** * HTRCXSetPower function. * Send the SetPower command to an RCX to configure the power level of the specified outputs. * * \param outputs The RCX output(s) to set power. See \ref RCXOutputConstants. * \param pwrsrc The RCX source. See \ref RCXSourceConstants. * \param pwrval The RCX value. */ inline void HTRCXSetPower(const byte outputs, const byte pwrsrc, const byte pwrval); /** * HTRCXSetPriority function. * Send the SetPriority command to an RCX. * * \param p The new task priority. */ inline void HTRCXSetPriority(const byte p); /** * HTRCXSetSensorMode function. * Send the SetSensorMode command to an RCX. * * \param port The RCX sensor port. * \param mode The RCX sensor mode. */ inline void HTRCXSetSensorMode(const byte port, const byte mode); /** * HTRCXSetSensorType function. * Send the SetSensorType command to an RCX. * * \param port The RCX sensor port. * \param type The RCX sensor type. */ inline void HTRCXSetSensorType(const byte port, const byte type); /** * HTRCXSetSleepTime function. * Send the SetSleepTime command to an RCX. * * \param t The new sleep time value. */ inline void HTRCXSetSleepTime(const byte t); /** * HTRCXSetTxPower function. * Send the SetTxPower command to an RCX. * * \param pwr The IR transmit power level. */ inline void HTRCXSetTxPower(const byte pwr); /** * HTRCXSetWatch function. * Send the SetWatch command to an RCX. * * \param hours The new watch time hours value. * \param minutes The new watch time minutes value. */ inline void HTRCXSetWatch(const byte hours, const byte minutes); /** * HTRCXStartTask function. * Send the StartTask command to an RCX. * * \param t The task number to start. */ inline void HTRCXStartTask(const byte t); /** * HTRCXStopAllTasks function. * Send the StopAllTasks command to an RCX. */ inline void HTRCXStopAllTasks(void); /** * HTRCXStopTask function. * Send the StopTask command to an RCX. * * \param t The task number to stop. */ inline void HTRCXStopTask(const byte t); /** * HTRCXToggle function. * Send commands to an RCX to toggle the direction of the specified outputs. * * \param outputs The RCX output(s) to toggle. See \ref RCXOutputConstants. */ inline void HTRCXToggle(const byte outputs); /** * HTRCXUnmuteSound function. * Send the UnmuteSound command to an RCX. */ inline void HTRCXUnmuteSound(void); /** * HTScoutCalibrateSensor function. * Send the CalibrateSensor command to a Scout. */ inline void HTScoutCalibrateSensor(void); /** * HTScoutMuteSound function. * Send the MuteSound command to a Scout. */ inline void HTScoutMuteSound(void); /** * HTScoutSelectSounds function. * Send the SelectSounds command to a Scout. * * \param grp The Scout sound group to select. */ inline void HTScoutSelectSounds(const byte grp); /** * HTScoutSendVLL function. * Send the SendVLL command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSendVLL(const byte src, const unsigned int value); /** * HTScoutSetEventFeedback function. * Send the SetEventFeedback command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSetEventFeedback(const byte src, const unsigned int value); /** * HTScoutSetLight function. * Send the SetLight command to a Scout. * * \param x Set the light on or off using this value. See \ref ScoutLightConstants. */ inline void HTScoutSetLight(const byte x); /** * HTScoutSetScoutMode function. * Send the SetScoutMode command to a Scout. * * \param mode Set the scout mode. See \ref ScoutModeConstants. */ inline void HTScoutSetScoutMode(const byte mode); /** * HTScoutSetSensorClickTime function. * Send the SetSensorClickTime command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSetSensorClickTime(const byte src, const unsigned int value); /** * HTScoutSetSensorHysteresis function. * Send the SetSensorHysteresis command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSetSensorHysteresis(const byte src, const unsigned int value); /** * HTScoutSetSensorLowerLimit function. * Send the SetSensorLowerLimit command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSetSensorLowerLimit(const byte src, const unsigned int value); /** * HTScoutSetSensorUpperLimit function. * Send the SetSensorUpperLimit command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void HTScoutSetSensorUpperLimit(const byte src, const unsigned int value); /** * HTScoutUnmuteSound function. * Send the UnmuteSound command to a Scout. */ inline void HTScoutUnmuteSound(void); #else #define SensorHTCompass(_port) asm { ReadSensorHTCompass(_port, __RETVAL__) } #define ReadSensorHTAccel(_port, _x, _y, _z) asm { __ReadSensorHTAccel(_port, _x, _y, _z, __RETVAL__) } #define ReadSensorHTColor(_port, _ColorNum, _Red, _Green, _Blue) asm { __ReadSensorHTColor(_port, _ColorNum, _Red, _Green, _Blue, __RETVAL__) } #define ReadSensorHTRawColor(_port, _Red, _Green, _Blue) asm { __ReadSensorHTRawColor(_port, _Red, _Green, _Blue, __RETVAL__) } #define ReadSensorHTNormalizedColor(_port, _ColorIdx, _Red, _Green, _Blue) asm { __ReadSensorHTNormalizedColor(_port, _ColorIdx, _Red, _Green, _Blue, __RETVAL__) } #define ReadSensorHTIRSeeker(_port, _dir, _s1, _s3, _s5, _s7, _s9) asm { __ReadSensorHTIRSeeker(_port, _dir, _s1, _s3, _s5, _s7, _s9, __RETVAL__) } #define SensorHTIRSeekerDir(_port) asm { ReadSensorHTIRSeekerDir(_port, __RETVAL__) } #define SensorHTColorNum(_port) asm { ReadSensorHTColorNum(_port, __RETVAL__) } #define ReadSensorHTTouchMultiplexer(_p, _t1, _t2, _t3, _t4) asm { __ReadSensorHTTouchMultiplexer(_p, _t1, _t2, _t3, _t4) } #define SensorHTIRSeeker2Addr(_port, _reg) asm { ReadSensorHTIRSeeker2Addr(_port, _reg, __RETVAL__) } #define SensorHTIRSeeker2DCDir(_port) asm { ReadSensorHTIRSeeker2Addr(_port, HTIR2_REG_DCDIR, __RETVAL__) } #define SensorHTIRSeeker2ACDir(_port) asm { ReadSensorHTIRSeeker2Addr(_port, HTIR2_REG_ACDIR, __RETVAL__) } #define ReadSensorHTIRSeeker2DC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _avg) asm { __ReadSensorHTIRSeeker2DC(_port, _dir, _s1, _s3, _s5, _s7, _s9, _avg, __RETVAL__) } #define ReadSensorHTIRSeeker2AC(_port, _dir, _s1, _s3, _s5, _s7, _s9) asm { __ReadSensorHTIRSeeker2AC(_port, _dir, _s1, _s3, _s5, _s7, _s9, __RETVAL__) } #define SetHTIRSeeker2Mode(_port, _mode) asm { __SetHTIRSeeker2Mode(_port, _mode, __RETVAL__) } #define SetHTColor2Mode(_port, _mode) asm { __SetHTColor2Mode(_port, _mode, __RETVAL__) } #define ReadSensorHTColor2Active(_port, _ColorNum, _Red, _Green, _Blue, _White) asm { __ReadSensorHTColor2Active(_port, _ColorNum, _Red, _Green, _Blue, _White, __RETVAL__) } #define ReadSensorHTNormalizedColor2Active(_port, _ColorIdx, _Red, _Green, _Blue) asm { __ReadSensorHTNormalizedColor2Active(_port, _ColorIdx, _Red, _Green, _Blue, __RETVAL__) } #define ReadSensorHTRawColor2(_port, _Red, _Green, _Blue, _White) asm { __ReadSensorHTRawColor2(_port, _Red, _Green, _Blue, _White, __RETVAL__) } #define ReadSensorHTIRReceiver(_port, _pfdata) asm { __ReadSensorHTIRReceiver(_port, _pfdata, __RETVAL__) } #define ReadSensorHTIRReceiverEx(_port, _reg, _pfchar) asm { __ReadSensorHTIRReceiverEx(_port, _reg, _pfchar, __RETVAL__) } #define ResetSensorHTAngle(_port, _mode) asm { __ResetSensorHTAngle(_port, _mode, __RETVAL__) } #define ReadSensorHTAngle(_port, _Angle, _AccAngle, _RPM) asm { __ReadSensorHTAngle(_port, _Angle, _AccAngle, _RPM, __RETVAL__) } #define HTPowerFunctionCommand(_port, _channel, _outa, _outb) asm { __HTPFComboDirect(_port, _channel, _outa, _outb, __RETVAL__) } #define HTPFComboDirect(_port, _channel, _outa, _outb) asm { __HTPFComboDirect(_port, _channel, _outa, _outb, __RETVAL__) } #define HTPFSinglePin(_port, _channel, _out, _pin, _func, _cont) asm { __HTPFSinglePin(_port, _channel, _out, _pin, _func, _cont, __RETVAL__) } #define HTPFSingleOutputCST(_port, _channel, _out, _func) asm { __HTPFSingleOutput(_port, _channel, _out, _func, TRUE, __RETVAL__) } #define HTPFSingleOutputPWM(_port, _channel, _out, _func) asm { __HTPFSingleOutput(_port, _channel, _out, _func, FALSE, __RETVAL__) } #define HTPFComboPWM(_port, _channel, _outa, _outb) asm { __HTPFComboPWM(_port, _channel, _outa, _outb, __RETVAL__) } #define HTPFTrain(_port, _channel, _func) asm { __HTIRTrain(_port, _channel, _func, TRUE, __RETVAL__) } #define HTIRTrain(_port, _channel, _func) asm { __HTIRTrain(_port, _channel, _func, FALSE, __RETVAL__) } #define HTPFRawOutput(_port, _nibble0, _nibble1, _nibble2) asm { __HTPFRawOutput(_port, _nibble0, _nibble1, _nibble2, __RETVAL__) } #define HTPFRepeat(_port, _count, _delay) asm { __HTPFRepeatLastCommand(_port, _count, _delay, __RETVAL__) } #define HTRCXSetIRLinkPort(_port) asm { __HTRCXSetIRLinkPort(_port) } #define HTRCXPoll(_src, _value) asm { __HTRCXPoll(_src, _value, __RETVAL__) } #define HTRCXBatteryLevel() asm { __HTRCXBatteryLevel(__RETVAL__) } #define HTRCXPing() asm { __HTRCXOpNoArgs(RCX_PingOp) } #define HTRCXDeleteTasks() asm { __HTRCXOpNoArgs(RCX_DeleteTasksOp) } #define HTRCXStopAllTasks() asm { __HTRCXOpNoArgs(RCX_StopAllTasksOp) } #define HTRCXPBTurnOff() asm { __HTRCXOpNoArgs(RCX_PBTurnOffOp) } #define HTRCXDeleteSubs() asm { __HTRCXOpNoArgs(RCX_DeleteSubsOp) } #define HTRCXClearSound() asm { __HTRCXOpNoArgs(RCX_ClearSoundOp) } #define HTRCXClearMsg() asm { __HTRCXOpNoArgs(RCX_ClearMsgOp) } #define HTRCXMuteSound() asm { __HTRCXOpNoArgs(RCX_MuteSoundOp) } #define HTRCXUnmuteSound() asm { __HTRCXOpNoArgs(RCX_UnmuteSoundOp) } #define HTRCXClearAllEvents() asm { __HTRCXOpNoArgs(RCX_ClearAllEventsOp) } #define HTRCXSetOutput(_outputs, _mode) asm { __HTRCXSetOutput(_outputs, _mode) } #define HTRCXSetDirection(_outputs, _dir) asm { __HTRCXSetDirection(_outputs, _dir) } #define HTRCXSetPower(_outputs, _pwrsrc, _pwrval) asm { __HTRCXSetPower(_outputs, _pwrsrc, _pwrval) } #define HTRCXOn(_outputs) asm { __HTRCXSetOutput(_outputs, RCX_OUT_ON) } #define HTRCXOff(_outputs) asm { __HTRCXSetOutput(_outputs, RCX_OUT_OFF) } #define HTRCXFloat(_outputs) asm { __HTRCXSetOutput(_outputs, RCX_OUT_FLOAT) } #define HTRCXToggle(_outputs) asm { __HTRCXSetDirection(_outputs, RCX_OUT_TOGGLE) } #define HTRCXFwd(_outputs) asm { __HTRCXSetDirection(_outputs, RCX_OUT_FWD) } #define HTRCXRev(_outputs) asm { __HTRCXSetDirection(_outputs, RCX_OUT_REV) } #define HTRCXOnFwd(_outputs) asm { __HTRCXOnFwd(_outputs) } #define HTRCXOnRev(_outputs) asm { __HTRCXOnRev(_outputs) } #define HTRCXOnFor(_outputs, _ms) asm { __HTRCXOnFor(_outputs, _ms) } #define HTRCXSetTxPower(_pwr) asm { __HTRCXSetTxPower(_pwr) } #define HTRCXPlaySound(_snd) asm { __HTRCXPlaySound(_snd) } #define HTRCXDeleteTask(_t) asm { __HTRCXDeleteTask(_t) } #define HTRCXStartTask(_t) asm { __HTRCXStartTask(_t) } #define HTRCXStopTask(_t) asm { __HTRCXStopTask(_t) } #define HTRCXSelectProgram(_prog) asm { __HTRCXSelectProgram(_prog) } #define HTRCXClearTimer(_timer) asm { __HTRCXClearTimer(_timer) } #define HTRCXSetSleepTime(_t) asm { __HTRCXSetSleepTime(_t) } #define HTRCXDeleteSub(_s) asm { __HTRCXDeleteSub(_s) } #define HTRCXClearSensor(_port) asm { __HTRCXClearSensor(_port) } #define HTRCXPlayToneVar(_varnum, _duration) asm { __HTRCXPlayToneVar(_varnum, _duration) } #define HTRCXSetWatch(_hours, _minutes) asm { __HTRCXSetWatch(_hours, _minutes) } #define HTRCXSetSensorType(_port, _type) asm { __HTRCXSetSensorType(_port, _type) } #define HTRCXSetSensorMode(_port, _mode) asm { __HTRCXSetSensorMode(_port, _mode) } #define HTRCXCreateDatalog(_size) asm { __HTRCXCreateDatalog(_size) } #define HTRCXAddToDatalog(_src, _value) asm { __HTRCXAddToDatalog(_src, _value) } #define HTRCXSendSerial(_first, _count) asm { __HTRCXSendSerial(_first, _count) } #define HTRCXRemote(_cmd) asm { __HTRCXRemote(_cmd) } #define HTRCXEvent(_src, _value) asm { __HTRCXEvent(_src, _value) } #define HTRCXPlayTone(_freq, _duration) asm { __HTRCXPlayTone(_freq, _duration) } #define HTRCXSelectDisplay(_src, _value) asm { __HTRCXSelectDisplay(_src, _value) } #define HTRCXPollMemory(_memaddress) asm { __HTRCXPollMemory(_memaddress, __RETVAL__) } #define HTRCXSetEvent(_evt, _src, _type) asm { __HTRCXSetEvent(_evt, _src, _type) } #define HTRCXSetGlobalOutput(_outputs, _mode) asm { __HTRCXSetGlobalOutput(_outputs, _mode) } #define HTRCXSetGlobalDirection(_outputs, _dir) asm { __HTRCXSetGlobalDirection(_outputs, _dir) } #define HTRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) asm { __HTRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) } #define HTRCXEnableOutput(_outputs) asm { __HTRCXSetGlobalOutput(_outputs, RCX_OUT_ON) } #define HTRCXDisableOutput(_outputs) asm { __HTRCXSetGlobalOutput(_outputs, RCX_OUT_OFF) } #define HTRCXInvertOutput(_outputs) asm { __HTRCXSetGlobalDirection(_outputs, RCX_OUT_REV) } #define HTRCXObvertOutput(_outputs) asm { __HTRCXSetGlobalDirection(_outputs, RCX_OUT_FWD) } #define HTRCXIncCounter(_counter) asm { __HTRCXIncCounter(_counter) } #define HTRCXDecCounter(_counter) asm { __HTRCXDecCounter(_counter) } #define HTRCXClearCounter(_counter) asm { __HTRCXClearCounter(_counter) } #define HTRCXSetPriority(_p) asm { __HTRCXSetPriority(_p) } #define HTRCXSetMessage(_msg) asm { __HTRCXSetMessage(_msg) } #define HTScoutCalibrateSensor() asm { __HTRCXOpNoArgs(RCX_LSCalibrateOp) } #define HTScoutMuteSound() asm { __HTScoutMuteSound() } #define HTScoutUnmuteSound() asm { __HTScoutUnmuteSound() } #define HTScoutSelectSounds(_grp) asm { __HTScoutSelectSounds(_grp) } #define HTScoutSetLight(_x) asm { __HTScoutSetLight(_x) } #define HTScoutSetSensorClickTime(_src, _value) asm { __HTScoutSetSensorClickTime(_src, _value) } #define HTScoutSetSensorHysteresis(_src, _value) asm { __HTScoutSetSensorHysteresis(_src, _value) } #define HTScoutSetSensorLowerLimit(_src, _value) asm { __HTScoutSetSensorLowerLimit(_src, _value) } #define HTScoutSetSensorUpperLimit(_src, _value) asm { __HTScoutSetSensorUpperLimit(_src, _value) } #define HTScoutSetEventFeedback(_src, _value) asm { __HTScoutSetEventFeedback(_src, _value) } #define HTScoutSendVLL(_src, _value) asm { __HTScoutSendVLL(_src, _value) } #define HTScoutSetScoutMode(_mode) asm { __HTScoutSetScoutMode(_mode) } #endif /** @} */ // end of HiTechnicAPI group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// MindSensors API /////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup MindSensorsAPI * @{ */ /** * Configure a mindsensors pressure sensor. * Configure the specified port for a mindsensors pressure sensor. * * \param port The port to configure. See \ref InPorts. */ inline void SetSensorMSPressure(const byte & port ) { SetSensorType(port, SENSOR_TYPE_LIGHT); SetSensorMode(port, SENSOR_MODE_RAW); ResetSensor(port); } /** * Configure a mindsensors DROD sensor. * Configure the specified port for a mindsensors DROD sensor. * * \param port The port to configure. See \ref InPorts. * \param bActive A flag indicating whether to configure the sensor in active * or inactive mode. */ inline void SetSensorMSDROD(const byte & port, bool bActive) { if (bActive) SetSensorType(port, SENSOR_TYPE_LIGHT_ACTIVE); else SetSensorType(port, SENSOR_TYPE_LIGHT_INACTIVE); SetSensorMode(port, SENSOR_MODE_PERCENT); ResetSensor(port); } /** * Configure a mindsensors SumoEyes sensor. * Configure the specified port for a mindsensors SumoEyes sensor. * * \param port The port to configure. See \ref InPorts. * \param bLong A flag indicating whether to configure the sensor in long range * or short range mode. */ inline void SetSensorNXTSumoEyes(const byte & port, bool bLong) { if (bLong) SetSensorType(port, SENSOR_TYPE_LIGHT_INACTIVE); else SetSensorType(port, SENSOR_TYPE_LIGHT_ACTIVE); SetSensorMode(port, SENSOR_MODE_PERCENT); ResetSensor(port); Wait(275); } /** * Read mindsensors pressure sensor. * Read the pressure sensor value of the mindsensors pressure sensor on the * specified port. * * \param port The sensor port. See \ref InPorts. * \return The pressure reading. */ inline int SensorMSPressure(const byte & port) { asm { getin __RETVAL__, port, RawValueField sub __RETVAL__, 1024, __RETVAL__ div __RETVAL__, __RETVAL__, 25 } } /** * Read mindsensors NXTSumoEyes obstacle zone. * Return the Mindsensors NXTSumoEyes sensor obstacle zone value. The port * should be configured for the NXTSumoEyes device using \ref SetSensorNXTSumoEyes * before calling this function. * * \param port The sensor port. See \ref InPorts. * \return The mindsensors NXTSumoEyes obstacle zone value. See \ref NXTSumoEyesConstants. */ char SensorNXTSumoEyes(const byte & port) { int value; asm { getin value, port, NormalizedValueField mul value, value, 100 div value, value, 1023 } if (value > 30 && value < 36) return NXTSE_ZONE_LEFT; if (value > 63 && value < 69) return NXTSE_ZONE_RIGHT; if (value > 74 && value <= 80) return NXTSE_ZONE_FRONT; return NXTSE_ZONE_NONE; } #ifdef __DOXYGEN_DOCS /** * Read mindsensors compass value. * Return the Mindsensors Compass sensor value. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The mindsensors compass value */ inline int SensorMSCompass(const byte & port, const byte i2caddr); /** * Read mindsensors DROD value. * Return the Mindsensors DROD sensor value. * * \param port The sensor port. See \ref InPorts. * \return The mindsensors DROD value */ inline int SensorMSDROD(const byte & port); /** * Read mindsensors NXTSumoEyes raw value. * Return the Mindsensors NXTSumoEyes raw sensor value. The port * should be configured for the NXTSumoEyes device using \ref SetSensorNXTSumoEyes * before calling this function. * * \param port The sensor port. See \ref InPorts. * \return The mindsensors NXTSumoEyes raw value */ inline int SensorNXTSumoEyesRaw(const byte & port); /** * Read mindsensors raw pressure value. * Return the Mindsensors pressure sensor raw value. * * \param port The sensor port. See \ref InPorts. * \return The mindsensors raw pressure value */ inline int SensorMSPressureRaw(const byte & port); /** * Read mindsensors acceleration values. * Read X, Y, and Z axis acceleration values from the mindsensors Accelerometer * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param x The output x-axis acceleration. * \param y The output y-axis acceleration. * \param z The output z-axis acceleration. * \return The function call result. */ inline bool ReadSensorMSAccel(const byte port, const byte i2caddr, int & x, int & y, int & z); /** * Read mindsensors playstation controller values. * Read playstation controller values from the mindsensors playstation * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param btnset1 The button set 1 values. See \ref MSPSPNXBtnSet1. * \param btnset2 The button set 2 values. See \ref MSPSPNXBtnSet2. * \param xleft The left joystick x value. * \param yleft The left joystick y value. * \param xright The right joystick x value. * \param yright The right joystick y value. * \return The function call result. */ inline bool ReadSensorMSPlayStation(const byte port, const byte i2caddr, byte & btnset1, byte & btnset2, byte & xleft, byte & yleft, byte & xright, byte & yright); /** * Read mindsensors RTClock values. * Read real-time clock values from the Mindsensors RTClock sensor. Returns * a boolean value indicating whether or not the operation completed * successfully. The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param sec The seconds. * \param min The minutes. * \param hrs The hours. * \param dow The day of week number. * \param date The day. * \param month The month. * \param year The year. * \return The function call result. */ inline bool ReadSensorMSRTClock(const byte port, byte & sec, byte & min, byte & hrs, byte & dow, byte & date, byte & month, byte & year); /** * Read mindsensors tilt values. * Read X, Y, and Z axis tilt values from the mindsensors tilt * sensor. Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param x The output x-axis tilt. * \param y The output y-axis tilt. * \param z The output z-axis tilt. * \return The function call result. */ inline bool ReadSensorMSTilt(const byte & port, const byte & i2caddr, byte & x, byte & y, byte & z); /** * Send PFMate command. * Send a PFMate command to the power function IR receiver. * Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The power function IR receiver channel. See the \ref PFMateChannelConstants group. * \param motors The motor(s) to control. See the \ref PFMateMotorConstants group. * \param cmdA The power function command for motor A. * \param spdA The power function speed for motor A. * \param cmdB The power function command for motor B. * \param spdB The power function speed for motor B. * \return The function call result. */ inline bool PFMateSend(const byte & port, const byte & i2caddr, const byte & channel, const byte & motors, const byte & cmdA, const byte & spdA, const byte & cmdB, const byte & spdB); /** * Send raw PFMate command. * Send a raw PFMate command to the power function IR receiver. * Returns a boolean value indicating whether or not the operation * completed successfully. The port must be configured as a Lowspeed port * before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The power function IR receiver channel. See the \ref PFMateChannelConstants group. * \param b1 Raw byte 1. * \param b2 Raw byte 2. * \return The function call result. */ inline bool PFMateSendRaw(const byte & port, const byte & i2caddr, const byte & channel, const byte & b1, const byte & b2); /** * Read a mindsensors device value. * Read a one, two, or four byte value from a mindsensors sensor. The value must be * stored with the least signficant byte (LSB) first (i.e., little endian). Returns a boolean value * indicating whether or not the operation completed successfully. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param reg The device register to read. * \param numbytes The number of bytes to read. Only 1, 2 or 4 byte values are supported. * \return The function call result. */ inline int MSReadValue(const byte port, const byte i2caddr, const byte reg, const byte numbytes); /** * Turn on power to device. * Turn the power on for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char MSEnergize(const byte port, const byte i2caddr); /** * Turn off power to device. * Turn power off for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char MSDeenergize(const byte port, const byte i2caddr); /** * Turn on mindsensors ADPA mode. * Turn ADPA mode on for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char MSADPAOn(const byte port, const byte i2caddr); /** * Turn off mindsensors ADPA mode. * Turn ADPA mode off for the mindsensors device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char MSADPAOff(const byte port, const byte i2caddr); /** * Configure DISTNx as GP2D12. * Configure the mindsensors DISTNx sensor as GP2D12. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char DISTNxGP2D12(const byte port, const byte i2caddr); /** * Configure DISTNx as GP2D120. * Configure the mindsensors DISTNx sensor as GP2D120. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char DISTNxGP2D120(const byte port, const byte i2caddr); /** * Configure DISTNx as GP2YA02. * Configure the mindsensors DISTNx sensor as GP2YA02. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char DISTNxGP2YA02(const byte port, const byte i2caddr); /** * Configure DISTNx as GP2YA21. * Configure the mindsensors DISTNx sensor as GP2YA21. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char DISTNxGP2YA21(const byte port, const byte i2caddr); /** * Read DISTNx distance value. * Read the mindsensors DISTNx sensor's distance value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The distance value. */ inline int DISTNxDistance(const byte port, const byte i2caddr); /** * Read DISTNx maximum distance value. * Read the mindsensors DISTNx sensor's maximum distance value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The maximum distance value. */ inline int DISTNxMaxDistance(const byte port, const byte i2caddr); /** * Read DISTNx minimum distance value. * Read the mindsensors DISTNx sensor's minimum distance value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The distance value. */ inline int DISTNxMinDistance(const byte port, const byte i2caddr); /** * Read DISTNx module type value. * Read the mindsensors DISTNx sensor's module type value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The module type value. */ inline byte DISTNxModuleType(const byte port, const byte i2caddr); /** * Read DISTNx num points value. * Read the mindsensors DISTNx sensor's num points value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The num points value. */ inline byte DISTNxNumPoints(const byte port, const byte i2caddr); /** * Read DISTNx voltage value. * Read the mindsensors DISTNx sensor's voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The voltage value. */ inline int DISTNxVoltage(const byte port, const byte i2caddr); /** * Calibrate ACCL-Nx X-axis. * Calibrate the mindsensors ACCL-Nx sensor X-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateX(const byte port, const byte i2caddr); /** * Stop calibrating ACCL-Nx X-axis. * Stop calibrating the mindsensors ACCL-Nx sensor X-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateXEnd(const byte port, const byte i2caddr); /** * Calibrate ACCL-Nx Y-axis. * Calibrate the mindsensors ACCL-Nx sensor Y-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateY(const byte port, const byte i2caddr); /** * Stop calibrating ACCL-Nx Y-axis. * Stop calibrating the mindsensors ACCL-Nx sensor Y-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateYEnd(const byte port, const byte i2caddr); /** * Calibrate ACCL-Nx Z-axis. * Calibrate the mindsensors ACCL-Nx sensor Z-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateZ(const byte port, const byte i2caddr); /** * Stop calibrating ACCL-Nx Z-axis. * Stop calibrating the mindsensors ACCL-Nx sensor Z-axis. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxCalibrateZEnd(const byte port, const byte i2caddr); /** * Reset ACCL-Nx calibration. * Reset the mindsensors ACCL-Nx sensor calibration to factory settings. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char ACCLNxResetCalibration(const byte port, const byte i2caddr); /** * Set ACCL-Nx sensitivity. * Reset the mindsensors ACCL-Nx sensor calibration to factory settings. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param slevel The sensitivity level. See \ref MSACCLNxSLevel. * \return The function call result. */ inline char SetACCLNxSensitivity(const byte port, const byte i2caddr, byte slevel); /** * Read ACCL-Nx sensitivity value. * Read the mindsensors ACCL-Nx sensitivity value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The sensitivity value. */ inline byte ACCLNxSensitivity(const byte port, const byte i2caddr); /** * Read ACCL-Nx X offset value. * Read the mindsensors ACCL-Nx sensor's X offset value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The X offset value. */ inline int ACCLNxXOffset(const byte port, const byte i2caddr); /** * Read ACCL-Nx X range value. * Read the mindsensors ACCL-Nx sensor's X range value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The X range value. */ inline int ACCLNxXRange(const byte port, const byte i2caddr); /** * Read ACCL-Nx Y offset value. * Read the mindsensors ACCL-Nx sensor's Y offset value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The Y offset value. */ inline int ACCLNxYOffset(const byte port, const byte i2caddr); /** * Read ACCL-Nx Y range value. * Read the mindsensors ACCL-Nx sensor's Y range value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The Y range value. */ inline int ACCLNxYRange(const byte port, const byte i2caddr); /** * Read ACCL-Nx Z offset value. * Read the mindsensors ACCL-Nx sensor's Z offset value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The Z offset value. */ inline int ACCLNxZOffset(const byte port, const byte i2caddr); /** * Read ACCL-Nx Z range value. * Read the mindsensors ACCL-Nx sensor's Z range value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The Z range value. */ inline int ACCLNxZRange(const byte port, const byte i2caddr); /** * Configure PSPNx in digital mode. * Configure the mindsensors PSPNx device in digital mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char PSPNxDigital(const byte & port, const byte & i2caddr); /** * Configure PSPNx in analog mode. * Configure the mindsensors PSPNx device in analog mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char PSPNxAnalog(const byte & port, const byte & i2caddr); /** * Read NXTServo servo position value. * Read the mindsensors NXTServo device's servo position value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \return The specified servo's position value. */ inline unsigned int NXTServoPosition(const byte & port, const byte & i2caddr, const byte servo); /** * Read NXTServo servo speed value. * Read the mindsensors NXTServo device's servo speed value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \return The specified servo's speed value. */ inline byte NXTServoSpeed(const byte & port, const byte & i2caddr, const byte servo); /** * Read NXTServo battery voltage value. * Read the mindsensors NXTServo device's battery voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \result The battery level. */ inline byte NXTServoBatteryVoltage(const byte & port, const byte & i2caddr); /** * Set NXTServo servo motor speed. * Set the speed of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \param speed The servo speed. (0..255) * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char SetNXTServoSpeed(const byte & port, const byte & i2caddr, const byte servo, const byte & speed); /** * Set NXTServo servo motor quick position. * Set the quick position of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \param qpos The servo quick position. See \ref NXTServoQPos group. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char SetNXTServoQuickPosition(const byte & port, const byte & i2caddr, const byte servo, const byte & qpos); /** * Set NXTServo servo motor position. * Set the position of a servo motor controlled by the NXTServo device. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \param pos The servo position. See \ref NXTServoPos group. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char SetNXTServoPosition(const byte & port, const byte & i2caddr, const byte servo, const byte & pos); /** * Reset NXTServo properties. * Reset NXTServo device properties to factory defaults. * Initial position = 1500. Initial speed = 0. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoReset(const byte & port, const byte & i2caddr); /** * Halt NXTServo macro. * Halt a macro executing on the NXTServo device. This command re-initializes * the macro environment. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoHaltMacro(const byte & port, const byte & i2caddr); /** * Resume NXTServo macro. * Resume a macro executing on the NXTServo device. This command resumes * executing a macro where it was paused last, using the same environment. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoResumeMacro(const byte & port, const byte & i2caddr); /** * Pause NXTServo macro. * Pause a macro executing on the NXTServo device. This command will pause the * currently executing macro, and save the environment for subsequent resumption. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoPauseMacro(const byte & port, const byte & i2caddr); /** * Initialize NXTServo servo properties. * Store the initial speed and position properties of the servo motor 'n'. * Current speed and position values of the nth servo is read from the * servo speed register and servo position register and written to permanent * memory. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param servo The servo number. See \ref NXTServoNumbers group. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoInit(const byte & port, const byte & i2caddr, const byte servo); /** * Goto NXTServo macro address. * Run the macro found at the specified EEPROM macro address. This command * re-initializes the macro environment. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param macro The EEPROM macro address. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoGotoMacroAddress(const byte & port, const byte & i2caddr, const byte & macro); /** * Edit NXTServo macro. * Put the NXTServo device into macro edit mode. This operation changes the * I2C address of the device to 0x40. Macros are written to EEPROM addresses * between 0x21 and 0xFF. Use \ref NXTServoQuitEdit to return the device to * its normal operation mode. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoEditMacro(const byte & port, const byte & i2caddr); /** * Quit NXTServo macro edit mode. * Stop editing NXTServo device macro EEPROM memory. Use \ref NXTServoEditMacro * to start editing a macro. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible result values. */ inline char NXTServoQuitEdit(const byte & port); /** * Set NXTHID into ASCII data mode. * Set the NXTHID device into ASCII data mode. Only printable characters can be * transmitted in this mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTHIDAsciiMode(const byte & port, const byte & i2caddr); /** * Set NXTHID into direct data mode. * Set the NXTHID device into direct data mode. Any character can be transmitted * while in this mode. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTHIDDirectMode(const byte & port, const byte & i2caddr); /** * Transmit NXTHID character. * Transmit a single character to a computer using the NXTHID device. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTHIDTransmit(const byte & port, const byte & i2caddr); /** * Load NXTHID character. * Load a character into the NXTHID device. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param modifier The key modifier. See the \ref NXTHIDModifiers group. * \param character The character. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTHIDLoadCharacter(const byte & port, const byte & i2caddr, const byte & modifier, const byte & character); /** * Reset NXTPowerMeter counters. * Reset the NXTPowerMeter counters back to zero. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTPowerMeterResetCounters(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter present current. * Read the mindsensors NXTPowerMeter device's present current value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter present current. */ inline int NXTPowerMeterPresentCurrent(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter present voltage. * Read the mindsensors NXTPowerMeter device's present voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter present voltage. */ inline int NXTPowerMeterPresentVoltage(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter capacity used. * Read the mindsensors NXTPowerMeter device's capacity used since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter capacity used value. */ inline int NXTPowerMeterCapacityUsed(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter present power. * Read the mindsensors NXTPowerMeter device's present power value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter present power value. */ inline int NXTPowerMeterPresentPower(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter total power consumed. * Read the mindsensors NXTPowerMeter device's total power consumed since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter total power consumed value. */ inline long NXTPowerMeterTotalPowerConsumed(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter maximum current. * Read the mindsensors NXTPowerMeter device's maximum current value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter maximum current value. */ inline int NXTPowerMeterMaxCurrent(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter minimum current. * Read the mindsensors NXTPowerMeter device's minimum current value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter minimum current value. */ inline int NXTPowerMeterMinCurrent(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter maximum voltage. * Read the mindsensors NXTPowerMeter device's maximum voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter maximum voltage value. */ inline int NXTPowerMeterMaxVoltage(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter minimum voltage. * Read the mindsensors NXTPowerMeter device's minimum voltage value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter minimum voltage value. */ inline int NXTPowerMeterMinVoltage(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter elapsed time. * Read the mindsensors NXTPowerMeter device's elapsed time since the last reset command. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter elapsed time value. */ inline long NXTPowerMeterElapsedTime(const byte & port, const byte & i2caddr); /** * Read NXTPowerMeter error count. * Read the mindsensors NXTPowerMeter device's error count value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTPowerMeter error count value. */ inline int NXTPowerMeterErrorCount(const byte & port, const byte & i2caddr); /** * Powerdown NXTLineLeader device. * Put the NXTLineLeader to sleep so that it does not consume power when it is * not required. The device wakes up on its own when any I2C communication * happens or you can specifically wake it up by using the \ref NXTLineLeaderPowerUp * command. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderPowerDown(const byte & port, const byte & i2caddr); /** * Powerup NXTLineLeader device. * Wake up the NXTLineLeader device so that it can be used. The device can be * put to sleep using the \ref NXTLineLeaderPowerDown command. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderPowerUp(const byte & port, const byte & i2caddr); /** * Invert NXTLineLeader colors. * Invert color sensing so that the device can detect a white line on a * black background. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderInvert(const byte & port, const byte & i2caddr); /** * Reset NXTLineLeader color inversion. * Reset the NXTLineLeader color detection back to its default state (black * line on a white background). * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderReset(const byte & port, const byte & i2caddr); /** * Take NXTLineLeader line snapshot. * Takes a snapshot of the line under the sensor and tracks that position in * subsequent tracking operations. This function also will set color inversion * if it sees a white line on a black background. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderSnapshot(const byte & port, const byte & i2caddr); /** * Calibrate NXTLineLeader white color. * Store calibration data for the white color. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderCalibrateWhite(const byte & port, const byte & i2caddr); /** * Calibrate NXTLineLeader black color. * Store calibration data for the black color. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char NXTLineLeaderCalibrateBlack(const byte & port, const byte & i2caddr); /** * Read NXTLineLeader steering. * Read the mindsensors NXTLineLeader device's steering value. This is the power * returned by the sensor to correct your course. Add this value to your left * motor and subtract it from your right motor. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTLineLeader steering value. */ inline char NXTLineLeaderSteering(const byte & port, const byte & i2caddr); /** * Read NXTLineLeader average. * Read the mindsensors NXTLineLeader device's average value. The * average is a weighted average of the bits set to 1 based on the position. * The left most bit has a weight of 10, second bit has a weight of 20, and so * forth. When all 8 sensors are over a black surface the average will be 45. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTLineLeader average value. */ inline char NXTLineLeaderAverage(const byte & port, const byte & i2caddr); /** * Read NXTLineLeader result. * Read the mindsensors NXTLineLeader device's result value. This is a single * byte showing the 8 sensor's readings. Each bit corresponding to the sensor * where the line is seen is set to 1, otherwise it is set to 0. * When all 8 sensors are over a black surface the result will be 255 (b11111111). * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The NXTLineLeader result value. */ inline byte NXTLineLeaderResult(const byte & port, const byte & i2caddr); /** * Write NXTLineLeader setpoint. * Write a new setpoint value to the NXTLineLeader device. The Set Point is a * value you can ask sensor to maintain the average to. The default value is * 45, whereby the line is maintained in center of the sensor. If you need to * maintain line towards left of the sensor, set the Set Point to * a lower value (minimum: 10). If you need it to be towards on the right of the * sensor, set it to higher value (maximum: 80). Set point is also useful while * tracking an edge of dark and light areas. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new setpoint value (10..80). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderSetpoint(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Kp value. * Write a Kp value to the NXTLineLeader device. This value divided by PID * Factor for Kp is the Proportional value for the PID control. Suggested value * is 25 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Kp value (0..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKpValue(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Ki value. * Write a Ki value to the NXTLineLeader device. This value divided by PID * Factor for Ki is the Integral value for the PID control. Suggested value * is 0 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Ki value (0..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKiValue(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Kd value. * Write a Kd value to the NXTLineLeader device. This value divided by PID * Factor for Kd is the Derivative value for the PID control. Suggested value * is 8 with a divisor factor of 32 (which is also a factory default), start * with this value, and tune it to meet your needs. Value ranges * between 0 and 255. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Kd value (0..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKdValue(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Kp factor. * Write a Kp divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Kp value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Kp factor (1..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKpFactor(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Ki factor. * Write a Ki divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Ki value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Ki factor (1..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKiFactor(const byte & port, const byte & i2caddr, const byte & value); /** * Write NXTLineLeader Kd factor. * Write a Kd divisor factor to the NXTLineLeader device. Value ranges between * 1 and 255. Change this value if you need more granularities in Kd value. * The port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref NBCInputPortConstants. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param value The new Kd factor (1..255). * \return A status code indicating whether the operation completed successfully or not. * See \ref CommLSCheckStatusType for possible Result values. */ inline char SetNXTLineLeaderKdFactor(const byte & port, const byte & i2caddr, const byte & value); /** * Configure NRLink in 2400 baud mode. * Configure the mindsensors NRLink device in 2400 baud mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLink2400(const byte port, const byte i2caddr); /** * Configure NRLink in 4800 baud mode. * Configure the mindsensors NRLink device in 4800 baud mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLink4800(const byte port, const byte i2caddr); /** * Flush NRLink buffers. * Flush the mindsensors NRLink device buffers. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkFlush(const byte port, const byte i2caddr); /** * Configure NRLink in IR long mode. * Configure the mindsensors NRLink device in IR long mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkIRLong(const byte port, const byte i2caddr); /** * Configure NRLink in IR short mode. * Configure the mindsensors NRLink device in IR short mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkIRShort(const byte port, const byte i2caddr); /** * Configure NRLink in power function mode. * Configure the mindsensors NRLink device in power function mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkSetPF(const byte port, const byte i2caddr); /** * Configure NRLink in RCX mode. * Configure the mindsensors NRLink device in RCX mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkSetRCX(const byte port, const byte i2caddr); /** * Configure NRLink in IR train mode. * Configure the mindsensors NRLink device in IR train mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkSetTrain(const byte port, const byte i2caddr); /** * Configure NRLink in raw IR transmit mode. * Configure the mindsensors NRLink device in raw IR transmit mode. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The function call result. */ inline char NRLinkTxRaw(const byte port, const byte i2caddr); /** * Read NRLink status. * Read the status of the mindsensors NRLink device. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \return The mindsensors NRLink status. */ inline byte NRLinkStatus(const byte port, const byte i2caddr); /** * Run NRLink macro. * Run the specified mindsensors NRLink device macro. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param macro The address of the macro to execute. * \return The function call result. */ inline char RunNRLinkMacro(const byte port, const byte i2caddr, const byte macro); /** * Write data to NRLink. * Write data to the mindsensors NRLink device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param data A byte array containing the data to write. * \return The function call result. */ inline char WriteNRLinkBytes(const byte port, const byte i2caddr, const byte data[]); /** * Read data from NRLink. * Read data from the mindsensors NRLink device on the specified port. The port * must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param data A byte array that will contain the data read from the device on output. * \return The function call result. */ inline bool ReadNRLinkBytes(const byte port, const byte i2caddr, byte & data[]); /** * MSIRTrain function. * Control an IR Train receiver set to the specified channel using the * mindsensors NRLink device. Valid function values are \ref TRAIN_FUNC_STOP, * \ref TRAIN_FUNC_INCR_SPEED, \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. * Valid channels are \ref TRAIN_CHANNEL_1 through \ref TRAIN_CHANNEL_3 and * \ref TRAIN_CHANNEL_ALL. The port must be configured as a Lowspeed port before * using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The IR Train channel. See \ref IRTrainChannels. * \param func The IR Train function. See \ref IRTrainFuncs * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSIRTrain(const byte port, const byte i2caddr, const byte channel, const byte func); /** * MSPFComboDirect function. * Execute a pair of Power Function motor commands on the specified channel * using the mindsensors NRLink device. Commands for outa and outb are * PF_CMD_STOP, PF_CMD_REV, PF_CMD_FWD, and \ref PF_CMD_BRAKE. Valid channels are * PF_CHANNEL_1 through PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param outa The Power Function command for output A. See \ref PFCmdConstants. * \param outb The Power Function command for output B. See \ref PFCmdConstants. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFComboDirect(const byte port, const byte i2caddr, const byte channel, const byte outa, const byte outb); /** * MSPFComboPWM function. * Control the speed of both outputs on a Power Function receiver set to the * specified channel using the mindsensors NRLink device. Valid output values * are \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param outa The Power Function PWM command for output A. See \ref PFPWMOptions. * \param outb The Power Function PWM command for output B. See \ref PFPWMOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFComboPWM(const byte port, const byte i2caddr, const byte channel, const byte outa, const byte outb); /** * MSPFRawOutput function. * Control a Power Function receiver set to the specified channel using the * mindsensors NRLink device. Build the raw data stream using the 3 nibbles * (4 bit values). The port must be configured as a Lowspeed port before using * this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param nibble0 The first raw data nibble. * \param nibble1 The second raw data nibble. * \param nibble2 The third raw data nibble. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFRawOutput(const byte port, const byte i2caddr, const byte nibble0, const byte nibble1, const byte nibble2); /** * MSPFRepeat function. * Repeat sending the last Power Function command using the mindsensors * NRLink device. Specify the number of times to repeat the command and the * number of milliseconds of delay between each repetition. The port must be * configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param count The number of times to repeat the command. * \param delay The number of milliseconds to delay between each repetition. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFRepeat(const byte port, const byte i2caddr, const byte count, const unsigned int delay); /** * MSPFSingleOutputCST function. * Control a single output on a Power Function receiver set to the specified * channel using the mindsensors NRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are \ref PF_CST_CLEAR1_CLEAR2, * \ref PF_CST_SET1_CLEAR2, \ref PF_CST_CLEAR1_SET2, \ref PF_CST_SET1_SET2, * \ref PF_CST_INCREMENT_PWM, \ref PF_CST_DECREMENT_PWM, \ref PF_CST_FULL_FWD, * \ref PF_CST_FULL_REV, and \ref PF_CST_TOGGLE_DIR. Valid channels are * \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param func The Power Function CST function. See \ref PFCSTOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFSingleOutputCST(const byte port, const byte i2caddr, const byte channel, const byte out, const byte func); /** * MSPFSingleOutputPWM function. * Control the speed of a single output on a Power Function receiver set to * the specified channel using the mindsensors NRLink device. Select the * desired output using \ref PF_OUT_A or \ref PF_OUT_B. Valid functions are * \ref PF_PWM_FLOAT, \ref PF_PWM_FWD1, \ref PF_PWM_FWD2, \ref PF_PWM_FWD3, \ref PF_PWM_FWD4, * \ref PF_PWM_FWD5, \ref PF_PWM_FWD6, \ref PF_PWM_FWD7, \ref PF_PWM_BRAKE, \ref PF_PWM_REV7, * \ref PF_PWM_REV6, \ref PF_PWM_REV5, \ref PF_PWM_REV4, \ref PF_PWM_REV3, \ref PF_PWM_REV2, and * \ref PF_PWM_REV1. Valid channels are \ref PF_CHANNEL_1 through \ref PF_CHANNEL_4. The * port must be configured as a Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param func The Power Function PWM function. See \ref PFPWMOptions. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFSingleOutputPWM(const byte port, const byte i2caddr, const byte channel, const byte out, const byte func); /** * MSPFSinglePin function. * Control a single pin on a Power Function receiver set to the specified * channel using the mindsensors NRLink device. Select the desired output * using \ref PF_OUT_A or \ref PF_OUT_B. Select the desired pin using \ref PF_PIN_C1 or * \ref PF_PIN_C2. Valid functions are \ref PF_FUNC_NOCHANGE, \ref PF_FUNC_CLEAR, * \ref PF_FUNC_SET, and \ref PF_FUNC_TOGGLE. Valid channels are \ref PF_CHANNEL_1 through * \ref PF_CHANNEL_4. Specify whether the mode by passing true (continuous) or * false (timeout) as the final parameter. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param out The Power Function output. See \ref PFOutputs. * \param pin The Power Function pin. See \ref PFPinConstants. * \param func The Power Function single pin function. See \ref PFPinFuncs. * \param cont Control whether the mode is continuous or timeout. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFSinglePin(const byte port, const byte i2caddr, const byte channel, const byte out, const byte pin, const byte func, bool cont); /** * MSPFTrain function. * Control both outputs on a Power Function receiver set to the specified * channel using the mindsensors NRLink device as if it were an IR Train * receiver. Valid function values are \ref TRAIN_FUNC_STOP, \ref TRAIN_FUNC_INCR_SPEED, * \ref TRAIN_FUNC_DECR_SPEED, and \ref TRAIN_FUNC_TOGGLE_LIGHT. Valid channels are * PF_CHANNEL_1 through PF_CHANNEL_4. The port must be configured as a * Lowspeed port before using this function. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. * \param channel The Power Function channel. See \ref PFChannelConstants. * \param func The Power Function train function. See \ref IRTrainFuncs. * \return The function call result. \ref NO_ERR or \ref CommandCommErrors. */ inline char MSPFTrain(const byte port, const byte i2caddr, const byte channel, const byte func); /** * MSRCXSetIRLinkPort function. * Set the global port in advance of using the MSRCX* and MSScout* API * functions for sending RCX and Scout messages over the mindsensors NRLink * device. The port must be configured as a Lowspeed port before using any of * the mindsensors RCX and Scout NRLink functions. * * \param port The sensor port. See \ref InPorts. * \param i2caddr The sensor I2C address. See sensor documentation for this value. */ inline void MSRCXSetNRLinkPort(const byte port, const byte i2caddr); /** * MSRCXBatteryLevel function. * Send the BatteryLevel command to an RCX to read the current battery level. * * \return The RCX battery level. */ inline int MSRCXBatteryLevel(void); /** * MSRCXPoll function. * Send the Poll command to an RCX to read a signed 2-byte value at the * specified source and value combination. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. * \return The value read from the specified port and value. */ inline int MSRCXPoll(const byte src, const byte value); /** * MSRCXPollMemory function. * Send the PollMemory command to an RCX. * * \param address The RCX memory address. * \return The value read from the specified address. */ inline int MSRCXPollMemory(const unsigned int address); /** * MSRCXAbsVar function. * Send the AbsVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXAbsVar(const byte varnum, const byte byte src, const unsigned int value); /** * MSRCXAddToDatalog function. * Send the AddToDatalog command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXAddToDatalog(const byte src, const unsigned int value); /** * MSRCXAndVar function. * Send the AndVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXAndVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXBoot function. * Send the Boot command to an RCX. */ inline void MSRCXBoot(void); /** * MSRCXCalibrateEvent function. * Send the CalibrateEvent command to an RCX. * * \param evt The event number. * \param low The low threshold. * \param hi The high threshold. * \param hyst The hysterisis value. */ inline void MSRCXCalibrateEvent(const byte evt, const byte low, const byte hi, const byte hyst); /** * MSRCXClearAllEvents function. * Send the ClearAllEvents command to an RCX. */ inline void MSRCXClearAllEvents(void); /** * MSRCXClearCounter function. * Send the ClearCounter command to an RCX. * * \param counter The counter to clear. */ inline void MSRCXClearCounter(const byte counter); /** * MSRCXClearMsg function. * Send the ClearMsg command to an RCX. */ inline void MSRCXClearMsg(void); /** * MSRCXClearSensor function. * Send the ClearSensor command to an RCX. * * \param port The RCX port number. */ inline void MSRCXClearSensor(const byte port); /** * MSRCXClearSound function. * Send the ClearSound command to an RCX. */ inline void MSRCXClearSound(void); /** * MSRCXClearTimer function. * Send the ClearTimer command to an RCX. * * \param timer The timer to clear. */ inline void MSRCXClearTimer(const byte timer); /** * MSRCXCreateDatalog function. * Send the CreateDatalog command to an RCX. * * \param size The new datalog size. */ inline void MSRCXCreateDatalog(const unsigned int size); /** * MSRCXDecCounter function. * Send the DecCounter command to an RCX. * * \param counter The counter to decrement. */ inline void MSRCXDecCounter(const byte counter); /** * MSRCXDeleteSub function. * Send the DeleteSub command to an RCX. * * \param s The subroutine number to delete. */ inline void MSRCXDeleteSub(const byte s); /** * MSRCXDeleteSubs function. * Send the DeleteSubs command to an RCX. */ inline void MSRCXDeleteSubs(void); /** * MSRCXDeleteTask function. * Send the DeleteTask command to an RCX. * * \param t The task number to delete. */ inline void MSRCXDeleteTask(const byte t); /** * MSRCXDeleteTasks function. * Send the DeleteTasks command to an RCX. */ inline void MSRCXDeleteTasks(void); /** * MSRCXDisableOutput function. * Send the DisableOutput command to an RCX. * * \param outputs The RCX output(s) to disable. See \ref RCXOutputConstants. */ inline void MSRCXDisableOutput(const byte outputs); /** * MSRCXDivVar function. * Send the DivVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXDivVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXEnableOutput function. * Send the EnableOutput command to an RCX. * * \param outputs The RCX output(s) to enable. See \ref RCXOutputConstants. */ inline void MSRCXEnableOutput(const byte outputs); /** * MSRCXEvent function. * Send the Event command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXEvent(const byte src, const unsigned int value); /** * MSRCXFloat function. * Send commands to an RCX to float the specified outputs. * * \param outputs The RCX output(s) to float. See \ref RCXOutputConstants. */ inline void MSRCXFloat(const byte outputs); /** * MSRCXFwd function. * Send commands to an RCX to set the specified outputs to the forward direction. * * \param outputs The RCX output(s) to set forward. See \ref RCXOutputConstants. */ inline void MSRCXFwd(const byte outputs); /** * MSRCXIncCounter function. * Send the IncCounter command to an RCX. * * \param counter The counter to increment. */ inline void MSRCXIncCounter(const byte counter); /** * MSRCXInvertOutput function. * Send the InvertOutput command to an RCX. * * \param outputs The RCX output(s) to invert. See \ref RCXOutputConstants. */ inline void MSRCXInvertOutput(const byte outputs); /** * MSRCXMulVar function. * Send the MulVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXMulVar(const byte varnum, const byte src, unsigned int value); /** * MSRCXMuteSound function. * Send the MuteSound command to an RCX. */ inline void MSRCXMuteSound(void); /** * MSRCXObvertOutput function. * Send the ObvertOutput command to an RCX. * * \param outputs The RCX output(s) to obvert. See \ref RCXOutputConstants. */ inline void MSRCXObvertOutput(const byte outputs); /** * MSRCXOff function. * Send commands to an RCX to turn off the specified outputs. * * \param outputs The RCX output(s) to turn off. See \ref RCXOutputConstants. */ inline void MSRCXOff(const byte outputs); /** * MSRCXOn function. * Send commands to an RCX to turn on the specified outputs. * * \param outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. */ inline void MSRCXOn(const byte outputs); /** * MSRCXOnFor function. * Send commands to an RCX to turn on the specified outputs in the forward * direction for the specified duration. * * \param outputs The RCX output(s) to turn on. See \ref RCXOutputConstants. * \param ms The number of milliseconds to leave the outputs on */ inline void MSRCXOnFor(const byte outputs, const unsigned int ms); /** * MSRCXOnFwd function. * Send commands to an RCX to turn on the specified outputs in the forward * direction. * * \param outputs The RCX output(s) to turn on in the forward direction. See \ref RCXOutputConstants. */ inline void MSRCXOnFwd(const byte outputs); /** * MSRCXOnRev function. * Send commands to an RCX to turn on the specified outputs in the reverse direction. * * \param outputs The RCX output(s) to turn on in the reverse direction. See \ref RCXOutputConstants. */ inline void MSRCXOnRev(const byte outputs); /** * MSRCXOrVar function. * Send the OrVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXOrVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXPBTurnOff function. * Send the PBTurnOff command to an RCX. */ inline void MSRCXPBTurnOff(void); /** * MSRCXPing function. * Send the Ping command to an RCX. */ inline void MSRCXPing(void); /** * MSRCXPlaySound function. * Send the PlaySound command to an RCX. * * \param snd The sound number to play. */ inline void MSRCXPlaySound(const byte snd); /** * MSRCXPlayTone function. * Send the PlayTone command to an RCX. * * \param freq The frequency of the tone to play. * \param duration The duration of the tone to play. */ inline void MSRCXPlayTone(const unsigned int freq, const byte duration); /** * MSRCXPlayToneVar function. * Send the PlayToneVar command to an RCX. * * \param varnum The variable containing the tone frequency to play. * \param duration The duration of the tone to play. */ inline void MSRCXPlayToneVar(const byte varnum, const byte duration); /** * MSRCXRemote function. * Send the Remote command to an RCX. * * \param cmd The RCX IR remote command to send. See \ref RCXRemoteConstants. */ inline void MSRCXRemote(unsigned int cmd); /** * MSRCXReset function. * Send the Reset command to an RCX. */ inline void MSRCXReset(void); /** * MSRCXRev function. * Send commands to an RCX to set the specified outputs to the reverse direction. * * \param outputs The RCX output(s) to reverse direction. See \ref RCXOutputConstants. */ inline void MSRCXRev(const byte outputs); /** * MSRCXSelectDisplay function. * Send the SelectDisplay command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSelectDisplay(const byte src, const unsigned int value); /** * MSRCXSelectProgram function. * Send the SelectProgram command to an RCX. * * \param prog The program number to select. */ inline void MSRCXSelectProgram(const byte prog); /** * MSRCXSendSerial function. * Send the SendSerial command to an RCX. * * \param first The first byte address. * \param count The number of bytes to send. */ inline void MSRCXSendSerial(const byte first, const byte count); /** * MSRCXSet function. * Send the Set command to an RCX. * * \param dstsrc The RCX destination source. See \ref RCXSourceConstants. * \param dstval The RCX destination value. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSet(const byte dstsrc, const byte dstval, const byte src, unsigned int value); /** * MSRCXSetDirection function. * Send the SetDirection command to an RCX to configure the direction of the specified outputs. * * \param outputs The RCX output(s) to set direction. See \ref RCXOutputConstants. * \param dir The RCX output direction. See \ref RCXOutputDirection. */ inline void MSRCXSetDirection(const byte outputs, const byte dir); /** * MSRCXSetEvent function. * Send the SetEvent command to an RCX. * * \param evt The event number to set. * \param src The RCX source. See \ref RCXSourceConstants. * \param type The event type. */ inline void MSRCXSetEvent(const byte evt, const byte src, const byte type); /** * MSRCXSetGlobalDirection function. * Send the SetGlobalDirection command to an RCX. * * \param outputs The RCX output(s) to set global direction. See \ref RCXOutputConstants. * \param dir The RCX output direction. See \ref RCXOutputDirection. */ inline void MSRCXSetGlobalDirection(const byte outputs, const byte dir); /** * MSRCXSetGlobalOutput function. * Send the SetGlobalOutput command to an RCX. * * \param outputs The RCX output(s) to set global mode. See \ref RCXOutputConstants. * \param mode The RCX output mode. See \ref RCXOutputMode. */ inline void MSRCXSetGlobalOutput(const byte outputs, const byte mode); /** * MSRCXSetMaxPower function. * Send the SetMaxPower command to an RCX. * * \param outputs The RCX output(s) to set max power. See \ref RCXOutputConstants. * \param pwrsrc The RCX source. See \ref RCXSourceConstants. * \param pwrval The RCX value. */ inline void MSRCXSetMaxPower(const byte outputs, const byte pwrsrc, const byte pwrval); /** * MSRCXSetMessage function. * Send the SetMessage command to an RCX. * * \param msg The numeric message to send. */ inline void MSRCXSetMessage(const byte msg); /** * MSRCXSetOutput function. * Send the SetOutput command to an RCX to configure the mode of the specified outputs * * \param outputs The RCX output(s) to set mode. See \ref RCXOutputConstants. * \param mode The RCX output mode. See \ref RCXOutputMode. */ inline void MSRCXSetOutput(const byte outputs, const byte mode); /** * MSRCXSetPower function. * Send the SetPower command to an RCX to configure the power level of the specified outputs. * * \param outputs The RCX output(s) to set power. See \ref RCXOutputConstants. * \param pwrsrc The RCX source. See \ref RCXSourceConstants. * \param pwrval The RCX value. */ inline void MSRCXSetPower(const byte outputs, const byte pwrsrc, const byte pwrval); /** * MSRCXSetPriority function. * Send the SetPriority command to an RCX. * * \param p The new task priority. */ inline void MSRCXSetPriority(const byte p); /** * MSRCXSetSensorMode function. * Send the SetSensorMode command to an RCX. * * \param port The RCX sensor port. * \param mode The RCX sensor mode. */ inline void MSRCXSetSensorMode(const byte port, const byte mode); /** * MSRCXSetSensorType function. * Send the SetSensorType command to an RCX. * * \param port The RCX sensor port. * \param type The RCX sensor type. */ inline void MSRCXSetSensorType(const byte port, const byte type); /** * MSRCXSetSleepTime function. * Send the SetSleepTime command to an RCX. * * \param t The new sleep time value. */ inline void MSRCXSetSleepTime(const byte t); /** * MSRCXSetTxPower function. * Send the SetTxPower command to an RCX. * * \param pwr The IR transmit power level. */ inline void MSRCXSetTxPower(const byte pwr); /** * MSRCXSetUserDisplay function. * Send the SetUserDisplay command to an RCX. * * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. * \param precision The number of digits of precision. */ inline void MSRCXSetUserDisplay(const byte src, const unsigned int value, const byte precision); /** * MSRCXSetVar function. * Send the SetVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSetVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXSetWatch function. * Send the SetWatch command to an RCX. * * \param hours The new watch time hours value. * \param minutes The new watch time minutes value. */ inline void MSRCXSetWatch(const byte hours, const byte minutes); /** * MSRCXSgnVar function. * Send the SgnVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSgnVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXStartTask function. * Send the StartTask command to an RCX. * * \param t The task number to start. */ inline void MSRCXStartTask(const byte t); /** * MSRCXStopAllTasks function. * Send the StopAllTasks command to an RCX. */ inline void MSRCXStopAllTasks(void); /** * MSRCXStopTask function. * Send the StopTask command to an RCX. * * \param t The task number to stop. */ inline void MSRCXStopTask(const byte t); /** * MSRCXSubVar function. * Send the SubVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSubVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXSumVar function. * Send the SumVar command to an RCX. * * \param varnum The variable number to change. * \param src The RCX source. See \ref RCXSourceConstants. * \param value The RCX value. */ inline void MSRCXSumVar(const byte varnum, const byte src, const unsigned int value); /** * MSRCXToggle function. * Send commands to an RCX to toggle the direction of the specified outputs. * * \param outputs The RCX output(s) to toggle. See \ref RCXOutputConstants. */ inline void MSRCXToggle(const byte outputs); /** * MSRCXUnlock function. * Send the Unlock command to an RCX. */ inline void MSRCXUnlock(void); /** * MSRCXUnmuteSound function. * Send the UnmuteSound command to an RCX. */ inline void MSRCXUnmuteSound(void); /** * MSScoutCalibrateSensor function. * Send the CalibrateSensor command to a Scout. */ inline void MSScoutCalibrateSensor(void); /** * MSScoutMuteSound function. * Send the MuteSound command to a Scout. */ inline void MSScoutMuteSound(void); /** * MSScoutSelectSounds function. * Send the SelectSounds command to a Scout. * * \param grp The Scout sound group to select. */ inline void MSScoutSelectSounds(const byte grp); /** * MSScoutSendVLL function. * Send the SendVLL command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSendVLL(const byte src, const unsigned int value); /** * MSScoutSetCounterLimit function. * Send the SetCounterLimit command to a Scout. * * \param ctr The counter for which to set the limit. * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetCounterLimit(const byte ctr, const byte src, const unsigned int value); /** * MSScoutSetEventFeedback function. * Send the SetEventFeedback command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetEventFeedback(const byte src, const unsigned int value); /** * MSScoutSetLight function. * Send the SetLight command to a Scout. * * \param x Set the light on or off using this value. See \ref ScoutLightConstants. */ inline void MSScoutSetLight(const byte x); /** * MSScoutSetScoutMode function. * Send the SetScoutMode command to a Scout. * * \param mode Set the scout mode. See \ref ScoutModeConstants. */ inline void MSScoutSetScoutMode(const byte mode); /** * MSScoutSetScoutRules function. * Send the SetScoutRules command to a Scout. * * \param m Scout motion rule. See \ref ScoutMotionRuleConstants. * \param t Scout touch rule. See \ref ScoutTouchRuleConstants. * \param l Scout light rule. See \ref ScoutLightRuleConstants. * \param tm Scout transmit rule. See \ref ScoutTransmitRuleConstants. * \param fx Scout special effects rule. See \ref ScoutSpecialEffectConstants. */ inline void MSScoutSetScoutRules(const byte m, const byte t, const byte l, const byte tm, const byte fx); /** * MSScoutSetSensorClickTime function. * Send the SetSensorClickTime command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetSensorClickTime(const byte src, const unsigned int value); /** * MSScoutSetSensorHysteresis function. * Send the SetSensorHysteresis command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetSensorHysteresis(const byte src, const unsigned int value); /** * MSScoutSetSensorLowerLimit function. * Send the SetSensorLowerLimit command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetSensorLowerLimit(const byte src, const unsigned int value); /** * MSScoutSetSensorUpperLimit function. * Send the SetSensorUpperLimit command to a Scout. * * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetSensorUpperLimit(const byte src, const unsigned int value); /** * MSScoutSetTimerLimit function. * Send the SetTimerLimit command to a Scout. * * \param tmr The timer for which to set a limit. * \param src The Scout source. See \ref RCXSourceConstants. * \param value The Scout value. */ inline void MSScoutSetTimerLimit(const byte tmr, const byte src, const unsigned int value); /** * MSScoutUnmuteSound function. * Send the UnmuteSound command to a Scout. */ inline void MSScoutUnmuteSound(void); #else #define SensorMSDROD(_p) asm { getin __RETVAL__, _p, NormalizedValueField } #define SensorNXTSumoEyesRaw(_p) asm { getin __RETVAL__, _p, NormalizedValueField } #define SensorMSPressureRaw(_p) asm { getin __RETVAL__, _p, RawValueField } #define SensorMSCompass(_port, _i2caddr) asm { ReadSensorMSCompass(_port, _i2caddr, __RETVAL__) } #define ReadSensorMSRTClock(_port, _sec, _min, _hrs, _dow, _date, _month, _year) asm { __ReadSensorMSRTClock(_port, _sec, _min, _hrs, _dow, _date, _month, _year, __RETVAL__) } #define ReadSensorMSTilt(_port, _i2caddr, _x, _y, _z) asm { __ReadSensorMSTilt(_port, _i2caddr, _x, _y, _z, __RETVAL__) } #define ReadSensorMSAccel(_port, _i2caddr, _x, _y, _z) asm { __ReadSensorMSAccel(_port, _i2caddr, _x, _y, _z, __RETVAL__) } #define MSReadValue(_port, _i2caddr, _reg, _bytes) asm { __MSReadValue(_port, _i2caddr, _reg, _bytes, __RETVAL__, __TMPBYTE__) } #define MSEnergize(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, MS_CMD_ENERGIZED, __RETVAL__) } #define MSDeenergize(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, MS_CMD_DEENERGIZED, __RETVAL__) } #define MSADPAOn(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, MS_CMD_ADPA_ON, __RETVAL__) } #define MSADPAOff(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, MS_CMD_ADPA_OFF, __RETVAL__) } #define DISTNxGP2D12(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2D12, __RETVAL__) } #define DISTNxGP2D120(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2D120, __RETVAL__) } #define DISTNxGP2YA21(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2YA21, __RETVAL__) } #define DISTNxGP2YA02(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, DIST_CMD_GP2YA02, __RETVAL__) } #define DISTNxDistance(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_DIST, 2, __RETVAL__, __TMPBYTE__) } #define DISTNxVoltage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_VOLT, 2, __RETVAL__, __TMPBYTE__) } #define DISTNxModuleType(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_MODULE_TYPE, 1, __RETVAL__, __TMPBYTE__) } #define DISTNxNumPoints(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_NUM_POINTS, 1, __RETVAL__, __TMPBYTE__) } #define DISTNxMinDistance(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_DIST_MIN, 2, __RETVAL__, __TMPBYTE__) } #define DISTNxMaxDistance(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, DIST_REG_DIST_MAX, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxCalibrateX(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_X_CAL, __RETVAL__) } #define ACCLNxCalibrateXEnd(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_X_CAL_END, __RETVAL__) } #define ACCLNxCalibrateY(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Y_CAL, __RETVAL__) } #define ACCLNxCalibrateYEnd(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Y_CAL_END, __RETVAL__) } #define ACCLNxCalibrateZ(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Z_CAL, __RETVAL__) } #define ACCLNxCalibrateZEnd(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_Z_CAL_END, __RETVAL__) } #define ACCLNxResetCalibration(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, ACCL_CMD_RESET_CAL, __RETVAL__) } #define SetACCLNxSensitivity(_port, _i2caddr, _slevel) asm { __I2CSendCmd(_port, _i2caddr, _slevel, __RETVAL__) } #define ACCLNxSensitivity(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_sENS_LVL, 1, __RETVAL__, __TMPBYTE__) } #define ACCLNxXOffset(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_X_OFFSET, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxXRange(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_X_RANGE, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxYOffset(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_Y_OFFSET, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxYRange(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_Y_RANGE, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxZOffset(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_Z_OFFSET, 2, __RETVAL__, __TMPBYTE__) } #define ACCLNxZRange(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, ACCL_REG_Z_RANGE, 2, __RETVAL__, __TMPBYTE__) } #define PFMateSend(_port, _i2caddr, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB) asm { __PFMateSend(_port, _i2caddr, _channel, _motors, _cmdA, _spdA, _cmdB, _spdB, __RETVAL__) } #define PFMateSendRaw(_port, _i2caddr, _channel, _b1, _b2) asm { __PFMateSendRaw(_port, _i2caddr, _channel, _b1, _b2, __RETVAL__) } #define NXTServoPosition(_port, _i2caddr, _servo) asm { __MSReadValue(_port, _i2caddr, NXTSERVO_REG_S1_POS+(_servo*2), 2, __RETVAL__, __TMPBYTE__) } #define NXTServoSpeed(_port, _i2caddr, _servo) asm { __MSReadValue(_port, _i2caddr, NXTSERVO_REG_S1_SPEED+_servo, 1, __RETVAL__, __TMPBYTE__) } #define NXTServoBatteryVoltage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTSERVO_REG_VOLTAGE, 1, __RETVAL__, __TMPBYTE__) } #define SetNXTServoSpeed(_port, _i2caddr, _servo, _speed) asm { __MSWriteToRegister(_port, _i2caddr, NXTSERVO_REG_S1_SPEED+_servo, _speed, __RETVAL__) } #define SetNXTServoQuickPosition(_port, _i2caddr, _servo, _qpos) asm { __MSWriteToRegister(_port, _i2caddr, NXTSERVO_REG_S1_QPOS+_servo, _qpos, __RETVAL__) } #define SetNXTServoPosition(_port, _i2caddr, _servo, _pos) asm { __MSWriteLEIntToRegister(_port, _i2caddr, NXTSERVO_REG_S1_POS+(_servo*2), _pos, __RETVAL__) } #define NXTServoReset(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_RESET, __RETVAL__) } #define NXTServoHaltMacro(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_HALT, __RETVAL__) } #define NXTServoResumeMacro(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_RESUME, __RETVAL__) } #define NXTServoPauseMacro(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTSERVO_CMD_PAUSE, __RETVAL__) } #define NXTServoInit(_port, _i2caddr, _servo) asm { __NXTServoInit(_port, _i2caddr, _servo, __RETVAL__) } #define NXTServoGotoMacroAddress(_port, _i2caddr, _macro) asm { __NXTServoGotoMacroAddress(_port, _i2caddr, _macro, __RETVAL__) } #define NXTServoEditMacro(_port, _i2caddr) asm { __NXTServoEditMacro(_port, _i2caddr, __RETVAL__) } #define NXTServoQuitEdit(_port) asm { __MSWriteToRegister(_port, MS_ADDR_NXTSERVO_EM, NXTSERVO_EM_REG_CMD, NXTSERVO_EM_CMD_QUIT, __RETVAL__) } #define NXTHIDAsciiMode(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_ASCII, __RETVAL__) } #define NXTHIDDirectMode(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_DIRECT, __RETVAL__) } #define NXTHIDTransmit(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTHID_CMD_TRANSMIT, __RETVAL__) } #define NXTHIDLoadCharacter(_port, _i2caddr, _modifier, _character) asm { __NXTHIDLoadCharacter(_port, _i2caddr, _modifier, _character, __RETVAL__) } #define NXTPowerMeterResetCounters(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTPM_CMD_RESET, __RETVAL__) } #define NXTPowerMeterPresentCurrent(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_CURRENT, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterPresentVoltage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_VOLTAGE, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterCapacityUsed(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_CAPACITY, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterPresentPower(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_POWER, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterTotalPowerConsumed(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_POWER, 4, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterMaxCurrent(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_MAXCURRENT, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterMinCurrent(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_MINCURRENT, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterMaxVoltage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_MAXVOLTAGE, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterMinVoltage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_MINVOLTAGE, 2, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterElapsedTime(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_TIME, 4, __RETVAL__, __TMPBYTE__) } #define NXTPowerMeterErrorCount(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTPM_REG_ERRORCOUNT, 2, __RETVAL__, __TMPBYTE__) } #define NXTLineLeaderSteering(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTLL_REG_STEERING, 1, __RETVAL__, __TMPBYTE__) } #define NXTLineLeaderAverage(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTLL_REG_AVERAGE, 1, __RETVAL__, __TMPBYTE__) } #define NXTLineLeaderResult(_port, _i2caddr) asm { __MSReadValue(_port, _i2caddr, NXTLL_REG_RESULT, 1, __RETVAL__, __TMPBYTE__) } #define NXTLineLeaderPowerDown(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_POWERDOWN, __RETVAL__) } #define NXTLineLeaderPowerUp(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_POWERUP, __RETVAL__) } #define NXTLineLeaderInvert(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_INVERT, __RETVAL__) } #define NXTLineLeaderReset(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_RESET, __RETVAL__) } #define NXTLineLeaderSnapshot(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_SNAPSHOT, __RETVAL__) } #define NXTLineLeaderCalibrateWhite(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_WHITE, __RETVAL__) } #define NXTLineLeaderCalibrateBlack(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NXTLL_CMD_BLACK, __RETVAL__) } #define SetNXTLineLeaderSetpoint(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_SETPOINT, _value, __RETVAL__) } #define SetNXTLineLeaderKpValue(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KP_VALUE, _value, __RETVAL__) } #define SetNXTLineLeaderKiValue(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KI_VALUE, _value, __RETVAL__) } #define SetNXTLineLeaderKdValue(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KD_VALUE, _value, __RETVAL__) } #define SetNXTLineLeaderKpFactor(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KP_FACTOR, _value, __RETVAL__) } #define SetNXTLineLeaderKiFactor(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KI_FACTOR, _value, __RETVAL__) } #define SetNXTLineLeaderKdFactor(_port, _i2caddr, _value) asm { __MSWriteToRegister(_port, _i2caddr, NXTLL_REG_KD_FACTOR, _value, __RETVAL__) } #define PSPNxDigital(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, PSP_CMD_DIGITAL, __RETVAL__) } #define PSPNxAnalog(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, PSP_CMD_ANALOG, __RETVAL__) } #define ReadSensorMSPlayStation(_port, _i2caddr, _b1, _b2, _xleft, _yleft, _xright, _yright) asm { __ReadSensorMSPlayStation(_port, _i2caddr, _b1, _b2, _xleft, _yleft, _xright, _yright, __RETVAL__) } #define NRLink2400(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_2400, __RETVAL__) } #define NRLink4800(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_4800, __RETVAL__) } #define NRLinkFlush(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_FLUSH, __RETVAL__) } #define NRLinkIRLong(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_IR_LONG, __RETVAL__) } #define NRLinkIRShort(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_IR_SHORT, __RETVAL__) } #define NRLinkTxRaw(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_TX_RAW, __RETVAL__) } #define NRLinkSetRCX(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_RCX, __RETVAL__) } #define NRLinkSetTrain(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_TRAIN, __RETVAL__) } #define NRLinkSetPF(_port, _i2caddr) asm { __I2CSendCmd(_port, _i2caddr, NRLINK_CMD_SET_PF, __RETVAL__) } #define RunNRLinkMacro(_port, _i2caddr, _macro) asm { __RunNRLinkMacro(_port, _i2caddr, _macro, __RETVAL__) } #define NRLinkStatus(_port, _i2caddr) asm { ReadNRLinkStatus(_port, _i2caddr, __RETVAL__, __TMPBYTE__) } #define WriteNRLinkBytes(_port, _i2caddr, _bytes) asm { __WriteNRLinkBytes(_port, _i2caddr, _bytes, __RETVAL__) } #define ReadNRLinkBytes(_port, _i2caddr, _bytes) asm { __ReadNRLinkBytes(_port, _i2caddr, _bytes, __RETVAL__) } #define MSPFComboDirect(_port, _i2caddr, _channel, _outa, _outb) asm { __MSPFComboDirect(_port, _i2caddr, _channel, _outa, _outb, __RETVAL__) } #define MSPFSinglePin(_port, _i2caddr, _channel, _out, _pin, _func, _cont) asm { __MSPFSinglePin(_port, _i2caddr, _channel, _out, _pin, _func, _cont, __RETVAL__) } #define MSPFSingleOutputCST(_port, _i2caddr, _channel, _out, _func) asm { __MSPFSingleOutput(_port, _i2caddr, _channel, _out, _func, TRUE, __RETVAL__) } #define MSPFSingleOutputPWM(_port, _i2caddr, _channel, _out, _func) asm { __MSPFSingleOutput(_port, _i2caddr, _channel, _out, _func, FALSE, __RETVAL__) } #define MSPFComboPWM(_port, _i2caddr, _channel, _outa, _outb) asm { __MSPFComboPWM(_port, _i2caddr, _channel, _outa, _outb, __RETVAL__) } #define MSPFTrain(_port, _i2caddr, _channel, _func) asm { __MSIRTrain(_port, _i2caddr, _channel, _func, TRUE, __RETVAL__) } #define MSIRTrain(_port, _i2caddr, _channel, _func) asm { __MSIRTrain(_port, _i2caddr, _channel, _func, FALSE, __RETVAL__) } #define MSPFRawOutput(_port, _i2caddr, _nibble0, _nibble1, _nibble2) asm { __MSPFRawOutput(_port, _i2caddr, _nibble0, _nibble1, _nibble2, __RETVAL__) } #define MSPFRepeat(_port, _i2caddr, _count, _delay) asm { __MSPFRepeatLastCommand(_port, _i2caddr, _count, _delay, __RETVAL__) } #define MSRCXSetNRLinkPort(_port, _i2caddr) asm { __MSRCXSetNRLink(_port, _i2caddr) } #define MSRCXPoll(_src, _value) asm { __MSRCXPoll(_src, _value, __RETVAL__) } #define MSRCXBatteryLevel() asm { __MSRCXBatteryLevel(__RETVAL__) } #define MSRCXPing() asm { __MSRCXOpNoArgs(RCX_PingOp) } #define MSRCXDeleteTasks() asm { __MSRCXOpNoArgs(RCX_DeleteTasksOp) } #define MSRCXStopAllTasks() asm { __MSRCXOpNoArgs(RCX_StopAllTasksOp) } #define MSRCXPBTurnOff() asm { __MSRCXOpNoArgs(RCX_PBTurnOffOp) } #define MSRCXDeleteSubs() asm { __MSRCXOpNoArgs(RCX_DeleteSubsOp) } #define MSRCXClearSound() asm { __MSRCXOpNoArgs(RCX_ClearSoundOp) } #define MSRCXClearMsg() asm { __MSRCXOpNoArgs(RCX_ClearMsgOp) } #define MSRCXMuteSound() asm { __MSRCXOpNoArgs(RCX_MuteSoundOp) } #define MSRCXUnmuteSound() asm { __MSRCXOpNoArgs(RCX_UnmuteSoundOp) } #define MSRCXClearAllEvents() asm { __MSRCXOpNoArgs(RCX_ClearAllEventsOp) } #define MSRCXSetOutput(_outputs, _mode) asm { __MSRCXSetOutput(_outputs, _mode) } #define MSRCXSetDirection(_outputs, _dir) asm { __MSRCXSetDirection(_outputs, _dir) } #define MSRCXSetPower(_outputs, _pwrsrc, _pwrval) asm { __MSRCXSetPower(_outputs, _pwrsrc, _pwrval) } #define MSRCXOn(_outputs) asm { __MSRCXSetOutput(_outputs, RCX_OUT_ON) } #define MSRCXOff(_outputs) asm { __MSRCXSetOutput(_outputs, RCX_OUT_OFF) } #define MSRCXFloat(_outputs) asm { __MSRCXSetOutput(_outputs, RCX_OUT_FLOAT) } #define MSRCXToggle(_outputs) asm { __MSRCXSetDirection(_outputs, RCX_OUT_TOGGLE) } #define MSRCXFwd(_outputs) asm { __MSRCXSetDirection(_outputs, RCX_OUT_FWD) } #define MSRCXRev(_outputs) asm { __MSRCXSetDirection(_outputs, RCX_OUT_REV) } #define MSRCXOnFwd(_outputs) asm { __MSRCXOnFwd(_outputs) } #define MSRCXOnRev(_outputs) asm { __MSRCXOnRev(_outputs) } #define MSRCXOnFor(_outputs, _ms) asm { __MSRCXOnFor(_outputs, _ms) } #define MSRCXSetTxPower(_pwr) asm { __MSRCXSetTxPower(_pwr) } #define MSRCXPlaySound(_snd) asm { __MSRCXPlaySound(_snd) } #define MSRCXDeleteTask(_t) asm { __MSRCXDeleteTask(_t) } #define MSRCXStartTask(_t) asm { __MSRCXStartTask(_t) } #define MSRCXStopTask(_t) asm { __MSRCXStopTask(_t) } #define MSRCXSelectProgram(_prog) asm { __MSRCXSelectProgram(_prog) } #define MSRCXClearTimer(_timer) asm { __MSRCXClearTimer(_timer) } #define MSRCXSetSleepTime(_t) asm { __MSRCXSetSleepTime(_t) } #define MSRCXDeleteSub(_s) asm { __MSRCXDeleteSub(_s) } #define MSRCXClearSensor(_port) asm { __MSRCXClearSensor(_port) } #define MSRCXPlayToneVar(_varnum, _duration) asm { __MSRCXPlayToneVar(_varnum, _duration) } #define MSRCXSetWatch(_hours, _minutes) asm { __MSRCXSetWatch(_hours, _minutes) } #define MSRCXSetSensorType(_port, _type) asm { __MSRCXSetSensorType(_port, _type) } #define MSRCXSetSensorMode(_port, _mode) asm { __MSRCXSetSensorMode(_port, _mode) } #define MSRCXCreateDatalog(_size) asm { __MSRCXCreateDatalog(_size) } #define MSRCXAddToDatalog(_src, _value) asm { __MSRCXAddToDatalog(_src, _value) } #define MSRCXSendSerial(_first, _count) asm { __MSRCXSendSerial(_first, _count) } #define MSRCXRemote(_cmd) asm { __MSRCXRemote(_cmd) } #define MSRCXEvent(_src, _value) asm { __MSRCXEvent(_src, _value) } #define MSRCXPlayTone(_freq, _duration) asm { __MSRCXPlayTone(_freq, _duration) } #define MSRCXSelectDisplay(_src, _value) asm { __MSRCXSelectDisplay(_src, _value) } #define MSRCXPollMemory(_memaddress) asm { __MSRCXPollMemory(_memaddress, __RETVAL__) } #define MSRCXSetEvent(_evt, _src, _type) asm { __MSRCXSetEvent(_evt, _src, _type) } #define MSRCXSetGlobalOutput(_outputs, _mode) asm { __MSRCXSetGlobalOutput(_outputs, _mode) } #define MSRCXSetGlobalDirection(_outputs, _dir) asm { __MSRCXSetGlobalDirection(_outputs, _dir) } #define MSRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) asm { __MSRCXSetMaxPower(_outputs, _pwrsrc, _pwrval) } #define MSRCXEnableOutput(_outputs) asm { __MSRCXSetGlobalOutput(_outputs, RCX_OUT_ON) } #define MSRCXDisableOutput(_outputs) asm { __MSRCXSetGlobalOutput(_outputs, RCX_OUT_OFF) } #define MSRCXInvertOutput(_outputs) asm { __MSRCXSetGlobalDirection(_outputs, RCX_OUT_REV) } #define MSRCXObvertOutput(_outputs) asm { __MSRCXSetGlobalDirection(_outputs, RCX_OUT_FWD) } #define MSRCXCalibrateEvent(_evt, _low, _hi, _hyst) asm { __MSRCXCalibrateEvent(_evt, _low, _hi, _hyst) } #define MSRCXSetVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_SetVarOp, _varnum, _src, _value) } #define MSRCXSumVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_SumVarOp, _varnum, _src, _value) } #define MSRCXSubVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_SubVarOp, _varnum, _src, _value) } #define MSRCXDivVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_DivVarOp, _varnum, _src, _value) } #define MSRCXMulVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_MulVarOp, _varnum, _src, _value) } #define MSRCXSgnVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_SgnVarOp, _varnum, _src, _value) } #define MSRCXAbsVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_AbsVarOp, _varnum, _src, _value) } #define MSRCXAndVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_AndVarOp, _varnum, _src, _value) } #define MSRCXOrVar(_varnum, _src, _value) asm { __MSRCXVarOp(RCX_OrVarOp, _varnum, _src, _value) } #define MSRCXSet(_dstsrc, _dstval, _src, _value) asm { __MSRCXSet(_dstsrc, _dstval, _src, _value) } #define MSRCXUnlock() asm { __MSRCXUnlock() } #define MSRCXReset() asm { __MSRCXReset() } #define MSRCXBoot() asm { __MSRCXBoot() } #define MSRCXSetUserDisplay(_src, _value, _precision) asm { __MSRCXSetUserDisplay(_src, _value, _precision) } #define MSRCXIncCounter(_counter) asm { __MSRCXIncCounter(_counter) } #define MSRCXDecCounter(_counter) asm { __MSRCXDecCounter(_counter) } #define MSRCXClearCounter(_counter) asm { __MSRCXClearCounter(_counter) } #define MSRCXSetPriority(_p) asm { __MSRCXSetPriority(_p) } #define MSRCXSetMessage(_msg) asm { __MSRCXSetMessage(_msg) } #define MSScoutCalibrateSensor() asm { __MSRCXOpNoArgs(RCX_LSCalibrateOp) } #define MSScoutMuteSound() asm { __MSScoutMuteSound() } #define MSScoutUnmuteSound() asm { __MSScoutUnmuteSound() } #define MSScoutSelectSounds(_grp) asm { __MSScoutSelectSounds(_grp) } #define MSScoutSetLight(_x) asm { __MSScoutSetLight(_x) } #define MSScoutSetCounterLimit(_ctr, _src, _value) asm { __MSScoutSetCounterLimit(_ctr, _src, _value) } #define MSScoutSetTimerLimit(_tmr, _src, _value) asm { __MSScoutSetTimerLimit(_tmr, _src, _value) } #define MSScoutSetSensorClickTime(_src, _value) asm { __MSScoutSetSensorClickTime(_src, _value) } #define MSScoutSetSensorHysteresis(_src, _value) asm { __MSScoutSetSensorHysteresis(_src, _value) } #define MSScoutSetSensorLowerLimit(_src, _value) asm { __MSScoutSetSensorLowerLimit(_src, _value) } #define MSScoutSetSensorUpperLimit(_src, _value) asm { __MSScoutSetSensorUpperLimit(_src, _value) } #define MSScoutSetEventFeedback(_src, _value) asm { __MSScoutSetEventFeedback(_src, _value) } #define MSScoutSendVLL(_src, _value) asm { __MSScoutSendVLL(_src, _value) } #define MSScoutSetScoutRules(_m, _t, _l, _tm, _fx) asm { __MSScoutSetScoutRules(_m, _t, _l, _tm, _fx) } #define MSScoutSetScoutMode(_mode) asm { __MSScoutSetScoutMode(_mode) } #endif /** @} */ // end of MindSensorsAPI group /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Codatex API /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @addtogroup CodatexAPI * @{ */ #ifdef __DOXYGEN_DOCS /** * RFIDInit function. * Initialize the Codatex RFID sensor. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \return The boolean function call result. */ inline bool RFIDInit(const byte & port); /** * RFIDMode function. * Configure the Codatex RFID sensor mode. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param mode The RFID sensor mode. See the \ref CTRFIDModeConstants group. * \return The boolean function call result. */ inline bool RFIDMode(const byte & port, const byte & mode); /** * RFIDStatus function. * Read the Codatex RFID sensor status. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \return The RFID sensor status. */ inline byte RFIDStatus(const byte & port); /** * RFIDRead function. * Read the Codatex RFID sensor value. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param output The five bytes of RFID data. * \return The boolean function call result. */ inline bool RFIDRead(const byte & port, byte & output[]); /** * RFIDStop function. * Stop the Codatex RFID sensor. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \return The boolean function call result. */ inline bool RFIDStop(const byte & port); /** * RFIDReadSingle function. * Set the Codatex RFID sensor into single mode and read the RFID data. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param output The five bytes of RFID data. * \return The boolean function call result. */ inline bool RFIDReadSingle(const byte & port, byte & output[]); /** * RFIDReadContinuous function. * Set the Codatex RFID sensor into continuous mode, if necessary, and read * the RFID data. * * \param port The port to which the Codatex RFID sensor is attached. See the * \ref InPorts group. You may use a constant or a variable. * \param output The five bytes of RFID data. * \return The boolean function call result. */ inline bool RFIDReadContinuous(const byte & port, byte & output[]); #else #define RFIDInit(_port) asm { __RFIDInit(_port, __RETVAL__) } #define RFIDMode(_port, _mode) asm { __RFIDMode(_port, _mode, __RETVAL__) } #define RFIDStatus(_port) asm { __RFIDStatus(_port, __RETVAL__) } #define RFIDRead(_port, _output) asm { __RFIDRead(_port, _output, __RETVAL__) } #define RFIDStop(_port) asm { __RFIDStop(_port, __RETVAL__) } #define RFIDReadSingle(_port, _output) asm { __RFIDReadSingle(_port, _output, __RETVAL__) } #define RFIDReadContinuous(_port, _output) asm { __RFIDReadContinuous(_port, _output, __RETVAL__) } #endif /** @} */ // end of CodatexAPI group /** @} */ // end of ThirdPartyDevices group /** @addtogroup StandardCAPIFunctions * @{ */ /////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// cmath API ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @defgroup cmathAPI cmath API * Standard C cmath API functions. * @{ */ #if __FIRMWARE_VERSION > 107 /** * Compute square root. * Computes the square root of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use sqrt() instead. * \param _X Floating point value. * \return Square root of _X. */ #define Sqrt(_X) asm { sqrt __FLTRETVAL__, _X } /** * Compute square root. * Computes the square root of x. * * \param x Floating point value. * \return Square root of x. */ inline float sqrt(float x) { asm { sqrt __FLTRETVAL__, x } } #ifdef __ENHANCED_FIRMWARE /** * Compute sine. * Computes the sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use sin() instead. * \param _X Floating point value. * \return Sine of _X. */ #define Sin(_X) asm { sin __FLTRETVAL__, _X } /** * Compute cosine. * Computes the cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use cos() instead. * \param _X Floating point value. * \return Cosine of _X. */ #define Cos(_X) asm { cos __FLTRETVAL__, _X } /** * Compute arc sine. * Computes the arc sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use asin() instead. * \param _X Floating point value. * \return Arc sine of _X. */ #define Asin(_X) asm { asin __FLTRETVAL__, _X } /** * Compute arc cosine. * Computes the arc cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use acos() instead. * \param _X Floating point value. * \return Arc cosine of _X. */ #define Acos(_X) asm { acos __FLTRETVAL__, _X } /** * Compute arc tangent. * Computes the arc tangent of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use atan() instead. * \param _X Floating point value. * \return Arc tangent of _X. */ #define Atan(_X) asm { atan __FLTRETVAL__, _X } /** * Round up value. * Computes the smallest integral value that is not less than _X. * Only constants or variables allowed (no expressions). * * \deprecated Use ceil() instead. * \param _X Floating point value. * \return The smallest integral value not less than _X. */ #define Ceil(_X) asm { ceil __FLTRETVAL__, _X } /** * Compute exponential function . * Computes the base-e exponential function of _X, which is the e number * raised to the power _X. Only constants or variables allowed * (no expressions). * * \deprecated Use exp() instead. * \param _X Floating point value. * \return Exponential value of _X. */ #define Exp(_X) asm { exp __FLTRETVAL__, _X } /** * Round down value. * Computes the largest integral value that is not greater than _X. * Only constants or variables allowed (no expressions). * * \deprecated Use floor() instead. * \param _X Floating point value. * \return The largest integral value not greater than _X. */ #define Floor(_X) asm { floor __FLTRETVAL__, _X } /** * Compute tangent. * Computes the tangent of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use tan() instead. * \param _X Floating point value. * \return Tangent of _X. */ #define Tan(_X) asm { tan __FLTRETVAL__, _X } /** * Compute hyperbolic tangent. * Computes the hyperbolic tangent of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use tanh() instead. * \param _X Floating point value. * \return Hyperbolic tangent of _X. */ #define Tanh(_X) asm { tanh __FLTRETVAL__, _X } /** * Compute hyperbolic cosine. * Computes the hyperbolic cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use cosh() instead. * \param _X Floating point value. * \return Hyperbolic cosine of _X. */ #define Cosh(_X) asm { cosh __FLTRETVAL__, _X } /** * Compute hyperbolic sine. * Computes the hyperbolic sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use sinh() instead. * \param _X Floating point value. * \return Hyperbolic sine of _X. */ #define Sinh(_X) asm { sinh __FLTRETVAL__, _X } /** * Compute natural logarithm. * Computes the natural logarithm of _X. The natural logarithm is the base-e * logarithm, the inverse of the natural exponential function (exp). For * base-10 logarithms, a specific function Log10() exists. * Only constants or variables allowed (no expressions). * * \deprecated Use log() instead. * \param _X Floating point value. * \return Natural logarithm of _X. */ #define Log(_X) asm { log __FLTRETVAL__, _X } /** * Compute common logarithm. * Computes the common logarithm of _X. The common logarithm is the base-10 * logarithm. For base-e logarithms, a specific function Log() exists. * Only constants or variables allowed (no expressions). * * \deprecated Use log10() instead. * \param _X Floating point value. * \return Common logarithm of _X. */ #define Log10(_X) asm { log10 __FLTRETVAL__, _X } /** * Compute arc tangent with 2 parameters. * Computes the principal value of the arc tangent of _Y/_X, expressed in * radians. To compute the value, the function uses the sign of both arguments * to determine the quadrant. * Only constants or variables allowed (no expressions). * * \deprecated Use atan2() instead. * \param _Y Floating point value representing a y coordinate. * \param _X Floating point value representing an x coordinate. * \return Arc tangent of _Y/_X, in the interval [-pi,+pi] radians. */ #define Atan2(_Y,_X) asm { atan2 __FLTRETVAL__, _Y, _X } /** * Raise to power. * Computes _Base raised to the power _Exponent. * Only constants or variables allowed (no expressions). * * \deprecated Use pow() instead. * \param _Base Floating point value. * \param _Exponent Floating point value. * \return The result of raising _Base to the power _Exponent. */ #define Pow(_Base,_Exponent) asm { pow __FLTRETVAL__, _Base, _Exponent } /** * Compute integral part. * Computes the integral part of _X. * Only constants or variables allowed (no expressions). * * \deprecated Use trunc() instead. * \param _X Floating point value. * \return Integral part of _X. */ #define Trunc(_X) asm { trunc __RETVAL__, _X } /** * Compute fractional part. * Computes the fractional part of _X. * Only constants or variables allowed (no expressions). * * \deprecated Use frac() instead. * \param _X Floating point value. * \return Fractional part of _X. */ #define Frac(_X) asm { frac __FLTRETVAL__, _X } /** * Multiply and divide. * Multiplies two 32-bit values and then divides the 64-bit result by a third * 32-bit value. * Only constants or variables allowed (no expressions). * * \deprecated Use muldiv32() instead. * \param _A 32-bit long value. * \param _B 32-bit long value. * \param _C 32-bit long value. * \return The result of multiplying _A times _B and dividing by _C. */ #define MulDiv32(_A,_B,_C) asm { muldiv __RETVAL__, _A, _B, _C } /** * Compute sine (degrees). * Computes the sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use sind() instead. * \param _X Floating point value. * \return Sine of _X. */ #define SinD(_X) asm { sind __FLTRETVAL__, _X } /** * Compute cosine (degrees). * Computes the cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use cosd() instead. * \param _X Floating point value. * \return Cosine of _X. */ #define CosD(_X) asm { cosd __FLTRETVAL__, _X } /** * Compute arch sine (degrees). * Computes the arc sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use asind() instead. * \param _X Floating point value. * \return Arc sine of _X. */ #define AsinD(_X) asm { asind __FLTRETVAL__, _X } /** * Compute arc cosine (degrees). * Computes the arc cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use acosd() instead. * \param _X Floating point value. * \return Arc cosine of _X. */ #define AcosD(_X) asm { acosd __FLTRETVAL__, _X } /** * Compute arc tangent (degrees). * Computes the arc tangent of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use atand() instead. * \param _X Floating point value. * \return Arc tangent of _X. */ #define AtanD(_X) asm { atand __FLTRETVAL__, _X } /** * Compute tangent (degrees). * Computes the sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use tand() instead. * \param _X Floating point value. * \return Tangent of _X. */ #define TanD(_X) asm { tand __FLTRETVAL__, _X } /** * Compute hyperbolic tangent (degrees). * Computes the hyperbolic tangent of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use tanhd() instead. * \param _X Floating point value. * \return Hyperbolic tangent of _X. */ #define TanhD(_X) asm { tanhd __FLTRETVAL__, _X } /** * Compute hyperbolic cosine (degrees). * Computes the hyperbolic cosine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use coshd() instead. * \param _X Floating point value. * \return Hyperbolic cosine of _X. */ #define CoshD(_X) asm { coshd __FLTRETVAL__, _X } /** * Compute hyperbolic sine (degrees). * Computes the hyperbolic sine of _X. Only constants or variables allowed * (no expressions). * * \deprecated Use sinhd() instead. * \param _X Floating point value. * \return Hyperbolic sine of _X. */ #define SinhD(_X) asm { sinhd __FLTRETVAL__, _X } /** * Compute arc tangent with two parameters (degrees). * Computes the arc tangent of _Y/_X. Only constants or variables allowed * (no expressions). * * \deprecated Use atan2d() instead. * \param _Y Floating point value. * \param _X Floating point value. * \return Arc tangent of _Y/_X, in the interval [-180,+180] degrees. */ #define Atan2D(_Y,_X) asm { atan2d __FLTRETVAL__, _Y, _X } /** * Compute cosine. * Computes the cosine of an angle of x radians. * * \param x Floating point value representing an angle expressed in radians. * \return Cosine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float cos(float x) { asm { cos __FLTRETVAL__, x } } /** * Compute sine. * Computes the sine of an angle of x radians. * * \param x Floating point value representing an angle expressed in radians. * \return Sine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float sin(float x) { asm { sin __FLTRETVAL__, x } } /** * Compute tangent. * Computes the tangent of an angle of x radians. * * \param x Floating point value representing an angle expressed in radians. * \return Tangent of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float tan(float x) { asm { tan __FLTRETVAL__, x } } /** * Compute arc cosine. * Computes the principal value of the arc cosine of x, expressed in radians. * In trigonometrics, arc cosine is the inverse operation of cosine. * * \param x Floating point value in the interval [-1,+1]. * \return Arc cosine of x, in the interval [0,pi] radians. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float acos(float x) { asm { acos __FLTRETVAL__, x } } /** * Compute arc sine. * Computes the principal value of the arc sine of x, expressed in radians. * In trigonometrics, arc sine is the inverse operation of sine. * * \param x Floating point value in the interval [-1,+1]. * \return Arc sine of x, in the interval [-pi/2,+pi/2] radians. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float asin(float x) { asm { asin __FLTRETVAL__, x } } /** * Compute arc tangent. * Computes the principal value of the arc tangent of x, expressed in radians. * In trigonometrics, arc tangent is the inverse operation of tangent. Notice * that because of the sign ambiguity, a function cannot determine with * certainty in which quadrant the angle falls only by its tangent value. * You can use atan2() if you need to determine the quadrant. * * \sa atan2() * \param x Floating point value. * \return Arc tangent of x, in the interval [-pi/2,+pi/2] radians. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float atan(float x) { asm { atan __FLTRETVAL__, x } } /** * Compute arc tangent with 2 parameters. * Computes the principal value of the arc tangent of y/x, expressed in * radians. To compute the value, the function uses the sign of both arguments * to determine the quadrant. * * \sa atan() * \param y Floating point value representing a y coordinate. * \param x Floating point value representing an x coordinate. * \return Arc tangent of y/x, in the interval [-pi,+pi] radians. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float atan2(float y, float x) { asm { atan2 __FLTRETVAL__, y, x } } /** * Compute hyperbolic cosine. * Computes the hyperbolic cosine of x, expressed in radians. * * \param x Floating point value. * \return Hyperbolic cosine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float cosh(float x) { asm { cosh __FLTRETVAL__, x } } /** * Compute hyperbolic sine. * Computes the hyperbolic sine of x, expressed in radians. * * \param x Floating point value. * \return Hyperbolic sine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float sinh(float x) { asm { sinh __FLTRETVAL__, x } } /** * Compute hyperbolic tangent. * Computes the hyperbolic tangent of x, expressed in radians. * * \param x Floating point value. * \return Hyperbolic tangent of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float tanh(float x) { asm { tanh __FLTRETVAL__, x } } /** * Compute exponential function. * Computes the base-e exponential function of x, which is the e number * raised to the power x. * * \param x Floating point value. * \return Exponential value of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float exp(float x) { asm { exp __FLTRETVAL__, x } } /** * Compute natural logarithm. * Computes the natural logarithm of x. The natural logarithm is the base-e * logarithm, the inverse of the natural exponential function (exp). For * base-10 logarithms, a specific function log10() exists. * * \sa log10(), exp() * \param x Floating point value. * \return Natural logarithm of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float log(float x) { asm { log __FLTRETVAL__, x } } /** * Compute common logarithm. * Computes the common logarithm of x. The common logarithm is the base-10 * logarithm. For base-e logarithms, a specific function log() exists. * * \sa log(), exp() * \param x Floating point value. * \return Common logarithm of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float log10(float x) { asm { log10 __FLTRETVAL__, x } } /** * Compute integral part. * Computes the integral part of x. * * \param x Floating point value. * \return Integral part of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline long trunc(float x) { asm { trunc __RETVAL__, x } } /** * Compute fractional part. * Computes the fractional part of x. * * \param x Floating point value. * \return Fractional part of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float frac(float x) { asm { frac __FLTRETVAL__, x } } /** * Raise to power. * Computes base raised to the power exponent. * * \param base Floating point value. * \param exponent Floating point value. * \return The result of raising base to the power exponent. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float pow(float base, float exponent) { asm { pow __FLTRETVAL__, base, exponent } } /** * Round up value. * Computes the smallest integral value that is not less than x. * * \param x Floating point value. * \return The smallest integral value not less than x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float ceil(float x) { asm { ceil __FLTRETVAL__, x } } /** * Round down value. * Computes the largest integral value that is not greater than x. * * \param x Floating point value. * \return The largest integral value not greater than x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float floor(float x) { asm { floor __FLTRETVAL__, x } } /** * Multiply and divide. * Multiplies two 32-bit values and then divides the 64-bit result by a third * 32-bit value. * * \param a 32-bit long value. * \param b 32-bit long value. * \param c 32-bit long value. * \return The result of multiplying a times b and dividing by c. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline long muldiv32(long a, long b, long c) { asm { muldiv __RETVAL__, a, b, c } } // degree-based trig functions /** * Compute cosine (degrees). * Computes the cosine of an angle of x degrees. * * \param x Floating point value representing an angle expressed in degrees. * \return Cosine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float cosd(float x) { asm { cosd __FLTRETVAL__, x } } /** * Compute sine (degrees). * Computes the sine of an angle of x degrees. * * \param x Floating point value representing an angle expressed in degrees. * \return Sine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float sind(float x) { asm { sind __FLTRETVAL__, x } } /** * Compute tangent (degrees). * Computes the tangent of an angle of x degrees. * * \param x Floating point value representing an angle expressed in degrees. * \return Tangent of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float tand(float x) { asm { tand __FLTRETVAL__, x } } /** * Compute arc cosine (degrees). * Computes the principal value of the arc cosine of x, expressed in degrees. * In trigonometrics, arc cosine is the inverse operation of cosine. * * \param x Floating point value in the interval [-1,+1]. * \return Arc cosine of x, in the interval [0,180] degrees. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float acosd(float x) { asm { acosd __FLTRETVAL__, x } } /** * Compute arc sine (degrees). * Computes the principal value of the arc sine of x, expressed in degrees. * In trigonometrics, arc sine is the inverse operation of sine. * * \param x Floating point value in the interval [-1,+1]. * \return Arc sine of x, in the interval [-90,+90] degrees. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float asind(float x) { asm { asind __FLTRETVAL__, x } } /** * Compute arc tangent (degrees). * Computes the principal value of the arc tangent of x, expressed in degrees. * In trigonometrics, arc tangent is the inverse operation of tangent. Notice * that because of the sign ambiguity, a function cannot determine with * certainty in which quadrant the angle falls only by its tangent value. * You can use atan2d if you need to determine the quadrant. * * \param x Floating point value. * \return Arc tangent of x, in the interval [-90,+90] degrees. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float atand(float x) { asm { atand __FLTRETVAL__, x } } /** * Compute arc tangent with 2 parameters (degrees). * Computes the principal value of the arc tangent of y/x, expressed in * degrees. To compute the value, the function uses the sign of both arguments * to determine the quadrant. * * \param y Floating point value representing a y coordinate. * \param x Floating point value representing an x coordinate. * \return Arc tangent of y/x, in the interval [-180,+180] degrees. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float atan2d(float y, float x) { asm { atan2d __FLTRETVAL__, y, x } } /** * Compute hyperbolic cosine (degrees). * Computes the hyperbolic cosine of x, expressed in degrees. * * \param x Floating point value. * \return Hyperbolic cosine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float coshd(float x) { asm { coshd __FLTRETVAL__, x } } /** * Compute hyperbolic sine (degrees). * Computes the hyperbolic sine of x, expressed in degrees. * * \param x Floating point value. * \return Hyperbolic sine of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float sinhd(float x) { asm { sinhd __FLTRETVAL__, x } } /** * Compute hyperbolic tangent (degrees). * Computes the hyperbolic tangent of x, expressed in degrees. * * \param x Floating point value. * \return Hyperbolic tangent of x. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline float tanhd(float x) { asm { tanhd __FLTRETVAL__, x } } #endif #else // math functions written by Tamas Sorosy (www.sorosy.com) // X is any integer; Y is the sqrt value (0->max); if X<0, Y is the sqrt value of absolute X #define Sqrt(_X) asm { __SQRT(_X,__RETVAL__) } #endif #if (__FIRMWARE_VERSION <= 107) || !defined(__ENHANCED_FIRMWARE) // X is any integer in degrees; Y is 100* the sin value (-100->100) #define Sin(_X) asm { __SIN(_X,__RETVAL__) } // X is any integer in degrees; Y is 100* the cos value (-100->100) #define Cos(_X) asm { __COS(_X,__RETVAL__) } // X is 100* the sin value (-100->100); Y is -90->90; Y is 101 if X is outside -100->100 range #define Asin(_X) asm { __ASIN(_X,__RETVAL__) } // X is 100* the cos value (-100->100); Y is 0->180; Y is -11 if X is outside -100->100 range #define Acos(_X) asm { __ACOS(_X,__RETVAL__) } #endif /** * Convert from BCD to decimal * Return the decimal equivalent of the binary coded decimal value provided. * * \param bcd The value you want to convert from bcd to decimal. * \return The decimal equivalent of the binary coded decimal byte. */ inline byte bcd2dec(byte bcd) { asm { __bcd2dec(bcd, __URETVAL__) } } #ifdef __DOXYGEN_DOCS /** * Is the value NaN. * Returns true if the floating point value is NaN (not a number). * * \param value A floating point variable. * \return Whether the value is NaN. */ inline bool isNAN(float value); /** * Sign value. * Return the sign of the value argument (-1, 0, or 1). Any scalar type can * be passed into this function. * * \param num The numeric value for which to calculate its sign value. * \return -1 if the parameter is negative, 0 if the parameter is zero, or 1 if * the parameter is positive. */ inline char sign(variant num); #else #define isNAN(_x) ((_x) != (_x)) #endif /** @} */ // end of cmathAPI group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// cstdio API ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @defgroup cstdioAPI cstdio API * Standard C cstdio API functions. * @{ */ /** * Close file. * Close the file associated with the specified file handle. The loader * result code is returned as the value of the function call. * * \param handle The handle of the file to be closed. * \return The loader result code. */ inline int fclose(byte handle) { return CloseFile(handle); } /** * Remove file. * Delete the specified file. The loader result code is returned as the value * of the function call. * * \param filename The name of the file to be deleted. * \return The loader result code. */ inline int remove(string filename) { return DeleteFile(filename); } /** * Rename file. * Rename a file from the old filename to the new filename. The loader * result code is returned as the value of the function call. * * \param old The name of the file to be renamed. * \param new The new name for the file. * \return The loader result code. */ inline int rename(string old, string new) { return RenameFile(old, new); } /** * Get character from file. * Returns the character currently pointed to by the internal file position * indicator of the file specified by the handle. The internal file position * indicator is then advanced by one character to point to the next character. * The functions fgetc and getc are equivalent. * * \param handle The handle of the file from which the character is read. * \return The character read from the file. */ inline char fgetc(byte handle) { char ch; asm { __readValue(handle, ch, __RETVAL__) mov __RETVAL__, ch } } /** * Get character from file. * Returns the character currently pointed to by the internal file position * indicator of the file specified by the handle. The internal file position * indicator is then advanced by one character to point to the next character. * The functions fgetc and getc are equivalent. * * \param _handle The handle of the file from which the character is read. * \return The character read from the file. */ #define getc(_handle) fgetc(_handle) /** * Get string from file. * Reads characters from a file and stores them as a string into str until * (num-1) characters have been read or either a newline or a the End-of-File * is reached, whichever comes first. A newline character makes fgets stop * reading, but it is considered a valid character and therefore it is * included in the string copied to str. A null character is automatically * appended in str after the characters read to signal the end of the string. * Returns the string parameter. * * \param str The string where the characters are stored. * \param num The maximum number of characters to be read. * \param handle The handle of the file from which the characters are read. * \return The string read from the file. */ inline string fgets(string & str, int num, byte handle) { asm { __readLnStringEx(handle, str, num, __RETVAL__) }; return str; } /** * Check End-of-file indicator. * Checks whether the End-of-File indicator associated with the handle is * set, returning a value different from zero if it is. * * \param handle The handle of the file to check. * \return Currently always returns 0. */ inline int feof(byte handle) { return 0; } unsigned long __fopen_default_size = 1024; /** * Set the default fopen file size. * Set the default size of a file created via a call to fopen. * * \param fsize The default new file size for fopen. */ inline void set_fopen_size(unsigned long fsize) { __fopen_default_size = fsize; } /** * Open file. * Opens the file whose name is specified in the parameter filename and * associates it with a file handle that can be identified in future * operations by the handle that is returned. The operations that are allowed * on the stream and how these are performed are defined by the mode parameter. * * \param filename The name of the file to be opened. * \param mode The file access mode. Valid values are "r" - opens an existing * file for reading, "w" - creates a new file and opens it for writing, and * "a" - opens an existing file for appending to the end of the file. * \return The handle to the opened file. */ byte fopen(string filename, const string mode) { byte handle; int result = LDR_ILLEGALHANDLE; unsigned long fsize; switch(mode) { case "r" : result = OpenFileRead(filename, fsize, handle); break; case "w" : fsize = __fopen_default_size; result = CreateFile(filename, fsize, handle); break; case "a" : result = OpenFileAppend(filename, fsize, handle); break; } if (result != LDR_SUCCESS) handle = NULL; return handle; } /** * Flush file. * Writes any buffered data to the file. A zero value indicates success. * * \param handle The handle of the file to be flushed. * \return Currently always returns 0. */ inline int fflush(byte handle) { return 0; } #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** * Get current position in file. * Returns the current value of the file position indicator of the specified * handle. * * \param handle The handle of the file. * \return The current file position in the open file. * * \warning This function requires the enhanced NBC/NXC firmware version 1.31+. */ inline unsigned long ftell(byte handle) { FileTellType ftt; ftt.FileHandle = handle; SysFileTell(ftt); return ftt.Position; } #endif /** * Write character to file. * Writes a character to the file and advances the position indicator. * The character is written at the current position of the file as indicated * by the internal position indicator, which is then advanced one character. * If there are no errors, the same character that has been written is * returned. If an error occurs, EOF is returned. * * \param ch The character to be written. * \param handle The handle of the file where the character is to be written. * \return The character written to the file. */ inline char fputc(char ch, byte handle) { if (Write(handle, ch) == LDR_SUCCESS) return ch; else return EOF; } /** * Write character to file. * Writes a character to the file and advances the position indicator. * The character is written at the current position of the file as indicated * by the internal position indicator, which is then advanced one character. * If there are no errors, the same character that has been written is * returned. If an error occurs, EOF is returned. * * \param _ch The character to be written. * \param _handle The handle of the file where the character is to be written. * \return The character written to the file. */ #define putc(_ch, _handle) fputc(_ch, _handle) /** * Write string to file. * Writes the string to the file specified by the handle. The null terminating * character at the end of the string is not written to the file. If there are * no errors, a non-negative value is returned. If an error occurs, EOF is * returned. * * \param str The string of characters to be written. * \param handle The handle of the file where the string is to be written. * \return The number of characters written to the file. */ inline int fputs(string str, byte handle) { int cnt; if (WriteString(handle, str, cnt) == LDR_SUCCESS) return cnt; else return EOF; } #ifdef __ENHANCED_FIRMWARE #ifdef __DOXYGEN_DOCS /** * Print formatted data to stdout. * Writes to the LCD at 0, LCD_LINE1 a sequence of data formatted as the * format argument specifies. After the format parameter, the function * expects one value argument. * * \param format A string specifying the desired format. * \param value A value to be formatted for writing to the LCD. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void printf(string format, variant value); /** * Write formatted data to file. * Writes a sequence of data formatted as the format argument specifies to a * file. After the format parameter, the function expects one value * argument. * * \param handle The handle of the file to write to. * \param format A string specifying the desired format. * \param value A value to be formatted for writing to the file. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void fprintf(byte handle, string format, variant value); /** * Write formatted data to string. * Writes a sequence of data formatted as the format argument specifies to a * string. After the format parameter, the function expects one value * argument. * * \param str The string to write to. * \param format A string specifying the desired format. * \param value A value to be formatted for writing to the string. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline void sprintf(string & str, string format, variant value); #else #define printf(_format, _value) { \ string msg = FormatNum(_format, _value); \ TextOut(0, LCD_LINE1, msg); \ } #define fprintf(_handle, _format, _value) { \ int cnt = fputs(FormatNum(_format, _value), _handle); \ } #define sprintf(_str, _format, _value) { \ _str = FormatNum(_format, _value); \ } #endif #if __FIRMWARE_VERSION > 107 /** @defgroup fseekConstants fseek origin constants * Constants for use in calls to fseek. * @{ */ #define SEEK_SET 0 /*!< Seek from the beginning of the file */ #define SEEK_CUR 1 /*!< Seek from the current file position */ #define SEEK_END 2 /*!< Seek from the end of the file */ /** @} */ // end of fseekConstants group /** * Reposition file position indicator. * Sets the position indicator associated with the file to a new position * defined by adding offset to a reference position specified by origin. * * \param handle The handle of the file. * \param offset The number of bytes to offset from origin. * \param origin Position from where offset is added. It is specified by one * of the following constants: SEEK_SET - beginning of file, SEEK_CUR - current * position of the file pointer, or SEEK_END - end of file. \ref fseekConstants * \return A value of zero if successful or non-zero otherwise. See \ref LoaderErrors. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline int fseek(byte handle, long offset, int origin) { FileSeekType fst; fst.FileHandle = handle; fst.Origin = origin; fst.Length = offset; SysFileSeek(fst); return fst.Result; } /** * Set position indicator to the beginning. * Sets the position indicator associated with stream to the beginning of * the file. * * \param handle The handle of the file. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. */ inline void rewind(byte handle) { fseek(handle, 0, SEEK_SET); } /** * Get character from stdin. * Returns the next character from the standard input (stdin). * It is equivalent to getc with stdin as its argument. On the NXT this means * wait for a button press and return the value of the button pressed. * * \return The pressed button. See \ref ButtonNameConstants. * */ inline int getchar() { int result = -1; while (true) { if (ButtonPressed(BTN1, false)) result = BTN1; else if (ButtonPressed(BTN2, false)) result = BTN2; else if (ButtonPressed(BTN3, false)) result = BTN3; else if (ButtonPressed(BTN4, false)) result = BTN4; if (result != -1) break; else Yield(); } while(ButtonPressed(result, false)); return result; } #endif #endif /* size_t fread(ptr, size, count, FILE*); // read blocks of data from file; returns number of blocks read size_t fwrite(ptr, size, count, FILE*); // write blocks of data to stream; returns number of blocks written int putchar(int character); // write character to stdout */ /** @} */ // end of cstdioAPI group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// cstdlib API ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @defgroup cstdlibAPI cstdlib API * Standard C cstdlib API functions and types. * @{ */ /** @defgroup cstdlibAPITypes cstdlib API types * Standard C cstdlib API types. * @{ */ /** * Parameters for the RandomNumber system call. * This structure is used when calling the \ref SysRandomNumber system call * function. * \sa SysRandomNumber() */ struct RandomNumberType { int Result; /*!< The random number. */ }; /** * Output type of the div function. * div_t structure. * Structure used to represent the value of an integral division performed * by div. It has two members of the same type, defined in either order as: * int quot; int rem;. * \sa div() */ struct div_t { int quot; /*!< Represents the quotient of the integral division operation performed by div, which is the integer of lesser magnitude that is nearest to the algebraic quotient. */ int rem; /*!< Represents the remainder of the integral division operation performed by div, which is the integer resulting from subtracting quot to the numerator of the operation. */ }; /** * Output type of the ldiv function. * Structure used to represent the value of an integral division performed * by ldiv. It has two members of the same type, defined in either order as: * long quot; long rem;. * \sa ldiv() */ struct ldiv_t { long quot; /*!< Represents the quotient of the integral division operation performed by div, which is the integer of lesser magnitude that is nearest to the algebraic quotient. */ long rem; /*!< Represents the remainder of the integral division operation performed by div, which is the integer resulting from subtracting quot to the numerator of the operation. */ }; /** @} */ // end of cstdlibAPITypes group #ifdef __DOXYGEN_DOCS /** * Abort current process. * Aborts the process with an abnormal program termination. * The function never returns to its caller. */ inline void abort(); /** * Absolute value. * Return the absolute value of the value argument. Any scalar type can * be passed into this function. * * \param num The numeric value. * \return The absolute value of num. The return type matches the input type. */ inline variant abs(variant num); /** * Generate random number. * Returns a pseudo-random integral number in the range 0 to \ref RAND_MAX. * * \return An integer value between 0 and RAND_MAX. */ inline unsigned int rand(); /** * Generate random number. * Return a signed or unsigned 16-bit random number. If the optional argument n * is not provided the function will return a signed value. Otherwise the * returned value will range between 0 and n (exclusive). * * \param n The maximum unsigned value desired (optional). * \return A random number */ inline int Random(unsigned int n = 0); /** * Draw a random number. * This function lets you obtain a random number via the \ref RandomNumberType * structure. * * \param args The RandomNumberType structure receiving results. */ inline void SysRandomNumber(RandomNumberType & args); #else #define abort() Stop(true) #define rand() Random(RAND_MAX) #define SysRandomNumber(_args) asm { \ compchktype _args, RandomNumberType \ syscall RandomNumber, _args \ } #endif /** * Convert string to integer. * Parses the string str interpreting its content as an integral number, * which is returned as an int value. * * The function first discards as many whitespace characters as necessary * until the first non-whitespace character is found. Then, starting from * this character, takes an optional initial plus or minus sign followed by as * many numerical digits as possible, and interprets them as a numerical value. * * The string can contain additional characters after those that form the * integral number, which are ignored and have no effect on the behavior of * this function. * * If the first sequence of non-whitespace characters in str does not form a * valid integral number, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String beginning with the representation of an integral number. * \return On success, the function returns the converted integral number * as an int value. If no valid conversion could be performed a zero value * is returned. */ inline int atoi(const string & str) { return StrToNum(str); } /** * Convert string to long integer. * Parses the string str interpreting its content as an integral number, * which is returned as a long int value. * * The function first discards as many whitespace characters as necessary * until the first non-whitespace character is found. Then, starting from * this character, takes an optional initial plus or minus sign followed by as * many numerical digits as possible, and interprets them as a numerical value. * * The string can contain additional characters after those that form the * integral number, which are ignored and have no effect on the behavior of * this function. * * If the first sequence of non-whitespace characters in str does not form a * valid integral number, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String beginning with the representation of an integral number. * \return On success, the function returns the converted integral number * as a long int value. If no valid conversion could be performed a zero value * is returned. */ inline long atol(const string & str) { return StrToNum(str); } /** * Absolute value. * Return the absolute value of parameter n. * * \param n Integral value. * \return The absolute value of n. */ inline long labs(long n) { return abs(n); } #if __FIRMWARE_VERSION > 107 /** * Convert string to float. * Parses the string str interpreting its content as a floating point number * and returns its value as a float. * * The function first discards as many whitespace characters as necessary until * the first non-whitespace character is found. Then, starting from this * character, takes as many characters as possible that are valid following a * syntax resembling that of floating point literals, and interprets them as a * numerical value. The rest of the string after the last valid character is * ignored and has no effect on the behavior of this function. * * A valid floating point number for atof is formed by a succession of: * - An optional plus or minus sign * - A sequence of digits, optionally containing a decimal-point character * - An optional exponent part, which itself consists on an 'e' or 'E' * character followed by an optional sign and a sequence of digits. * * If the first sequence of non-whitespace characters in str does not form a * valid floating-point number as just defined, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String beginning with the representation of a floating-point number. * \return On success, the function returns the converted floating point number * as a float value. If no valid conversion could be performed a zero value * (0.0) is returned. */ inline float atof(const string & str) { float result; asm { strtonum result, __TMPWORD__, str, NA, NA } return result; } /** * Convert string to float. * Parses the string str interpreting its content as a floating point number * and returns its value as a float. * * The function first discards as many whitespace characters as necessary until * the first non-whitespace character is found. Then, starting from this * character, takes as many characters as possible that are valid following a * syntax resembling that of floating point literals, and interprets them as a * numerical value. A string containing the rest of the string after the last * valid character is stored in endptr. * * A valid floating point number for atof is formed by a succession of: * - An optional plus or minus sign * - A sequence of digits, optionally containing a decimal-point character * - An optional exponent part, which itself consists on an 'e' or 'E' * character followed by an optional sign and a sequence of digits. * * If the first sequence of non-whitespace characters in str does not form a * valid floating-point number as just defined, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String beginning with the representation of a floating-point number. * \param endptr Reference to a string, whose value is set by the function to * the remaining characters in str after the numerical value. * \return On success, the function returns the converted floating point number * as a float value. If no valid conversion could be performed a zero value * (0.0) is returned. */ inline float strtod(const string & str, string & endptr) { float result; int offsetpast; asm { strtonum result, offsetpast, str, NA, NA strsubset endptr, str, offsetpast, NA } return result; } #endif /** * Convert string to long integer. * Parses the C string str interpreting its content as an integral number of * the specified base, which is returned as a long int value. * * The function first discards as many whitespace characters as necessary * until the first non-whitespace character is found. Then, starting from this * character, takes as many characters as possible that are valid following a * syntax that depends on the base parameter, and interprets them as a * numerical value. A string containing the rest of the characters following the * integer representation in str is stored in endptr. * * If the first sequence of non-whitespace characters in str does not form a * valid integral number, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String beginning with the representation of an integral number. * \param endptr Reference to a string, whose value is set by the function to * the remaining characters in str after the numerical value. * \param base Optional and ignored if specified. * \return On success, the function returns the converted integral number * as a long int value. If no valid conversion could be performed a zero value * is returned. * \warning Only base = 10 is currently supported. */ inline long strtol(const string & str, string & endptr, int base = 10) { long result; int offsetpast; asm { strtonum result, offsetpast, str, NA, NA strsubset endptr, str, offsetpast, NA } return result; } /** * Convert string to unsigned long integer. * Parses the C string str interpreting its content as an unsigned integral * number of the specified base, which is returned as an unsigned long int value. * * The function first discards as many whitespace characters as necessary * until the first non-whitespace character is found. Then, starting from this * character, takes as many characters as possible that are valid following a * syntax that depends on the base parameter, and interprets them as a * numerical value. A string containing the rest of the characters following the * integer representation in str is stored in endptr. * * If the first sequence of non-whitespace characters in str does not form a * valid integral number, or if no such sequence exists * because either str is empty or contains only whitespace characters, no * conversion is performed. * * \param str String containing the representation of an unsigned integral number. * \param endptr Reference to a string, whose value is set by the function to * the remaining characters in str after the numerical value. * \param base Optional and ignored if specified. * \return On success, the function returns the converted integral number * as an unsigned long int value. If no valid conversion could be performed a * zero value is returned. * \warning Only base = 10 is currently supported. */ inline long strtoul(const string & str, string & endptr, int base = 10) { unsigned long result; int offsetpast; asm { strtonum result, offsetpast, str, NA, NA strsubset endptr, str, offsetpast, NA } return result; } /** * Integral division. * Returns the integral quotient and remainder of the division of numerator by * denominator as a structure of type div_t, which has two members: * quot and rem. * * \param numer Numerator. * \param denom Denominator. * \return The result is returned by value in a structure defined in cstdlib, * which has two members. For div_t, these are, in either order: * int quot; int rem. */ inline div_t div(int numer, int denom) { div_t result; result.quot = numer / denom; result.rem = numer % denom; return result; } /** * Integral division. * Returns the integral quotient and remainder of the division of numerator by * denominator as a structure of type ldiv_t, which has two members: * quot and rem. * * \param numer Numerator. * \param denom Denominator. * \return The result is returned by value in a structure defined in cstdlib, * which has two members. For ldiv_t, these are, in either order: * long quot; long rem. */ inline ldiv_t ldiv(long numer, long denom) { ldiv_t result; result.quot = numer / denom; result.rem = numer % denom; return result; } /** @} */ // end of cstdlibAPI group /////////////////////////////////////////////////////////////////////////////// //////////////////////////////// cstring API ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @defgroup cstringAPI cstring API * Standard C cstring API functions. * @{ */ #ifdef __DOXYGEN_DOCS /** * Convert string to number. * Return the numeric value specified by the string passed to the function. * If the content of the string is not a numeric value then this function * returns zero. The input string parameter * may be a variable, constant, or expression. * * \param str String beginning with the representation of a number. * \param str A string. * \return A number. */ inline variant StrToNum(string str); /** * Get string length. * Return the length of the specified string. The length of a string does * not include the null terminator at the end of the string. The input * string parameter may be a variable, constant, or expression. * * \param str A string. * \return The length of the string. */ inline unsigned int StrLen(string str); /** * Extract a character from a string. * Return the numeric value of the character in the specified string at the * specified index. The input string parameter * may be a variable, constant, or expression. * * \param str A string. * \param idx The index of the character to retrieve. * \return The numeric value of the character at the specified index. */ inline byte StrIndex(string str, unsigned int idx); /** * Convert number to string. * Return the string representation of the specified numeric value. * * \param num A number. * \return The string representation of the parameter num. */ inline string NumToStr(variant num); /** * Concatenate strings. * Return a string which is the result of concatenating all of the * string arguments together. This function accepts * any number of parameters which may be string variables, constants, * or expressions. * * \param str1 The first string. * \param str2 The second string. * \param strN The Nth string. * \return The concatenated string. */ inline string StrCat(string str1, string str2, string strN); /** * Extract a portion of a string. * Return a sub-string from the specified input string starting at idx and * including the specified number of characters. The input string parameter * may be a variable, constant, or expression. * * \param str A string. * \param idx The starting point of the sub-string. * \param len The length of the sub-string. * \return The sub-string extracted from parameter str. */ inline string SubStr(string str, unsigned int idx, unsigned int len); /** * Flatten a number to a string. * Return a string containing the byte representation of the specified value. * * \param num A number. * \return A string containing the byte representation of the parameter num. */ inline string Flatten(variant num); /** * Replace a portion of a string. * Return a string with the part of the string replaced (starting at the * specified index) with the contents of the new string value provided in * the third argument. The input string parameters * may be variables, constants, or expressions. * * \param str A string. * \param idx The starting point for the replace operation. * \param strnew The replacement string. * \return The modified string. */ inline string StrReplace(string str, unsigned int idx, string strnew); /** * Format a number. * Return the formatted string using the format and value. Use a standard * numeric sprintf format specifier within the format string. The input string * parameter may be a variable, constant, or expression. * * \param fmt The string format containing a sprintf numeric format specifier. * \param num A number. * \return A string containing the formatted numeric value. * * \warning This function requires the enhanced NBC/NXC firmware. */ inline string FormatNum(string fmt, variant num); /** * Flatten any data to a string. * Return a string containing the byte representation of the specified value. * * \sa UnflattenVar * \param x Any NXC datatype. * \return A string containing the byte representation of the parameter x. */ inline string FlattenVar(variant x); /** * Unflatten a string into a data type. * Convert a string containing the byte representation of the specified * variable back into the original variable type. * * \sa FlattenVar, Flatten * \param str A string containing flattened data. * \param x A variable reference where the unflattened data is stored. * \return A boolean value indicating whether the operation succeeded or not. */ inline int UnflattenVar(string str, variant & x); #else #define FlattenVar(_value) asm { flatten __STRRETVAL__, _value } #define UnflattenVar(_str, _value) asm { \ unflatten _value, __RETVAL__, _str, _value \ not __RETVAL__, __RETVAL__ \ } #endif /** * Find substring position. * Returns the index value of the first character in a specified substring * that occurs in a given string. Pos searches for Substr within S and * returns an integer value that is the index of the first character of * Substr within S. Pos is case-sensitive. If Substr is not found, Pos * returns negative one. * * \param Substr A substring to search for in another string. * \param S A string that might contain the specified substring. * \return The position of the substring in the specified string or -1 if it is * not found. */ inline int Pos(string Substr, string S) { asm { __doPos(Substr, S, __RETVAL__) } } /** * Convert a byte array to a string. * Convert the specified array to a string by appending a null terminator to * the end of the array elements. The array must be a one-dimensional array * of byte. * * \sa StrToByteArray, ByteArrayToStrEx * \param data A byte array. * \return A string containing data and a null terminator byte. */ inline string ByteArrayToStr(byte data[]) { asm { arrtostr __STRBUFFER__, data } } /** * Convert a byte array to a string. * Convert the specified array to a string by appending a null terminator to * the end of the array elements. The array must be a one-dimensional array * of byte. * * \sa StrToByteArray, ByteArrayToStr * \param data A byte array. * \param str A string variable reference which, on output, will contain * data and a null terminator byte. */ inline void ByteArrayToStrEx(byte data[], string & str) { asm { arrtostr str, data } } /** * Convert a string to a byte array. * Convert the specified string to an array of byte by removing the null * terminator at the end of the string. The output array variable must be a * one-dimensional array of byte. * * \sa ByteArrayToStr, ByteArrayToStrEx * \param str A string * \param data A byte array reference which, on output, will contain str * without its null terminator. */ inline void StrToByteArray(string str, byte & data[]) { asm { strtoarr data, str } } /** * Copy a portion of a string. * Returns a substring of a string. * * \param str A string * \param idx The starting index of the substring. * \param len The length of the substring. * \return The specified substring. */ inline string Copy(string str, unsigned int idx, unsigned int len) { asm { strsubset __STRBUFFER__, str, idx, len } } /** * Copy a portion from the middle of a string. * Returns the substring of a specified length that appears at a specified * position in a string. * * \param str A string * \param idx The starting index of the substring. * \param len The length of the substring. * \return The substring of a specified length that appears at a specified * position in a string. */ inline string MidStr(string str, unsigned int idx, unsigned int len) { asm { strsubset __STRBUFFER__, str, idx, len } } /** * Copy a portion from the end of a string. * Returns the substring of a specified length that appears at the end of a string. * * \param str A string * \param size The size or length of the substring. * \return The substring of a specified length that appears at the end of a string. */ inline string RightStr(string str, unsigned int size) { unsigned int idx; asm { strlen idx, str sub idx, idx, size strsubset __STRBUFFER__, str, idx, size } } /** * Copy a portion from the start of a string. * Returns the substring of a specified length that appears at the start of a string. * * \param str A string * \param size The size or length of the substring. * \return The substring of a specified length that appears at the start of a string. */ inline string LeftStr(string str, unsigned int size) { asm { strsubset __STRBUFFER__, str, 0, size } } // cstring functions /** * Get string length. * Return the length of the specified string. The length of a string does * not include the null terminator at the end of the string. * * \param str A string. * \return The length of the string. */ inline int strlen(const string & str) { asm { strlen __RETVAL__, str } } /** * Concatenate strings. * Appends a copy of the source string to the destination string. The * terminating null character in destination is overwritten by the first * character of source, and a new null-character is appended at the end of * the new string formed by the concatenation of both in destination. The * destination string is returned. * * \param dest The destination string. * \param src The string to be appended. * \return The destination string. */ inline string strcat(string & dest, const string & src) { asm { strcat __STRBUFFER__, dest, src mov dest, __STRBUFFER__ } } /** * Append characters from string. * Appends the first num characters of source to destination, plus a * terminating null-character. If the length of the string in source is less * than num, only the content up to the terminating null-character is copied. * The destination string is returned. * * \param dest The destination string. * \param src The string to be appended. * \param num The maximum number of characters to be appended. * \return The destination string. */ inline string strncat(string & dest, const string & src, unsigned int num) { asm { strsubset __STRRETVAL__, src, 0, num strcat __STRBUFFER__, dest, __STRRETVAL__ mov dest, __STRBUFFER__ } } /** * Copy string. * Copies the string pointed by source into the array pointed by destination, * including the terminating null character. The destination string is returned. * * \param dest The destination string. * \param src The string to be appended. * \return The destination string. */ inline string strcpy(string & dest, const string & src) { asm { mov __STRBUFFER__, src mov dest, __STRBUFFER__ } } /** * Copy characters from string. * Copies the first num characters of source to destination. The destination * string is returned. * * \param dest The destination string. * \param src The string to be appended. * \param num The maximum number of characters to be appended. * \return The destination string. */ inline string strncpy(string & dest, const string & src, unsigned int num) { asm { strsubset dest, src, 0, num mov __STRBUFFER__, dest } } /** * Compare two strings. * Compares the string str1 to the string str2. * * \param str1 A string to be compared. * \param str2 A string to be compared. * \return Returns an integral value indicating the relationship between the * strings. A zero value indicates that both strings are equal. A value * greater than zero indicates that the first character that does not match * has a greater value in str1 than in str2. A value less than zero indicates * the opposite. */ inline int strcmp(const string & str1, const string & str2) { int result = -1; if (str1 == str2) result = 0; else if (str1 > str2) result = 1; return result; } /** * Compare characters of two strings. * Compares up to num characters of the string str1 to those of the string str2. * * \param str1 A string to be compared. * \param str2 A string to be compared. * \param num The maximum number of characters to be compared. * \return Returns an integral value indicating the relationship between the * strings. A zero value indicates that the characters compared in both * strings are all equal. A value greater than zero indicates that the first * character that does not match has a greater value in str1 than in str2. A * value less than zero indicates the opposite. */ inline int strncmp(const string & str1, const string & str2, unsigned int num) { string sub1, sub2; asm { strsubset sub1, str1, 0, num strsubset sub2, str2, 0, num } int result = -1; if (sub1 == sub2) result = 0; else if (sub1 > sub2) result = 1; return result; } #ifdef __DOXYGEN_DOCS /** * Copy memory. * Copies memory contents from the source to the destination. The num * argument is ignored. * * \param dest The destination variable. * \param src The source variable. * \param num The number of bytes to copy (ignored). */ inline void memcpy(variant dest, variant src, byte num); /** * Move memory. * Moves memory contents from the source to the destination. The num * argument is ignored. * * \param dest The destination variable. * \param src The source variable. * \param num The number of bytes to copy (ignored). */ inline void memmove(variant dest, variant src, byte num); /** * Compare two blocks of memory. * Compares the variant ptr1 to the variant ptr2. Returns an integral value * indicating the relationship between the variables. The num argument is * ignored. * * \param ptr1 A variable to be compared. * \param ptr2 A variable to be compared. * \param num The number of bytes to compare (ignored). */ inline char memcmp(variant ptr1, variant ptr2, byte num); /** * Get the absolute address of a variable. * Get the absolute address of a variable and return it to the calling routine * as an unsigned long value. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param data A variable whose address you wish to get. * \return The absolute address of the variable. */ inline unsigned long addressOf(variant data); /** * Get the relative address of a variable. * Get the relative address of a variable and return it to the calling routine * as an unsigned long value. The relative address is an offset from the * Command module's MemoryPool address. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param data A variable whose address you wish to get. * \return The relative address of the variable. */ inline unsigned long reladdressOf(variant data); /** * Get the absolute or relative address of a variable. * Get the absolute or relative address of a variable and return it to the * calling routine as an unsigned long value. The relative address is an * offset from the Command module's MemoryPool address. * * \warning This function requires the enhanced NBC/NXC firmware version 1.28+. * * \param data A variable whose address you wish to get. * \param relative A boolean flag indicating whether you want to get the * relative or absolute address. * \return The absolute or relative address of the variable. */ inline unsigned long addressOfEx(variant data, bool relative); #else #define memcpy(_dest, _src, _num) asm { mov _dest, _src } #define memmove(_dest, _src, _num) asm { mov _dest, _src } #define memcmp(_ptr1, _ptr2, _num) ( (_ptr1 == _ptr2) ? 0 : ( (_ptr1 > _ptr2) ? 1 : -1 ) ) #define addressOf(_data) asm { addrof __URETVAL__, _data, 0 } #define reladdressOf(_data) asm { addrof __URETVAL__, _data, 1 } #define addressOfEx(_data, _rel) asm { addrof __URETVAL__, _data, _rel } #endif /* void * memchr (void * ptr, int value, size_t num ); // Locate character in block of memory char * strchr ( char * str, int character ); // Locate first occurrence of character in string size_t strcspn ( const char * str1, const char * str2 ); // Get span until character in string char * strpbrk ( const char *, const char * ); // Locate character in string char * strrchr ( const char *, int ); // Locate last occurrence of character in string size_t strspn ( const char * str1, const char * str2 ); // Get span of character set in string char * strtok ( char * str, const char * delimiters ); // Split string into tokens char * strstr ( const char *, const char * ); // Locate substring void * memset ( void * ptr, byte value, size_t num ); // Fill block of memory (something like replace) */ /** @} */ // end of cstringAPI group /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// ctype API /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /** @defgroup ctypeAPI ctype API * Standard C ctype API functions. * @{ */ /** * Check if character is uppercase letter. * Checks if parameter c is an uppercase alphabetic letter. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is an uppercase alphabetic * letter, otherwise it returns 0 (false). */ inline int isupper(int c) { return ((c >= 'A') && (c <= 'Z')); } /** * Check if character is lowercase letter. * Checks if parameter c is an lowercase alphabetic letter. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is an lowercase alphabetic * letter, otherwise it returns 0 (false). */ inline int islower(int c) { return ((c >= 'a') && (c <= 'z')); } /** * Check if character is alphabetic. * Checks if parameter c is either an uppercase or lowercase letter. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is an alphabetic letter, * otherwise it returns 0 (false). */ inline int isalpha(int c) { return isupper(c) || islower(c); } /** * Check if character is decimal digit. * Checks if parameter c is a decimal digit character. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a decimal digit, otherwise * it returns 0 (false). */ inline int isdigit(int c) { return ((c >= '0') && (c <= '9')); } /** * Check if character is alphanumeric. * Checks if parameter c is either a decimal digit or an uppercase or * lowercase letter. The result is true if either isalpha or isdigit would * also return true. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is either a digit or a * letter, otherwise it returns 0 (false). */ inline int isalnum(int c) { return isalpha(c) || isdigit(c); } /** * Check if character is a white-space. * Checks if parameter c is a white-space character. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a white-space character, * otherwise it returns 0 (false). */ inline int isspace(int c) { return (c == 0x20) || ((c >= 0x09) && (c <= 0x0d)); } /** * Check if character is a control character. * Checks if parameter c is a control character. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a control character, * otherwise it returns 0 (false). */ inline int iscntrl(int c) { return (c <= 0x1f) || (c == 0x7f); } /** * Check if character is printable. * Checks if parameter c is a printable character (i.e., not a control * character). * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a printable character, * otherwise it returns 0 (false). */ inline int isprint(int c) { return !iscntrl(c); } /** * Check if character has graphical representation. * Checks if parameter c is a character with a graphical representation. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c has a graphical representation, * otherwise it returns 0 (false). */ inline int isgraph(int c) { return (c != 0x20) && isprint(c); } /** * Check if character is a punctuation. * Checks if parameter c is a punctuation character. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a punctuation character, * otherwise it returns 0 (false). */ inline int ispunct(int c) { return isgraph(c) && !isalnum(c); } /** * Check if character is hexadecimal digit. * Checks if parameter c is a hexadecimal digit character. * * \param c Character to be checked. * \return Returns a non-zero value (true) if c is a hexadecimal digit * character, otherwise it returns 0 (false). */ inline int isxdigit(int c) { return isdigit(c) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')); } /** * Convert lowercase letter to uppercase. * Converts parameter c to its uppercase equivalent if c is a lowercase * letter and has an uppercase equivalent. If no such conversion is possible, * the value returned is c unchanged. * * \param c Lowercase letter character to be converted. * \return The uppercase equivalent to c, if such value exists, or c * (unchanged) otherwise.. */ inline int toupper(int c) { if (islower(c)) c -= 32; return c; } /** * Convert uppercase letter to lowercase. * Converts parameter c to its lowercase equivalent if c is an uppercase * letter and has a lowercase equivalent. If no such conversion is possible, * the value returned is c unchanged. * * \param c Uppercase letter character to be converted. * \return The lowercase equivalent to c, if such value exists, or c * (unchanged) otherwise.. */ inline int tolower(int c) { if (isupper(c)) c += 32; return c; } /** @} */ // end of ctypeAPI group /** @} */ // end of StandardCAPIFunctions group /** @addtogroup RICMacros * @{ */ /** * Set the value of an element in an RIC data array. * \param _data The RIC data array * \param _idx The array index to update * \param _newval The new value to write into the RIC data array */ #define RICSetValue(_data, _idx, _newval) _data[(_idx)] = (_newval)&0xFF; _data[(_idx)+1] = (_newval)>>8 /** @} */ // end of RICMacros group /** @addtogroup GraphicsLibrary * @{ */ //------------------------------------------------------------------------------ // File : nbcGL.nbc // Description : Data and subroutines for a very simple 3D engine. // Programmed by : Arno van der Vegt, legoasimo@gmail.com //------------------------------------------------------------------------------ /** * Initialize graphics library. * Setup all the necessary data for the graphics library to function. Call this * function before any other graphics library routine. */ inline void glInit() { asm { __glInit() } } /** * Set graphics library options. * Adjust graphic library settings for circle size and cull mode. * * \param glType The setting type. See \ref GLConstantsSettings. * \param glValue The setting value. For culling modes see \ref GLConstantsCullMode. */ inline void glSet(int glType, int glValue) { asm { __glSet(glType, glValue) } } /** * Begin defining an object. * Start the process of defining a graphics library object using low level * functions such as \ref glBegin, \ref glAddVertex, and \ref glEnd. * * \return The object index of the new object being created. */ inline int glBeginObject() { asm { __glBeginObject(__RETVAL__) } } /** * Stop defining an object. * Finish the process of defining a graphics library object. Call this function * after you have completed the object definition. */ inline void glEndObject() { asm { __glEndObject() } } /** * Perform an object action. * Execute the specified action on the specified object. * * \param glObjectId The object id. * \param glAction The action to perform on the object. See \ref GLConstantsActions. * \param glValue The setting value. */ inline void glObjectAction(int glObjectId, int glAction, int glValue) { asm { __glObjectAction(glObjectId, glAction, glValue) } } /** * Add a vertex to an object. * Add a vertex to an object currently being defined. This function should * only be used between \ref glBegin and \ref glEnd which are themselves * nested within a \ref glBeginObject and \ref glEndObject pair. * * \param glX The X axis coordinate. * \param glY The Y axis coordinate. * \param glZ The Z axis coordinate. */ inline void glAddVertex(int glX, int glY, int glZ) { asm { __glAddVertex(glX, glY, glZ) } } /** * Begin a new polygon for the current object. * Start defining a polygon surface for the current graphics object using * the specified begin mode. * * \param glBeginMode The desired mode. See \ref GLConstantsBeginModes. */ inline void glBegin(int glBeginMode) { asm { __glBegin(glBeginMode) } } /** * Finish a polygon for the current object. * Stop defining a polgyon surface for the current graphics object. */ inline void glEnd() { asm { __glEnd() } } /** * Begin a new render. * Start the process of rendering the existing graphic objects. */ inline void glBeginRender() { asm { __glBeginRender() } } /** * Call a graphic object. * Tell the graphics library that you want it to include the specified * object in the render. * * \param glObjectId The desired object id. */ inline void glCallObject(int glObjectId) { asm { __glCallObject(glObjectId) } } /** * Finish the current render. * Rotate the vertex list, clear the screen, and draw the rendered objects * to the LCD. */ inline void glFinishRender() { asm { __glFinishRender() } } /** * Set the X axis angle. * Set the X axis angle to the specified value. * * \param glValue The new X axis angle. */ inline void glSetAngleX(int glValue) { asm { __glSetAngleX(glValue) } } /** * Add to the X axis angle. * Add the specified value to the existing X axis angle. * * \param glValue The value to add to the X axis angle. */ inline void glAddToAngleX(int glValue) { asm { __glAddToAngleX(glValue) } } /** * Set the Y axis angle. * Set the Y axis angle to the specified value. * * \param glValue The new Y axis angle. */ inline void glSetAngleY(int glValue) { asm { __glSetAngleY(glValue) } } /** * Add to the Y axis angle. * Add the specified value to the existing Y axis angle. * * \param glValue The value to add to the Y axis angle. */ inline void glAddToAngleY(int glValue) { asm { __glAddToAngleY(glValue) } } /** * Set the Z axis angle. * Set the Z axis angle to the specified value. * * \param glValue The new Z axis angle. */ inline void glSetAngleZ(int glValue) { asm { __glSetAngleZ(glValue) } } /** * Add to the Z axis angle. * Add the specified value to the existing Z axis angle. * * \param glValue The value to add to the Z axis angle. */ inline void glAddToAngleZ(int glValue) { asm { __glAddToAngleZ(glValue) } } /** * Table-based sine scaled by 32768. * Return the sine of the specified angle in degrees. The result is scaled * by 32768. * * \param glAngle The angle in degrees. * \return The sine value scaled by 32768. */ inline int glSin32768(int glAngle) { asm { __glSin32768(__RETVAL__, glAngle) } } /** * Table-based cosine scaled by 32768. * Return the cosine of the specified angle in degrees. The result is scaled * by 32768. * * \param glAngle The angle in degrees. * \return The cosine value scaled by 32768. */ inline int glCos32768(int glAngle) { asm { __glCos32768(__RETVAL__, glAngle) } } /** * Create a 3D box. * Define a 3D box using the specified begin mode for all faces. The center * of the box is at the origin of the XYZ axis with width, height, and depth * specified via the glSizeX, glSizeY, and glSizeZ parameters. * * \param glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param glSizeX The X axis size (width). * \param glSizeY The Y axis size (height). * \param glSizeZ The Z axis size (depth). */ inline int glBox(int glMode, int glSizeX, int glSizeY, int glSizeZ) { asm { __glBox(glMode, glSizeX, glSizeY, glSizeZ, __RETVAL__) } } /** * Create a 3D cube. * Define a 3D cube using the specified begin mode for all faces. The center * of the box is at the origin of the XYZ axis with equal width, height, and depth * specified via the glSize parameter. * * \param glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param glSize The cube's width, height, and depth. */ inline int glCube(int glMode, int glSize) { asm { __glBox(glMode, glSize, glSize, glSize, __RETVAL__) } } /** * Create a 3D pyramid. * Define a 3D pyramid using the specified begin mode for all faces. The center * of the pyramid is at the origin of the XYZ axis with width, height, and depth * specified via the glSizeX, glSizeY, and glSizeZ parameters. * * \param glMode The begin mode for each surface. See \ref GLConstantsBeginModes. * \param glSizeX The X axis size (width). * \param glSizeY The Y axis size (height). * \param glSizeZ The Z axis size (depth). */ inline int glPyramid(int glMode, int glSizeX, int glSizeY, int glSizeZ) { asm { __glPyramid(glMode, glSizeX, glSizeY, glSizeZ, __RETVAL__) } } /** @} */ // end of GraphicsLibrary group #if defined(__ENHANCED_FIRMWARE) && (__FIRMWARE_VERSION > 107) /** @addtogroup NXTFirmwareModules * @{ */ /** @addtogroup OutputModule * @{ */ /** @addtogroup OutputModuleFunctions * @{ */ /** * Enable absolute position regulation with PID factors. * Enable absolute position regulation on the specified output. Motor is kept * regulated as long as this is enabled. * Optionally specify proportional, integral, and derivative factors. * * \param output Desired output port. Can be a constant or a variable, see * \ref OutputPortConstants. * \param p Proportional factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. Default value is \ref PID_3. * \param i Integral factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. Default value is \ref PID_1. * \param d Derivative factor used by the firmware's PID motor control * algorithm. See \ref PIDConstants. Default value is \ref PID_1. */ inline void PosRegEnable(byte output, byte p = PID_3, byte i = PID_1, byte d = PID_1) { SetOutput(output, OutputModeField, OUT_MODE_MOTORON+OUT_MODE_BRAKE+OUT_MODE_REGULATED, RegModeField, OUT_REGMODE_POS, RunStateField, OUT_RUNSTATE_RUNNING, PowerField, 0, TurnRatioField, 0, RegPValueField, p, RegIValueField, i, RegDValueField, d, UpdateFlagsField, UF_UPDATE_MODE+UF_UPDATE_SPEED+UF_UPDATE_PID_VALUES+UF_UPDATE_RESET_COUNT); Wait(MS_2); } /** * Change the current value for set angle. * Make the absolute position regulation going toward the new provided angle. * Returns immediately, but keep regulating. * * \param output Desired output port. Can be a constant or a variable, see * \ref OutputPortConstants. * \param angle New set position, in degree. The 0 angle corresponds to the * position of the motor when absolute position regulation was first enabled. * Can be negative. Can be greater than 360 degree to make several turns. */ inline void PosRegSetAngle(byte output, long angle) { SetOutput(output, TachoLimitField, angle, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT); } /** * Add to the current value for set angle. * Add an offset to the current set position. Returns immediately, but keep * regulating. * * \param output Desired output port. Can be a constant or a variable, see * \ref OutputPortConstants. * \param angle_add Value to add to the current set position, in degree. Can * be negative. Can be greater than 360 degree to make several turns. */ inline void PosRegAddAngle(byte output, long angle_add) { long current_angle = GetOutput(output, TachoLimitField); SetOutput(output, TachoLimitField, current_angle + angle_add, UpdateFlagsField, UF_UPDATE_TACHO_LIMIT); } /** * Set maximum limits. * Set maximum speed and acceleration. * * \param output Desired output port. Can be a constant or a variable, see * \ref OutputPortConstants. * \param max_speed Maximum speed, or 0 to disable speed limiting. * \param max_acceleration Maximum acceleration, or 0 to disable acceleration * limiting. The max_speed parameter should not be 0 if this is not 0. */ inline void PosRegSetMax(byte output, byte max_speed, byte max_acceleration) { SetOutput(output, MaxSpeedField, max_speed, MaxAccelerationField, max_acceleration, UpdateFlagsField, UF_UPDATE_PID_VALUES); Wait(MS_2); } /** @} */ // end of OutputModuleFunctions group /** @} */ // end of OutputModule group /** @} */ // end of NXTFirmwareModules group #endif #endif // NXCDEFS_H NXT/uRIC.pas0000644000175000017500000010024311537752673012436 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uRIC; interface const IMG_DESCRIPTION_ID = 0; // Ignored at this time IMG_SPRITE_ID = 1; IMG_VARMAP_ID = 2; IMG_COPYBITS_ID = 3; IMG_PIXEL_ID = 4; IMG_LINE_ID = 5; IMG_RECTANGLE_ID = 6; IMG_CIRCLE_ID = 7; IMG_NUMBOX_ID = 8; IMG_ELLIPSE_ID = 9; IMG_POLYGON_ID = 10; const USEARGS_MASK = $1000; function IMG_SYMB_USEARGS(v : cardinal) : cardinal; function IMG_SYMB_MAP(v : cardinal) : cardinal; function IMG_SYMB_ARG(v : cardinal) : cardinal; const DRAW_OPT_CLEAR_WHOLE_SCREEN = $0001; DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN = $0002; function DRAW_OPT_CLEAR_MODE(v : cardinal) : cardinal; const DO_NOT_CLEAR = 0; CLEAR_B4_DRAW = 1; RESTORE_NXT_SCREEN = 0; DISPLAY_HEIGHT = 64; DISPLAY_WIDTH = 100; DISPLAY_REALWIDTH = DISPLAY_WIDTH; function TRANSLATE_Y(y : integer) : integer; type IMG_PT = record X : SmallInt; Y : SmallInt; end; PIMG_PT = ^IMG_PT; IMG_RECT = record Pt : IMG_PT; Width : SmallInt; Height : SmallInt; end; PIMG_RECT = ^IMG_RECT; IMG_OP_CORE = record OpSize : Word; OpCode : Word; end; PIMG_OP_CORE = ^IMG_OP_CORE; IMG_OP_DESCRIPTION = record OpSize : Word; OpCode : Word; Options : Word; Width : Word; Height : Word; end; PIMG_OP_DESCRIPTION = ^IMG_OP_DESCRIPTION; IMG_OP_SPRITE = record OpSize : Word; OpCode : Word; DataAddr : Word; //Address sprite handle will be stored in. Rows : Word; //Second dimension of the array below. RowBytes : Word; //The actual size of the following array. Must be even. Bytes : array[0..1] of Byte; // Minimum of two for alignment purposes end; PIMG_OP_SPRITE = ^IMG_OP_SPRITE; IOV_MAPELT = record Domain : Word; Range : Word; end; PIOV_MAPELT = ^IOV_MAPELT; IMG_OP_VARMAP = record OpSize : Word; OpCode : Word; DataAddr : Word; //Address sprite handle will be stored in. MapCount : Word; //The actual size of the following array. Must be even. MapElt : array[0..1] of IOV_MAPELT; //Minimum of two for alignment purposes end; PIMG_OP_VARMAP = ^IMG_OP_VARMAP; IMG_OP_COPYBITS = record OpSize : Word; OpCode : Word; CopyOptions : Word; // Copy, CopyNot, Or, BitClear, And, Xor; DataAddr : Word; // Address of an already defined sprite Src : IMG_RECT; // Source rectangle Dst : IMG_PT; // Destination left top end; PIMG_OP_COPYBITS = ^IMG_OP_COPYBITS; IMG_OP_PIXEL = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt : IMG_PT; Value : Word; // typically mapped to an argument end; PIMG_OP_PIXEL = ^IMG_OP_PIXEL; IMG_OP_LINE = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt1 : IMG_PT; Pt2 : IMG_PT; end; PIMG_OP_LINE = ^IMG_OP_LINE; IMG_OP_RECT = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt : IMG_PT; Width : SmallInt; Height : SmallInt; end; PIMG_OP_RECT = ^IMG_OP_RECT; IMG_OP_CIRCLE = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt : IMG_PT; Radius : Word; end; PIMG_OP_CIRCLE = ^IMG_OP_CIRCLE; IMG_OP_NUMBOX = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt : IMG_PT; Value : Word; // typically mapped to an argument end; PIMG_OP_NUMBOX = ^IMG_OP_NUMBOX; IMG_OP_ELLIPSE = record OpSize : Word; OpCode : Word; CopyOptions : Word; Pt : IMG_PT; Radius1 : Word; Radius2 : Word; end; PIMG_OP_ELLIPSE = ^IMG_OP_ELLIPSE; IMG_OP_POLYGON = record OpSize : Word; OpCode : Word; CopyOptions : Word; Count : Word; Points : array[0..2] of IMG_PT; // at least 3 points per polygon end; PIMG_OP_POLYGON = ^IMG_OP_POLYGON; FONT_REC = record FormatMsb : Byte; FormatLsb : Byte; DataBytesMsb : Byte; DataBytesLsb : Byte; ItemsX : Byte; ItemsY : Byte; ItemsPixelsX : Byte; ItemsPixelsY : Byte; Data : array[0..1] of Byte; end; P_FONT = ^FONT_REC; TOpTypes = (otCore, otDescr, otSprite, otVarmap, otCopyBits, otPixel, otLine, otRect, otCircle, otNumBox, otEllipse, otPolygon); IMG_OP_UNION = record case TOpTypes of otCore: (Core : IMG_OP_CORE); otDescr: (Desc : IMG_OP_DESCRIPTION); otSprite: (Sprite : IMG_OP_SPRITE); otVarmap: (VarMap : IMG_OP_VARMAP); otCopyBits: (CopyBits : IMG_OP_COPYBITS); otPixel: (Pixel : IMG_OP_PIXEL); otLine: (Line : IMG_OP_LINE); otRect: (Rect : IMG_OP_RECT); otCircle: (Circle : IMG_OP_CIRCLE); otNumBox: (NumBox : IMG_OP_NUMBOX); otEllipse: (Ellipse : IMG_OP_ELLIPSE); otPolygon: (Polygon : IMG_OP_POLYGON); end; PIMG_OP_UNION = ^IMG_OP_UNION; const IMG_MAX_DATA = 11; type TRICVariables = array[0..255] of Integer; var gpImgData : array[0..IMG_MAX_DATA-1] of PIMG_OP_UNION; gpPassedImgVars : TRICVariables; gPassedVarsCount : SmallInt; function cCmdWrapSetScreenMode(var Status : Integer; ScreenMode : Cardinal) : integer; function cCmdWrapDrawPoint(var Status : Integer; Location : PIMG_PT; Options : Cardinal) : Integer; function cCmdWrapDrawLine(var Status : Integer; StartLoc, EndLoc : PIMG_PT; Options : Cardinal) : Integer; function cCmdWrapDrawCircle(var Status : Integer; StartLoc : PIMG_PT; Radius : Integer; Options : Cardinal) : Integer; function cCmdWrapDrawRect(var Status : Integer; TopLeft, BotRight : PIMG_PT; Options : Cardinal) : Integer; function cCmdWrapDrawPicture(var Status : Integer; TopLeft : PIMG_PT; Filename : string; Variables : TRICVariables; Options : Cardinal) : Integer; procedure cCmdRestoreDefaultScreen; implementation uses Classes, Math, SysUtils, uNXTConstants; procedure pMapDisplayUpdateMask(mask : cardinal); begin case mask of SCREENBIT shl SCREEN_BACKGROUND : begin end; SCREENBIT shl SCREEN_LARGE : begin end; else end; end; procedure pMapDisplayPFunc(funcID, p1, p2, p3, p4, p5 : byte); begin if (funcID =0) or (p1 = 0) or (p2 = 0) or (p3 = 0) or (p4 = 0) or (p5 = 0) then begin end; end; (* void cDisplayString(FONT *pFont,UBYTE X,UBYTE Y,UBYTE *pString) { UBYTE *pSource; UBYTE *pDestination; UBYTE FontWidth; UBYTE Line; UBYTE Items; UBYTE Item; Line = (Y & 0xF8) / 8; Items = pFont->ItemsX * pFont->ItemsY; pDestination = (UBYTE* )&IOMapDisplay.Display[Line * DISPLAY_WIDTH + X]; while ( *pString) { Item = *pString - ' '; if (Item < Items) { FontWidth = pFont->ItemPixelsX; pSource = (UBYTE* )&pFont->Data[Item * FontWidth]; while (FontWidth--) { *pDestination = *pSource; pDestination++; pSource++; } } pString++; } } void cDisplayUpdateScreen(SCREEN_CORDINATE *pCord,BMPMAP *pBitmap) { UBYTE *pSource; UBYTE *pDestination; UBYTE Line; UBYTE Lines; if (pBitmap) { if ((((pBitmap->StartY + pCord->StartY) & 0x07) == 0) && ((pBitmap->PixelsY & 0x07) == 0)) { pSource = pBitmap->Data; Line = (pBitmap->StartY + pCord->StartY) / 8; Lines = Line + pBitmap->PixelsY / 8; while (Line < Lines) { pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pBitmap->StartX + pCord->StartX]; memcpy(pDestination,pSource,(size_t)pBitmap->PixelsX); pSource += pBitmap->PixelsX; Line++; } } } } void cDisplayCenterString(FONT *pFont,UBYTE *pString,UBYTE Line) { UWORD Chars; UBYTE Column; if (pString) { Chars = 0; while (pString[Chars]) { Chars++; } Column = (DISPLAY_WIDTH - Chars * pFont->ItemPixelsX) / 2; cDisplayString(pFont,Column,Line * 8,pString); } } void cDisplayUpdateMenuIcon(UBYTE *pIcon,SCREEN_CORDINATE *pCord) { UBYTE *pDestination; UBYTE Line; UBYTE Column; UBYTE Lines; UBYTE Columns; if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0)) { Line = pCord->StartY / 8; Lines = Line + pCord->PixelsY / 8; Columns = pCord->StartX + pCord->PixelsX; if (pIcon != NULL) { while (Line < Lines) { Column = pCord->StartX; pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + Column]; while (Column < Columns) { *pDestination |= *pIcon; pIcon++; pDestination++; Column++; } Line++; } } else { while (Line < Lines) { pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX]; memset(pDestination,0,(size_t)pCord->PixelsX); Line++; } } } } void cDisplayUpdateIcon(ICON *pIcons,UBYTE Index,SCREEN_CORDINATE *pCord) { UBYTE *pSource; UBYTE *pDestination; UBYTE Line; UBYTE Lines; if (pIcons) { if ((Index > 0) && (Index <= (pIcons->ItemsX * pIcons->ItemsY))) { Index--; if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0)) { Line = pCord->StartY / 8; Lines = Line + pCord->PixelsY / 8; pSource = &pIcons->Data[((Index / pIcons->ItemsX) * pIcons->ItemsX * pIcons->ItemPixelsX * pIcons->ItemPixelsY / 8) + ((Index % pIcons->ItemsX) * pIcons->ItemPixelsX)]; while (Line < Lines) { pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX]; memcpy(pDestination,pSource,(size_t)pCord->PixelsX); pSource += (pIcons->ItemPixelsX * pIcons->ItemsX); Line++; } } } else { if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0)) { Line = pCord->StartY / 8; Lines = Line + pCord->PixelsY / 8; while (Line < Lines) { pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX]; memset(pDestination,0,(size_t)pCord->PixelsX); Line++; } } } } } void cDisplayFrame(SCREEN_CORDINATE *pCord) { cDisplayLineX(pCord->StartX,pCord->StartX + pCord->PixelsX - 1,pCord->StartY); cDisplayLineY(pCord->StartX,pCord->StartY,pCord->StartY + pCord->PixelsY - 1); cDisplayLineY(pCord->StartX + pCord->PixelsX - 1,pCord->StartY,pCord->StartY + pCord->PixelsY - 1); } void cDisplayEraseScreen(SCREEN_CORDINATE *pCord) { UBYTE *pDestination; UBYTE Line; UBYTE Lines; if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0)) { Line = pCord->StartY / 8; Lines = Line + pCord->PixelsY / 8; while (Line < Lines) { pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX]; memset(pDestination,0,(size_t)pCord->PixelsX); Line++; } } } *) const OP_CLR = 0; OP_SET = 1; OP_OR = 2; OP_AND = 3; OP_XOR = 4; OP_NOT = 5; procedure SetDisplayByte(addr : Word; op : Byte; val : Byte); begin if (addr = 0) or (val = 0) then Exit; case op of OP_CLR : begin end; OP_SET : begin end; OP_OR : begin end; OP_AND : begin end; OP_XOR : begin end; OP_NOT : begin end; end; end; procedure cDisplayChar(pFont : P_FONT; bOn, X, Y, Ch : Byte); begin if not Assigned(pFont) or (bOn = 0) or (X = 0) or (Y = 0) or (Ch = 0) then Exit; (* UBYTE *pSource; UBYTE FontWidth; UBYTE FontHeight; UBYTE Items; UBYTE Item; UBYTE TmpY; Items := pFont^.ItemsX * pFont^.ItemsY; Item := Ch - Ord(' '); if (Item < Items) then begin FontWidth := pFont^.ItemPixelsX; pSource = (UBYTE* )&pFont->Data[Item * FontWidth]; while (FontWidth--) begin TmpY = 0; FontHeight = pFont->ItemPixelsY; while (FontHeight--) begin if (bOn = 1) then begin if ((( *pSource) & (1 << TmpY))) then begin cDisplaySetPixel(X,Y + TmpY); end else begin cDisplayClrPixel(X,Y + TmpY); end; end else begin if ((( *pSource) & (1 << TmpY))) then begin cDisplayClrPixel(X,Y + TmpY); end else begin cDisplaySetPixel(X,Y + TmpY); end; end; TmpY++; end; X++; pSource++; end; end; *) end; procedure cDisplayLineX(X1, X2, Y : Byte); var X, M : Byte; begin M := Byte(1 shl Byte((Y mod 8))); Y := Byte(Y shr 3); for X := X1 to Byte(X2 - 1) do begin SetDisplayByte(Word(Y * DISPLAY_WIDTH + X), OP_OR, M); // IOMapDisplay.Display[Y * DISPLAY_WIDTH + X] |= M; end; end; procedure cDisplayLineY(X, Y1, Y2 : Byte); var Y : Byte; begin for Y := Y1 to Byte(Y2 - 1) do begin SetDisplayByte(Word((Y div 8) * DISPLAY_WIDTH + X), OP_OR, Byte(1 shl (Y mod 8))); // IOMapDisplay.Display[(Y / 8) * DISPLAY_WIDTH + X] |= (1 << (Y % 8)); end; end; procedure cDisplaySetPixel(X, Y : Byte); begin if ((X < DISPLAY_WIDTH) and (Y < DISPLAY_HEIGHT)) then begin SetDisplayByte(Word((Y div 8) * DISPLAY_WIDTH + X), OP_OR, Byte(1 shl (Y mod 8))); end; end; procedure cDisplayClrPixel(X, Y : Byte); begin if ((X < DISPLAY_WIDTH) and (Y < DISPLAY_HEIGHT)) then begin SetDisplayByte(Word((Y div 8) * DISPLAY_WIDTH + X), OP_AND, Byte(not (1 shl (Y mod 8)))); // IOMapDisplay.Display[(Y div 8) * DISPLAY_WIDTH + X] &= ~(1 shl (Y % 8)); end; end; procedure cDisplayEraseLine(Line : Byte); var Tmp : Byte; begin for Tmp := 0 to DISPLAY_WIDTH - 1 do SetDisplayByte(Word(Line * DISPLAY_WIDTH + Tmp), OP_SET, $00); end; procedure cDisplayErase; var Tmp : Byte; begin for Tmp := 0 to (DISPLAY_HEIGHT div 8) - 1 do cDisplayEraseLine(Tmp); end; procedure cDisplayDraw(Cmd, bOn, X1, Y1, X2, Y2 : Byte); var IOMapDisplayPFont : P_FONT; begin IOMapDisplayPFont := nil; case Cmd of DISPLAY_ERASE_ALL : begin cDisplayErase(); end; DISPLAY_PIXEL : begin if bOn = 1 then begin cDisplaySetPixel(X1,Y1); end else begin cDisplayClrPixel(X1,Y1); end; end; DISPLAY_HORIZONTAL_LINE : begin if bOn = 1 then begin if (X1 > X2) then begin cDisplayLineX(X2,X1,Y1); end else begin cDisplayLineX(X1,X2,Y1); end; end; end; DISPLAY_VERTICAL_LINE : begin if bOn = 1 then begin if (Y1 > Y2) then begin cDisplayLineY(X1,Y2,Y1); end else begin cDisplayLineY(X1,Y1,Y2); end; end; end; DISPLAY_CHAR : begin cDisplayChar(IOMapDisplayPFont,bOn,X1,Y1,X2); end; end; end; procedure cCmdSetPixel(x, y, Val : Integer); begin y := TRANSLATE_Y(y); // draw the pixel pMapDisplayPFunc(DISPLAY_PIXEL, Byte(Val), Byte(x), Byte(y), 0, 0); end; procedure cCmdDrawLine(x1, y1, x2, y2 : Integer); var d, x, y, ax, ay, sx, sy, dx, dy : integer; begin dx := x2-x1; ax := Abs(dx) shl 1; sx := Sign(dx); dy := y2-y1; ay := Abs(dy) shl 1; sy := Sign(dy); x := x1; y := y1; if ax > ay then begin // x dominant d := ay - (ay shr 1); while true do begin cCmdSetPixel(x, y, 1); if x = x2 then Exit; if d >= 0 then begin inc(y, sy); dec(d, ax); end; inc(x, sx); inc(d, ay); end; end else begin // y dominant d := ax - (ay shr 1); while true do begin cCmdSetPixel(x, y, 1); if (y = y2) then Exit; if d >= 0 then begin inc(x, sx); dec(d, ay); end; inc(y, sy); inc(d, ax); end; end; end; procedure cCmdDrawRect(left, bottom, width, height : integer); var right, top : integer; begin right := left + width; top := bottom + height; // Draw the four line segments cCmdDrawLine(left, top, right, top); cCmdDrawLine(right, top, right, bottom); cCmdDrawLine(right, bottom, left, bottom); cCmdDrawLine(left, bottom, left, top); end; procedure cCmdDrawCircle(cx, cy, radius : integer); var x, x1, y, y1, dp, delta : integer; begin x1 := cx; y1 := cy; x := 0; y := radius; dp := 2 * (1-radius); while y >= 0 do begin cCmdSetPixel(x+x1, y+y1, 1); cCmdSetPixel(-x+x1, -y+y1, 1); cCmdSetPixel(x+x1, -y+y1, 1); cCmdSetPixel(-x+x1, y+y1, 1); if dp < 0 then begin delta := 2*dp + 2*y - 1; if delta > 0 then begin inc(x); dec(y); inc(dp, 2*x - 2*y + 2); end else begin inc(x); inc(dp, 2*x + 1); end; end else if dp > 0 then begin delta := 2*dp - 2*x - 1; if delta > 0 then begin dec(y); inc(dp, 1 - 2*y); end else begin inc(x); dec(y); inc(dp, 2*x - 2*y + 2); end; end else begin inc(x); dec(y); inc(dp, 2*x - 2*y + 2); end; end; end; procedure cCmdRestoreDefaultScreen; begin (* //If this program has taken over the display, reset it for the UI if (VarsCmd.DirtyDisplay == TRUE) { VarsCmd.DirtyDisplay = FALSE; pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); pMapDisplay->UpdateMask = SCREEN_BIT(SCREEN_BACKGROUND); pMapUi->Flags |= UI_ENABLE_STATUS_UPDATE | UI_REDRAW_STATUS; } *) end; procedure cCmdClearScreenIfNeeded(DrawOptions : Cardinal); begin if DRAW_OPT_CLEAR_MODE(DrawOptions) <> 0 then begin end; (* //If we are the first drawing command, clear the screen and record that we've done so if (VarsCmd.DirtyDisplay == FALSE) { VarsCmd.DirtyDisplay = TRUE; pMapUi->Flags &= ~UI_ENABLE_STATUS_UPDATE; //Override DrawOptions because we have to clear anyway DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN; } if (DRAW_OPT_CLEAR_MODE(DrawOptions)) { pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); //Clear UpdateMask to kill any pending updates pMapDisplay->UpdateMask = 0; } return; *) end; function cCmdWrapSetScreenMode(var Status : Integer; ScreenMode : Cardinal) : integer; begin if ScreenMode = RESTORE_NXT_SCREEN then cCmdRestoreDefaultScreen; Status := NO_ERR; Result := NO_ERR; end; function cCmdWrapDrawPoint(var Status : Integer; Location : PIMG_PT; Options : Cardinal) : Integer; var pPt : PIMG_PT; begin pPt := Location; cCmdClearScreenIfNeeded(Options); cCmdSetPixel(pPt^.X, pPt^.Y, 1); pMapDisplayUpdateMask(SCREEN_BIT(SCREEN_BACKGROUND)); Status := NO_ERR; Result := NO_ERR; end; function cCmdWrapDrawLine(var Status : Integer; StartLoc, EndLoc : PIMG_PT; Options : Cardinal) : Integer; var pPt1, pPt2 : PIMG_PT; begin pPt1 := StartLoc; pPt2 := EndLoc; cCmdClearScreenIfNeeded(Options); cCmdDrawLine(pPt1^.X, pPt1^.Y, pPt2^.X, pPt2^.Y); pMapDisplayUpdateMask(SCREEN_BIT(SCREEN_BACKGROUND)); Status := NO_ERR; Result := NO_ERR; end; function cCmdWrapDrawCircle(var Status : Integer; StartLoc : PIMG_PT; Radius : Integer; Options : Cardinal) : Integer; var pPt : PIMG_PT; begin pPt := StartLoc; cCmdClearScreenIfNeeded(Options); cCmdDrawCircle(pPt^.X, pPt^.Y, Radius); pMapDisplayUpdateMask(SCREEN_BIT(SCREEN_BACKGROUND)); Status := NO_ERR; Result := NO_ERR; end; function cCmdWrapDrawRect(var Status : Integer; TopLeft, BotRight : PIMG_PT; Options : Cardinal) : Integer; var pPt1, pPt2 : PIMG_PT; begin pPt1 := TopLeft; pPt2 := BotRight; // actually width, height cCmdClearScreenIfNeeded(Options); cCmdDrawRect(pPt1^.X, pPt1^.Y, pPt2^.X, pPt2^.Y); pMapDisplayUpdateMask(SCREEN_BIT(SCREEN_BACKGROUND)); Status := NO_ERR; Result := NO_ERR; end; function cCmdGetIMGData(DataAddr : Cardinal) : PIMG_OP_UNION; begin if DataAddr >= IMG_MAX_DATA then Result := nil else Result := gpImgData[DataAddr]; end; procedure cCmdSetIMGData(DataAddr : Cardinal; pSprite : PIMG_OP_UNION); begin if (DataAddr >= 1) and (DataAddr < IMG_MAX_DATA) then gpImgData[DataAddr] := pSprite; end; function cCmdResolveValue(Value : SmallInt) : Integer; var pVarMap : PIMG_OP_VARMAP; Arg, i, DCur, RCur, DSpread, VSpread, RSpread : Integer; Count, DPrev, RPrev : Integer; begin if IMG_SYMB_USEARGS(Value) = 0 then Result := Value else begin pVarMap := PIMG_OP_VARMAP(cCmdGetIMGData(IMG_SYMB_MAP(Value))); Arg := gpPassedImgVars[IMG_SYMB_ARG(Value)]; if pVarMap = nil then Result := Arg else begin // Scan through the list finding the pair the Arg lies between // Then linearly interpolate the mapping. Count := pVarMap^.MapCount; DPrev := pVarMap^.MapElt[0].Domain; RPrev := pVarMap^.MapElt[0].Range; RCur := 0; if Arg <= DPrev then begin Result := RPrev; Exit; end; for i := 1 to Count - 1 do begin DCur := pVarMap^.MapElt[i].Domain; RCur := pVarMap^.MapElt[i].Range; if Arg < DCur then begin DSpread := DCur - DPrev; VSpread := Arg - DPrev; RSpread := RCur - RPrev; Result := RPrev + ((VSpread*RSpread) div DSpread); Exit; end; DPrev := DCur; RPrev := RCur; end; // If we get this far then it is too large, map it to the last point. Result := RCur; end; end; end; //#define DISP_BUFFER_P (( UBYTE* ) &(pMapDisplay->Normal)) var DISP_BUFFER_P : PByte = nil; masks : array[0..7] of byte = ($80, $40, $20, $10, $08, $04, $02, $01); procedure cCmdCopyBitMapBits(dst_x, dst_y, src_x, src_y, src_width, src_height : integer; pSprite : PIMG_OP_SPRITE); var dy, sx, sy, _trim, last_x, last_y, rowbytes : integer; pSrcByte, pDstBytes, pDstByte, pFirstDstByte, pLastDstByte : PByte; bit_y, not_bit_y : Byte; begin // Data in the image file is row major 8 pixels per byte.top row first. // src and dst coordinates treat the bottom left most pixel as (0,0) if (pSprite = nil) or (pSprite^.OpCode <> IMG_SPRITE_ID) then Exit; pDstBytes := DISP_BUFFER_P; GetMem(pDstBytes, src_width*src_height); try // Clip the edges. Modify the source and width as well. if dst_x < 0 then begin // bounds check start of x _trim := (0 - dst_x); dst_x := 0; inc(src_x, _trim); dec(src_width, _trim); end; last_x := dst_x + src_width; if last_x > DISPLAY_WIDTH then // bounds check end of x last_x := DISPLAY_WIDTH; if dst_y < 0 then begin // bounds check start of y _trim := (0 - dst_y); dst_y := 0; inc(src_y, _trim); dec(src_height, _trim); end; last_y := dst_y + src_height; if last_y > DISPLAY_HEIGHT then // bound check end of y last_y := DISPLAY_HEIGHT; // Convert the 0,0 bottom left origin to the top left 0,0 used by the actual // buffer last_y := TRANSLATE_Y(last_y); dst_y := TRANSLATE_Y(dst_y); // The last row is the top most scan line in the LCD Buffer // so limit if the copy would copy into memory before the buffer. // The first row copied will be the one closest to the bottom of the LCD // If that is off screen then limit as well and adjust the start point on the start // Copy bits top to top moving down. sy := src_y; rowbytes := pSprite^.RowBytes; pSrcByte := PByte(PChar(@(pSprite^.Bytes[0])) + ((pSprite^.Rows - 1 - sy) * rowbytes)); pFirstDstByte := PByte(PChar(pDstBytes) + ((dst_y shr 3) * DISPLAY_REALWIDTH) + dst_x); for dy := dst_y downto (last_y + 1) do begin sx := src_x; bit_y := masks[7 - (dy and $07)]; not_bit_y := not bit_y; pDstByte := pFirstDstByte; pLastDstByte := PByte(PChar(pDstByte) + (last_x - dst_x)); while PChar(pDstByte) < PChar(pLastDstByte) do begin if (PByte(PChar(pSrcByte) + (sx shr 3))^ and masks[sx and $07]) <> 0 then pDstByte^ := pDstByte^ or bit_y else pDstByte^ := pDstByte^ and not_bit_y; inc(sx); inc(pDstByte); end; dec(pSrcByte, rowbytes); // inc(sy); if (dy and $07) = 0 then // bump back the scan line start point at rollover dec(pFirstDstByte, DISPLAY_REALWIDTH); end; // actually draw pDstBytes to NXT here ... finally FreeMem(pDstBytes); end; end; procedure cCmdDrawString(txt : string; X, Y : Cardinal); begin if (txt = '') or (X = Y) then Exit; (* UBYTE *pSource; UBYTE *pDestination; FONT *pFont; ULONG FontWidth; ULONG Items; ULONG Item; ULONG Line; //Get current font information pFont = pMapDisplay->pFont; Items = pFont->ItemsX * pFont->ItemsY; //Invert Y coordinate to match display buffer Y = TRANSLATE_Y(Y); Line = (Y & 0xF8) / 8; //If text line is out of bounds, do nothing. if (Line >= TEXTLINES) return; //Calculate pointer to first byte of drawing destination pDestination = &(DISP_BUFFER_P[Line * DISPLAY_WIDTH + X]); while (*pString) { FontWidth = pFont->ItemPixelsX; //Calculate X coordinate of the right edge of this character. //If it will extend past the right edge, clip the string. X += FontWidth; if (X >= DISPLAY_WIDTH) break; //If item is defined by the font, display it. Else, ignore it. Item = *pString - ' '; if (Item < Items) { pSource = (UBYTE* )&(pFont->Data[Item * FontWidth]); while (FontWidth--) { *pDestination = *pSource; pDestination++; pSource++; } } pString++; } *) end; function cCmdWrapDrawPicture(var Status : Integer; TopLeft : PIMG_PT; Filename : string; Variables : TRICVariables; Options : Cardinal) : Integer; var DStatus, i, OpSize : integer; DataSize : Cardinal; Pt : IMG_PT; // Where to draw the picture at (up and to the right) // ImageHandle : Byte; pImage : PIMG_OP_UNION; pCB : PIMG_OP_COPYBITS; pL : PIMG_OP_LINE; pR : PIMG_OP_RECT; pC : PIMG_OP_CIRCLE; pNB : PIMG_OP_NUMBOX; NumStr : string; MS : TMemoryStream; begin DStatus := NO_ERR; cCmdClearScreenIfNeeded(Options); //Open the file in memory map mode. return if failure. MS := TMemoryStream.Create; try if FileExists(Filename) then begin MS.LoadFromFile(Filename); DataSize := Cardinal(MS.Size); MS.Position := 0; pImage := MS.Memory; // Read the ArgV params, Clear the data table. Pt := TopLeft^; gpPassedImgVars := Variables; for i := 0 to IMG_MAX_DATA - 1 do gpImgData[i] := nil; // Run through the op codes. while not IS_ERR(DStatus) do begin // Setup to look at an opcode, make sure it looke reasonable. if DataSize < SizeOf(IMG_OP_CORE) then begin DStatus := ERR_FILE; Break; // Too small to look at, somethings wrong. end; OpSize := pImage^.Core.OpSize + SizeOf(Word); if (OpSize and $01) <> 0 then begin DStatus := ERR_FILE; Break; // Odd sizes not allowed. end; case pImage^.Core.OpCode of IMG_DESCRIPTION_ID : begin // no-op end; IMG_SPRITE_ID : begin if OpSize >= SizeOf(IMG_OP_SPRITE) then cCmdSetIMGData(pImage^.Sprite.DataAddr, pImage); end; IMG_VARMAP_ID : begin if OpSize >= SizeOf(IMG_OP_VARMAP) then cCmdSetIMGData(pImage^.VarMap.DataAddr, pImage); end; IMG_COPYBITS_ID : begin if OpSize >= SizeOf(IMG_OP_COPYBITS) then begin pCB := @(pImage^.CopyBits); cCmdCopyBitMapBits( (cCmdResolveValue(pCB^.Dst.X) + Pt.Y), (cCmdResolveValue(pCB^.Dst.Y) + Pt.Y), cCmdResolveValue((pCB^.Src.Pt.X)), cCmdResolveValue((pCB^.Src.Pt.Y)), cCmdResolveValue((pCB^.Src.Width)), cCmdResolveValue((pCB^.Src.Height)), PIMG_OP_SPRITE(cCmdGetIMGData(cCmdResolveValue(pCB^.DataAddr)))); end; end; IMG_PIXEL_ID : begin if OpSize >= SizeOf(IMG_OP_PIXEL) then begin cCmdSetPixel( (cCmdResolveValue(pImage^.Pixel.Pt.X)+Pt.X), (cCmdResolveValue(pImage^.Pixel.Pt.Y)+Pt.Y), cCmdResolveValue(pImage^.Pixel.Value)); end; end; IMG_LINE_ID : begin if OpSize >= SizeOf(IMG_OP_LINE) then begin pL := @(pImage^.Line); cCmdDrawLine( (cCmdResolveValue(pL^.Pt1.X)+Pt.X), (cCmdResolveValue(pL^.Pt1.Y)+Pt.Y), (cCmdResolveValue(pL^.Pt2.X)+Pt.X), (cCmdResolveValue(pL^.Pt2.Y)+Pt.Y) ); end; end; IMG_RECTANGLE_ID : begin if OpSize >= SizeOf(IMG_OP_RECT) then begin pR := @(pImage^.Rect); cCmdDrawRect( (cCmdResolveValue(pR^.Pt.X)+Pt.X), (cCmdResolveValue(pR^.Pt.Y)+Pt.Y), (cCmdResolveValue(pR^.Width)+Pt.X), (cCmdResolveValue(pR^.Height)+Pt.Y) ); end; end; IMG_CIRCLE_ID : begin if OpSize >= SizeOf(IMG_OP_CIRCLE) then begin pC := @(pImage^.Circle); cCmdDrawCircle( (cCmdResolveValue(pC^.Pt.X)+Pt.X), (cCmdResolveValue(pC^.Pt.Y)+Pt.Y), cCmdResolveValue(pC^.Radius) ); end; end; IMG_NUMBOX_ID : begin if OpSize >= SizeOf(IMG_OP_NUMBOX) then begin pNB := @(pImage^.NumBox); NumStr := Format('%d', [cCmdResolveValue(pNB^.Value)]); cCmdDrawString( NumStr, (cCmdResolveValue(pNB^.Pt.X) + Pt.X), (cCmdResolveValue(pNB^.Pt.Y) + Pt.Y)); end; end; else //Unrecognized opcode, pass an error back to the diagram. DStatus := ERR_FILE; Break; end; dec(DataSize, OpSize); pImage := PIMG_OP_UNION(PChar(pImage) + OpSize); end; pMapDisplayUpdateMask(SCREEN_BIT(SCREEN_BACKGROUND)); end; finally MS.Free; end; // Set return value and return Status := DStatus; Result := NO_ERR; end; function IMG_SYMB_USEARGS(v : cardinal) : cardinal; begin Result := v and $F000; end; function IMG_SYMB_MAP(v : cardinal) : cardinal; begin Result := (v and $0F00) shr 8; end; function IMG_SYMB_ARG(v : cardinal) : cardinal; begin Result := v and $00FF; end; function DRAW_OPT_CLEAR_MODE(v : cardinal) : cardinal; begin Result := v and $0003; end; function TRANSLATE_Y(y : integer) : integer; begin Result := (DISPLAY_HEIGHT-1) - y; end; end. NXT/uNXTClasses.pas0000644000175000017500000111261311537752673014015 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNXTClasses; {$B-} interface uses Classes, Contnrs, SysUtils, uNXTConstants, uPreprocess, uNBCCommon; type TCompilerStatusChangeEvent = procedure(Sender : TObject; const StatusMsg : string; const bDone : boolean) of object; NXTInstruction = record Encoding : TOpCode; CCType : Byte; Arity : Byte; Name : string; end; type TAsmLineType = (altBeginDS, altEndDS, altBeginClump, altEndClump, altCode, altVarDecl, altTypeDecl, altBeginStruct, altEndStruct, altBeginSub, altEndSub, altCodeDepends, altInvalid); TAsmLineTypes = set of TAsmLineType; TMainAsmState = (masDataSegment, masCodeSegment, masClump, masClumpSub, masStruct, masDSClump, masStructDSClump, masDSClumpSub, masStructDSClumpSub, masBlockComment); PRXEHeader = ^RXEHeader; RXEHeader = record FormatString : array[0..13] of Char; // add null terminator at end Skip : Byte; // second 0 Version : Byte; DSCount : Word; DSSize : Word; DSStaticSize : Word; DSDefaultsSize : Word; DynDSDefaultsOffset : Word; DynDSDefaultsSize : Word; MemMgrHead : Word; MemMgrTail : Word; DVArrayOffset : Word; ClumpCount : Word; CodespaceCount : Word; end; DSTocEntry = record TypeDesc : Byte; Flags : Byte; DataDesc: Word; Size : Word; RefCount: Word; end; DSTocEntries = array of DSTocEntry; // dynamic array DopeVector = record offset : Word; elemsize : Word; count : Word; backptr : Word; link : Word; end; DopeVectors = array of DopeVector; // dynamic array ClumpRecord = record FireCount : Byte; DependentCount : Byte; CodeStart : Word; end; ClumpRecords = array of ClumpRecord; // dynamic array TSTTFuncType = function(const stype : string; bUseCase : Boolean = false) : TDSType; const BytesPerType : array[TDSType] of Byte = (4, 1, 1, 2, 2, 4, 4, 2, 4, 4, 4); NOT_AN_ELEMENT = $FFFF; type TDSBase = class; TDSData = class; TDataspaceEntry = class(TCollectionItem) private fThreadNames : TStrings; fDataType: TDSType; fIdentifier: string; fDefValue: Cardinal; fAddress: Word; fSubEntries: TDSBase; fArrayValues: TObjectList; fDSID: integer; fArrayMember: boolean; fRefCount : integer; fTypeName: string; function GetValue(idx: integer): Cardinal; function GetArrayInit: string; procedure SetSubEntries(const Value: TDSBase); function GetDataTypeAsString: string; function GetFullPathIdentifier: string; function GetDSBase: TDSBase; procedure SetArrayMember(const Value: boolean); procedure SetIdentifier(const Value: string); function GetInUse: boolean; function GetRefCount: integer; function GetClusterInit: string; function GetInitializationString: string; function GetArrayBaseType: TDSType; function GetIsArray: boolean; protected procedure AssignTo(Dest: TPersistent); override; procedure SaveToDynamicDefaults(aDS : TDSData; const cnt, doffset : integer); public constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure SaveToStream(aStream : TStream); procedure SaveToStrings(aStrings : TStrings; bDefine : boolean = false; bInCluster : boolean = false); procedure LoadFromStream(aStream : TStream); procedure AddValue(aValue : Cardinal); function AddValuesFromString(Calc : TNBCExpParser; sargs : string) : TDSType; function ValueCount : Word; function ArrayElementSize(bPad : boolean = true) : Word; function ElementSize(bPad : boolean = true) : Word; procedure IncRefCount; procedure DecRefCount; procedure AddThread(const aThreadName : string); function ThreadCount : integer; property DSBase : TDSBase read GetDSBase; property DSID : integer read fDSID write fDSID; property Identifier : string read fIdentifier write SetIdentifier; property TypeName : string read fTypeName write fTypeName; property DataType : TDSType read fDataType write fDataType; property DataTypeAsString : string read GetDataTypeAsString; property DefaultValue : Cardinal read fDefValue write fDefValue; property Address : Word read fAddress write fAddress; property SubEntries : TDSBase read fSubEntries write SetSubEntries; // used to store array types and cluster structure property Values[idx : integer] : Cardinal read GetValue; // used to store array default values property FullPathIdentifier : string read GetFullPathIdentifier; property InitializationString : string read GetInitializationString; property ArrayMember : boolean read fArrayMember write SetArrayMember; property BaseDataType : TDSType read GetArrayBaseType; property IsArray : boolean read GetIsArray; property InUse : boolean read GetInUse; property RefCount : integer read GetRefCount; end; TDSData = class private fDSStaticSize : integer; public TOC : DSTocEntries; TOCNames : array of string; StaticDefaults : array of byte; DynamicDefaults : array of byte; DopeVecs : DopeVectors; Head : Word; Tail : Word; constructor Create; function DynDSDefaultsOffset : Word; function DynDSDefaultsSize : Word; function DSCount : Word; function DSStaticSize : Word; function DVArrayOffset : Word; procedure SaveToStream(aStream : TStream); procedure SaveToSymbolTable(aStrings : TStrings); end; TDSBaseSortCompare = function(List: TDSBase; Index1, Index2: Integer): Integer; EDuplicateDataspaceEntry = class(Exception) public constructor Create(DE : TDataspaceEntry); end; // TDataspaceEntry = class; TDSBase = class(TCollection) private fParent: TPersistent; procedure ExchangeItems(Index1, Index2: Integer); function GetRoot: TDataspaceEntry; protected fEntryIndex : TStringList; function GetItem(Index: Integer): TDataspaceEntry; procedure SetItem(Index: Integer; Value: TDataspaceEntry); procedure AssignTo(Dest : TPersistent); override; procedure QuickSort(L, R: Integer; SCompare: TDSBaseSortCompare); function ResolveNestedArrayAddress(DS : TDSData; DV : DopeVector) : TDataspaceEntry; public constructor Create; virtual; destructor Destroy; override; function Add: TDataspaceEntry; function Insert(Index: Integer): TDataspaceEntry; function IndexOfName(const name : string) : integer; function FullPathName(DE : TDataspaceEntry) : string; function FindEntryByAddress(Addr : Word) : TDataspaceEntry; virtual; function FindEntryByFullName(const path : string) : TDataspaceEntry; virtual; function FindEntryByName(name : string) : TDataspaceEntry; virtual; procedure Sort; virtual; procedure CheckEntry(DE : TDataspaceEntry); property Items[Index: Integer]: TDataspaceEntry read GetItem write SetItem; default; property Parent : TPersistent read fParent write fParent; property Root : TDataspaceEntry read GetRoot; end; TDataDefs = class(TDSBase); TDataspace = class(TDSBase) private function GetCaseSensitive: boolean; procedure SetCaseSensitive(const Value: boolean); protected fVectors : DopeVectors; fMMTail: Word; fMMHead: Word; fDSIndexMap : TStringList; fDSList : TObjectList; function GetVector(index: Integer): DopeVector; protected procedure LoadArrayValuesFromDynamicData(DS : TDSData); function FinalizeDataspace(DS : TDSBase; addr : Word) : Word; procedure ProcessDopeVectors(aDS : TDSData; addr : Word); procedure ProcessArray(DE : TDataspaceEntry; aDS : TDSData; var doffset : integer); public constructor Create; override; destructor Destroy; override; procedure Compact; procedure SaveToStream(aStream : TStream); procedure SaveToStrings(aStrings : TStrings); procedure LoadFromStream(aStream : TStream); procedure LoadFromDSData(aDS : TDSData); procedure SaveToDSData(aDS : TDSData); function IndexOfEntryByAddress(Addr : Word) : Integer; function FindEntryByFullName(const path : string) : TDataspaceEntry; override; function FindEntryAndAddReference(const path : string) : TDataspaceEntry; procedure RemoveReferenceIfPresent(const path : string); procedure AddReference(DE : TDataspaceEntry); procedure RemoveReference(DE : TDataspaceEntry); function DataspaceIndex(const ident : string) : Integer; property Vectors[index : Integer] : DopeVector read GetVector; property MMHead : Word read fMMHead write fMMHead; property MMTail : Word read fMMTail write fMMTail; property CaseSensitive : boolean read GetCaseSensitive write SetCaseSensitive; end; ClumpDepArray = array of Byte; TClumpData = class public CRecs : ClumpRecords; ClumpDeps : ClumpDepArray; procedure SaveToStream(aStream : TStream); end; TRXEHeader = class public Head : RXEHeader; end; CodeArray = array of Word; TCodeSpaceAry = class public Code : CodeArray; function CodespaceCount : Word; procedure SaveToStream(aStream : TStream); end; TAsmArgument = class(TCollectionItem) private fValue: string; fDSID: integer; procedure SetValue(const Value: string); public property Value : string read fValue write SetValue; function IsQuoted(delim : char) : boolean; property DSID : integer read fDSID; function Evaluate(Calc : TNBCExpParser) : Extended; end; TOnNameToDSID = procedure(const aName : string; var aId : integer) of object; TAsmArguments = class(TCollection) private function GetItem(Index: Integer): TAsmArgument; procedure SetItem(Index: Integer; const Value: TAsmArgument); function GetAsString: string; protected procedure AssignTo(Dest: TPersistent); override; public constructor Create; function Add: TAsmArgument; function Insert(Index: Integer): TAsmArgument; property Items[Index: Integer]: TAsmArgument read GetItem write SetItem; default; property AsString : string read GetAsString; end; TClumpCode = class; TClump = class; TCodeSpace = class; TRXEProgram = class; TAsmLine = class(TCollectionItem) private fMacroExpansion: boolean; function GetAsString: string; procedure SetAsString(const Value: string); function GetClump: TClump; function GetCodeSpace: TCodeSpace; function GetPC: word; function GetOptimizable: boolean; protected fComment: string; fLabel: string; fArgs: TAsmArguments; fOpCode: TOpcode; fLineNum: integer; // fPC: word; fInstrSize : integer; fStartAddress : integer; fCode : CodeArray; fArity : Byte; fCC : Byte; fsop : ShortInt; fIsSpecial : boolean; fSpecialStr : string; procedure SetArgs(const Value: TAsmArguments); function GetClumpCode: TClumpCode; function CanBeShortOpEncoded : boolean; procedure FinalizeASMInstrSize; procedure FinalizeCode; procedure FinalizeArgs(bResolveDSIDs : Boolean); procedure FixupFinClump; function IsLabel(const name : string; var aID : integer) : boolean; procedure HandleNameToDSID(const name : string; var aId : integer); procedure RemoveVariableReference(const arg : string; const idx : integer); procedure RemoveVariableReferences; function FirmwareVersion : word; public constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure AddArgs(sargs : string); function InstructionSize : integer; procedure SaveToCode(var Store : CodeArray); property LineLabel : string read fLabel write fLabel; property Command : TOpcode read fOpCode write fOpCode; property Args : TAsmArguments read fArgs write SetArgs; property Comment : string read fComment write fComment; property LineNum : integer read fLineNum write fLineNum; property ProgramCounter : word read GetPC; property IsPartOfMacroExpansion : boolean read fMacroExpansion; property IsSpecial : boolean read fIsSpecial; // property ProgramCounter : word read fPC write fPC; property ClumpCode : TClumpCode read GetClumpCode; property Clump : TClump read GetClump; property CodeSpace : TCodeSpace read GetCodeSpace; property StartAddress : integer read fStartAddress; property AsString : string read GetAsString write SetAsString; property Optimizable : boolean read GetOptimizable; end; TClumpCode = class(TCollection) private fOnNameToDSID: TOnNameToDSID; fClump : TClump; protected function GetItem(Index: Integer): TAsmLine; procedure SetItem(Index: Integer; const Value: TAsmLine); procedure HandleNameToDSID(const aName : string; var aId : integer); procedure FixupFinalization; public constructor Create(aClump : TClump); destructor Destroy; override; function Add: TAsmLine; property Items[Index: Integer]: TAsmLine read GetItem write SetItem; default; property Clump : TClump read fClump; property OnNameToDSID : TOnNameToDSID read fOnNameToDSID write fOnNameToDSID; end; TClump = class(TCollectionItem) private fName: string; fClumpCode: TClumpCode; fIsSub: boolean; fDatasize : integer; fCode : CodeArray; fFilename: string; fLastLine: integer; function GetUpstream(aIndex: integer): string; function GetCodeSpace: TCodeSpace; function GetDataSize: Word; function GetStartAddress: Word; function GetDownstream(aIndex: integer): string; function GetDownCount: Byte; function GetUpCount: integer; function GetFireCount: Word; function GetCaseSensitive: boolean; function GetInUse: boolean; procedure RemoveOrNOPLine(AL, ALNext: TAsmLine; const idx: integer); function GetCallerCount: Byte; function GetIsMultithreaded: boolean; protected fLabelMap : TStringList; fUpstream : TStringList; fDownstream : TStringList; fCallers : TStringList; fRefCount : integer; procedure FinalizeClump; procedure HandleNameToDSID(const aname : string; var aId : integer); procedure RemoveReferences; public constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure Optimize(const level : Integer); procedure OptimizeMutexes; procedure RemoveUnusedLabels; procedure AddClumpDependencies(const opcode, args : string); procedure AddDependant(const clumpName : string); procedure AddAncestor(const clumpName : string); procedure AddCaller(const clumpName : string); procedure AddLabel(const lbl : string; Line : TAsmLine); function IndexOfLabel(const lbl : string) : integer; function AsmLineFromLabelIndex(const idx : integer) : TAsmLine; procedure IncRefCount; procedure DecRefCount; procedure SaveToCode(var Store : CodeArray); procedure SaveDependencies(var Store : ClumpDepArray); property CodeSpace : TCodeSpace read GetCodeSpace; property StartAddress : Word read GetStartAddress; property FireCount : Word read GetFireCount; property DataSize : Word read GetDataSize; property Name : string read fName write fName; property UpstreamClumps[aIndex : integer] : string read GetUpstream; property UpstreamCount : integer read GetUpCount; property DownstreamClumps[aIndex : integer] : string read GetDownstream; property DownstreamCount : Byte read GetDownCount; property CallerCount : Byte read GetCallerCount; property ClumpCode : TClumpCode read fClumpCode; property IsSubroutine : boolean read fIsSub write fIsSub; property CaseSensitive : boolean read GetCaseSensitive; property InUse : boolean read GetInUse; property Filename : string read fFilename write fFilename; property LastLine : integer read fLastLine write fLastLine; property IsMultithreaded : boolean read GetIsMultithreaded; end; TCodeSpace = class(TCollection) private fNXTInstructions : array of NXTInstruction; fOnNameToDSID: TOnNameToDSID; fCalc: TNBCExpParser; fCaseSensitive : Boolean; fDS: TDataspace; fFirmwareVersion: word; function GetCaseSensitive: boolean; procedure SetCaseSensitive(const Value: boolean); procedure BuildReferences; procedure InitializeInstructions; function IndexOfOpcode(op: TOpCode): integer; function OpcodeToStr(const op : TOpCode) : string; procedure SetFirmwareVersion(const Value: word); protected fRXEProg : TRXEProgram; fInitName: string; fAddresses : TObjectList; fFireCounts : TObjectList; fMultiThreadedClumps : TStrings; function GetItem(aIndex: Integer): TClump; procedure SetItem(aIndex: Integer; const aValue: TClump); function GetAddress(aIndex: Integer): Word; function GetFireCount(aIndex: integer): Byte; procedure FinalizeDependencies; procedure FinalizeAddressesAndFireCounts; procedure HandleNameToDSID(const aName : string; var aId : integer); function GetNXTInstruction(const idx : integer) : NXTInstruction; procedure RemoveUnusedLabels; public constructor Create(rp : TRXEProgram; ds : TDataspace); destructor Destroy; override; function Add: TClump; procedure Compact; procedure Optimize(const level : Integer); procedure OptimizeMutexes; procedure SaveToCodeData(aCD : TClumpData; aCode : TCodeSpaceAry); procedure SaveToSymbolTable(aStrings : TStrings); procedure SaveToStrings(aStrings : TStrings); function IndexOf(const aName : string) : integer; procedure AddReferenceIfPresent(aClump : TClump; const aName : string); procedure RemoveReferenceIfPresent(const aName : string); procedure MultiThread(const aName : string); property Items[aIndex: Integer]: TClump read GetItem write SetItem; default; property StartingAddresses[aIndex: Integer] : Word read GetAddress; property FireCounts[aIndex : integer] : Byte read GetFireCount; property InitialClumpName : string read fInitName write fInitName; property Calc : TNBCExpParser read fCalc write fCalc; property OnNameToDSID : TOnNameToDSID read fOnNameToDSID write fOnNameToDSID; property CaseSensitive : boolean read GetCaseSensitive write SetCaseSensitive; property Dataspace : TDataspace read fDS; property FirmwareVersion : word read fFirmwareVersion write SetFirmwareVersion; property RXEProgram : TRXEProgram read fRXEProg; end; TAsmArgType = (aatVariable, aatVarNoConst, aatVarOrNull, aatConstant, aatClumpID, aatLabelID, aatCluster, aatString, aatStringNoConst, aatArray, aatScalar, aatScalarNoConst, aatScalarOrNull, aatMutex, aatTypeName); TOnNBCCompilerMessage = procedure(const msg : string; var stop : boolean) of object; TRXEProgram = class(TPersistent) private fNXTInstructions : array of NXTInstruction; fOnCompMSg: TOnNBCCompilerMessage; fCalc: TNBCExpParser; fCaseSensitive: boolean; fStandardDefines: boolean; fExtraDefines: boolean; fCompVersion: byte; fIncDirs: TStrings; fCompilerOutput : TStrings; fSymbolTable : TStrings; fOptimizeLevel: integer; fReturnRequired: boolean; fDefines: TStrings; fWarningsOff: boolean; fEnhancedFirmware: boolean; fIgnoreSystemFile: boolean; fMaxErrors: word; fFirmwareVersion: word; fOnCompilerStatusChange: TCompilerStatusChangeEvent; fMaxPreProcDepth: word; procedure SetCaseSensitive(const Value: boolean); procedure SetStandardDefines(const Value: boolean); procedure SetExtraDefines(const Value: boolean); procedure SetCompVersion(const Value: byte); procedure SetIncDirs(const Value: TStrings); function GetSymbolTable: TStrings; function GetCurrentFile(bFullPath: boolean): string; function GetCurrentPath: string; procedure SetCurrentFile(const Value: string); procedure CreateReturnerClump(const basename: string); procedure CreateSpawnerClump(const basename: string); procedure SetDefines(const Value: TStrings); procedure LoadSystemFile(S: TStream); procedure SetLineCounter(const Value: integer); procedure SetFirmwareVersion(const Value: word); function IndexOfOpcode(op: TOpCode): integer; procedure InitializeInstructions; procedure ChunkLine(const state: TMainAsmState; namedTypes: TMapList; line: string; bUseCase: boolean; var lbl, opcode, args: string; var lineType: TAsmLineType; var bIgnoreDups: boolean); function DetermineLineType(const state: TMainAsmState; namedTypes: TMapList; op: string; bUseCase: boolean): TAsmLineType; function StrToOpcode(const op: string; bUseCase: boolean = False): TOpCode; function OpcodeToStr(const op: TOpCode): string; protected fDSData : TDSData; fClumpData : TClumpData; fCode : TCodeSpaceAry; fMainStateLast : TMainAsmState; fMainStateCurrent : TMainAsmState; fCurrentFile : string; fCurrentPath : string; fLineCounter : integer; fDD : TDataDefs; fDS : TDataspace; fCS : TCodeSpace; fHeader : RXEHeader; fNamedTypes : TMapList; fConstStrMap : TMapList; fCurrentClump : TClump; fCurrentStruct : TDataspaceEntry; fMsgs : TStrings; fBadProgram : boolean; fProgErrorCount : integer; fClumpUsesWait : boolean; fClumpUsesSign : boolean; fClumpUsesShift : boolean; fAbsCount : integer; fSignCount : integer; fShiftCount : integer; fVarI : integer; fVarJ : integer; fClumpName : string; fSkipCount : integer; fProductVersion : string; fSpawnedThreads : TStrings; fIgnoreDupDefs : boolean; fSpecialFunctions : TObjectList; fIgnoreLines : boolean; procedure DoCompilerStatusChange(const Status : string; const bDone : boolean = False); function GetVersion: byte; procedure SetVersion(const Value: byte); function GetFormat: string; procedure SetFormat(const Value: string); function GetClumpCount: Word; function GetCodespaceCount: Word; function GetDSCount: Word; function GetDSDefaultsSize: Word; function GetDSSize: Word; function GetDVArrayOffset: Word; function GetDynDSDefaultsOffset: Word; function GetDynDSDefaultsSize: Word; function GetMemMgrHead: Word; function GetMemMgrTail: Word; function GetNXTInstruction(const idx : integer) : NXTInstruction; procedure ReportProblem(const lineNo : integer; const fName, line, msg : string; err : boolean); procedure ProcessASMLine(aStrings : TStrings; var idx : integer); function ReplaceSpecialStringCharacters(const line : string) : string; procedure HandleConstantExpressions(AL : TAsmLine); procedure ProcessSpecialFunctions(AL : TAsmLine); procedure HandlePseudoOpcodes(AL : TAsmLine; op : TOpCode{; const args : string}); procedure UpdateHeader; procedure CheckArgs(AL : TAsmLine); procedure DoCompilerCheck(AL : TAsmLine; bIfCheck : boolean); procedure DoCompilerCheckType(AL : TAsmLine); procedure ValidateLabels(aClump : TClump); procedure HandleNameToDSID(const aName : string; var aId : integer); procedure CreateObjects; procedure FreeObjects; procedure InitializeHeader; procedure LoadSpecialFunctions; procedure HandleCalcParserError(Sender: TObject; E: Exception); procedure CreateWaitClump(const basename : string); procedure DefineWaitArgs(const basename : string); procedure DefineShiftArgs(const basename : string); function ReplaceTokens(const line : string) : string; procedure FixupComparisonCodes(Arg : TAsmArgument); procedure DefineVar(aVarName : string; dt :TDSType); procedure RegisterThreadForSpawning(aThreadName : string); procedure ProcessSpawnedThreads; procedure OutputUnusedItemWarnings; procedure CheckMainThread; procedure HandleSpecialFunctionSizeOf(Arg : TAsmArgument; const left, right, name : string); procedure HandleSpecialFunctionIsConst(Arg : TAsmArgument; const left, right, name : string); procedure HandleSpecialFunctionValueOf(Arg : TAsmArgument; const left, right, name : string); procedure HandleSpecialFunctionTypeOf(Arg : TAsmArgument; const left, right, name : string); procedure HandlePreprocStatusChange(Sender : TObject; const StatusMsg : string); property LineCounter : integer read fLineCounter write SetLineCounter; public constructor Create; destructor Destroy; override; procedure Clear; function Parse(aStream : TStream) : string; overload; function Parse(aStrings : TStrings) : string; overload; procedure LoadFromStream(aStream : TStream); function SaveToStream(aStream : TStream) : boolean; function SaveToFile(const filename : string) : boolean; procedure SaveToStrings(aStrings : TStrings); property Calc : TNBCExpParser read fCalc; property IncludeDirs : TStrings read fIncDirs write SetIncDirs; // header properties property FormatString : string read GetFormat write SetFormat; property Version : byte read GetVersion write SetVersion; property DSCount : Word read GetDSCount; property DSSize : Word read GetDSSize; property DSDefaultsSize : Word read GetDSDefaultsSize; property DynDSDefaultsOffset : Word read GetDynDSDefaultsOffset; property DynDSDefaultsSize : Word read GetDynDSDefaultsSize; property MemMgrHead : Word read GetMemMgrHead; property MemMgrTail : Word read GetMemMgrTail; property DVArrayOffset : Word read GetDVArrayOffset; property ClumpCount : Word read GetClumpCount; property CodespaceCount : Word read GetCodespaceCount; // dataspace definitions property property DataDefinitions : TDataDefs read fDD; // dataspace property property Dataspace : TDataspace read fDS; // codespace property property Codespace : TCodeSpace read fCS; property CompilerMessages : TStrings read fMsgs; property SymbolTable : TStrings read GetSymbolTable; property CompilerOutput : TStrings read fCompilerOutput; property CaseSensitive : boolean read fCaseSensitive write SetCaseSensitive; property CurrentFile : string read fCurrentFile write SetCurrentFile; property StandardDefines : boolean read fStandardDefines write SetStandardDefines; property ExtraDefines : boolean read fExtraDefines write SetExtraDefines; property CompilerVersion : byte read fCompVersion write SetCompVersion; property ReturnRequiredInSubroutine : boolean read fReturnRequired write fReturnRequired; property OptimizeLevel : integer read fOptimizeLevel write fOptimizeLevel; property Defines : TStrings read fDefines write SetDefines; property WarningsOff : boolean read fWarningsOff write fWarningsOff; property EnhancedFirmware : boolean read fEnhancedFirmware write fEnhancedFirmware; property FirmwareVersion : word read fFirmwareVersion write SetFirmwareVersion; property IgnoreSystemFile : boolean read fIgnoreSystemFile write fIgnoreSystemFile; property MaxErrors : word read fMaxErrors write fMaxErrors; property MaxPreprocessorDepth : word read fMaxPreProcDepth write fMaxPreProcDepth; property OnCompilerMessage : TOnNBCCompilerMessage read fOnCompMSg write fOnCompMsg; property OnCompilerStatusChange : TCompilerStatusChangeEvent read fOnCompilerStatusChange write fOnCompilerStatusChange; end; TRXEDumper = class private fNXTInstructions : array of NXTInstruction; fOnlyDumpCode: boolean; fFirmwareVersion: word; function TOCNameFromArg(DS : TDSData; const argValue: word): string; procedure SetFirmwareVersion(const Value: word); procedure InitializeInstructions; function IndexOfOpcode(op: TOpCode): integer; protected fHeader : TRXEHeader; fDSData : TDSData; fClumpData : TClumpData; fCode : TCodeSpaceAry; fFilename : string; fAddrList : TStringList; fFixups : TStringList; fTmpDataspace : TDataspace; function GetAddressLine(const str : string) : string; procedure FixupLabelStrings(aStrings : TStrings; const addr, line : integer); procedure OutputByteCodePhaseOne(aStrings : TStrings); procedure OutputDataspace(aStrings: TStrings); procedure OutputBytecode(aStrings: TStrings); procedure OutputClumpBeginEndIfNeeded(CD : TClumpData; const addr : integer; aStrings : TStrings); function ProcessInstructionArg(DS : TDSData; const addr : integer; const op : TOpCode; const argIdx : integer; const argValue : word) : string; function ProcessInstruction(DS : TDSData; CS : TCodeSpaceAry; const addr: integer; aStrings : TStrings): integer; procedure DumpRXEHeader(aStrings : TStrings); procedure DumpRXEDataSpace(aStrings : TStrings); procedure DumpRXEClumpRecords(aStrings : TStrings); procedure DumpRXECodeSpace(aStrings : TStrings); procedure FinalizeRXE; procedure InitializeRXE; function GetNXTInstruction(const idx : integer) : NXTInstruction; public { Public declarations } constructor Create; destructor Destroy; override; procedure LoadFromFile(const aFilename : string); procedure LoadFromStream(aStream : TStream); procedure SaveToFile(const aFilename : string); procedure SaveToStream(aStream : TStream); procedure DumpRXE(aStrings : TStrings); procedure Decompile(aStrings : TStrings); property Filename : string read fFilename write fFilename; property OnlyDumpCode : boolean read fOnlyDumpCode write fOnlyDumpCode; property FirmwareVersion : word read fFirmwareVersion write SetFirmwareVersion; end; const RXEHeaderText = 'FormatString = %0:s'#13#10 + 'Version = %1:d'#13#10 + 'DSCount = %2:d (0x%2:x)'#13#10 + 'DSSize = %3:d (0x%3:x)'#13#10 + 'DSStaticSize = %4:d (0x%4:x)'#13#10 + 'DSDefaultsSize = %5:d (0x%5:x)'#13#10 + 'DynDSDefaultsOffset = %6:d (0x%6:x)'#13#10 + 'DynDSDefaultsSize = %7:d (0x%7:x)'#13#10 + 'MemMgrHead = %8:d (0x%8:x)'#13#10 + 'MemMgrTail = %9:d (0x%9:x)'#13#10 + 'DVArrayOffset = %10:d (0x%10:x)'#13#10 + 'ClumpCount = %11:d (0x%11:x)'#13#10 + 'CodespaceCount = %12:d (0x%12:x)'; const STR_USES = 'precedes'; type TNXTInstructions = array of NXTInstruction; var NXTInstructions : array of NXTInstruction; const StandardOpcodeCount1x = 54; EnhancedOpcodeCount1x = 27; PseudoOpcodeCount1x = 39; NXTInstructionsCount1x = StandardOpcodeCount1x+EnhancedOpcodeCount1x+PseudoOpcodeCount1x; NXTInstructions1x : array[0..NXTInstructionsCount1x-1] of NXTInstruction = ( ( Encoding: OP_ADD ; CCType: 0; Arity: 3; Name: 'add'; ), ( Encoding: OP_SUB ; CCType: 0; Arity: 3; Name: 'sub'; ), ( Encoding: OP_NEG ; CCType: 0; Arity: 2; Name: 'neg'; ), ( Encoding: OP_MUL ; CCType: 0; Arity: 3; Name: 'mul'; ), ( Encoding: OP_DIV ; CCType: 0; Arity: 3; Name: 'div'; ), ( Encoding: OP_MOD ; CCType: 0; Arity: 3; Name: 'mod'; ), ( Encoding: OP_AND ; CCType: 0; Arity: 3; Name: 'and'; ), ( Encoding: OP_OR ; CCType: 0; Arity: 3; Name: 'or'; ), ( Encoding: OP_XOR ; CCType: 0; Arity: 3; Name: 'xor'; ), ( Encoding: OP_NOT ; CCType: 0; Arity: 2; Name: 'not'; ), ( Encoding: OP_CMNT ; CCType: 0; Arity: 2; Name: 'cmnt'; ), ( Encoding: OP_LSL ; CCType: 0; Arity: 3; Name: 'lsl'; ), ( Encoding: OP_LSR ; CCType: 0; Arity: 3; Name: 'lsr'; ), ( Encoding: OP_ASL ; CCType: 0; Arity: 3; Name: 'asl'; ), ( Encoding: OP_ASR ; CCType: 0; Arity: 3; Name: 'asr'; ), ( Encoding: OP_ROTL ; CCType: 0; Arity: 3; Name: 'rotl'; ), ( Encoding: OP_ROTR ; CCType: 0; Arity: 3; Name: 'rotr'; ), ( Encoding: OP_CMP ; CCType: 2; Arity: 3; Name: 'cmp'; ), ( Encoding: OP_TST ; CCType: 1; Arity: 2; Name: 'tst'; ), ( Encoding: OP_CMPSET ; CCType: 2; Arity: 4; Name: 'cmpset'; ), ( Encoding: OP_TSTSET ; CCType: 1; Arity: 3; Name: 'tstset'; ), ( Encoding: OP_INDEX ; CCType: 0; Arity: 3; Name: 'index'; ), ( Encoding: OP_REPLACE ; CCType: 0; Arity: 4; Name: 'replace'; ), ( Encoding: OP_ARRSIZE ; CCType: 0; Arity: 2; Name: 'arrsize'; ), ( Encoding: OP_ARRBUILD ; CCType: 0; Arity: 6; Name: 'arrbuild'; ), ( Encoding: OP_ARRSUBSET ; CCType: 0; Arity: 4; Name: 'arrsubset'; ), ( Encoding: OP_ARRINIT ; CCType: 0; Arity: 3; Name: 'arrinit'; ), ( Encoding: OP_MOV ; CCType: 0; Arity: 2; Name: 'mov'; ), ( Encoding: OP_SET ; CCType: 0; Arity: 2; Name: 'set'; ), ( Encoding: OP_FLATTEN ; CCType: 0; Arity: 2; Name: 'flatten'; ), ( Encoding: OP_UNFLATTEN ; CCType: 0; Arity: 4; Name: 'unflatten'; ), ( Encoding: OP_NUMTOSTRING ; CCType: 0; Arity: 2; Name: 'numtostr'; ), ( Encoding: OP_STRINGTONUM ; CCType: 0; Arity: 5; Name: 'strtonum'; ), ( Encoding: OP_STRCAT ; CCType: 0; Arity: 6; Name: 'strcat'; ), ( Encoding: OP_STRSUBSET ; CCType: 0; Arity: 4; Name: 'strsubset'; ), ( Encoding: OP_STRTOBYTEARR ; CCType: 0; Arity: 2; Name: 'strtoarr'; ), ( Encoding: OP_BYTEARRTOSTR ; CCType: 0; Arity: 2; Name: 'arrtostr'; ), ( Encoding: OP_JMP ; CCType: 0; Arity: 1; Name: 'jmp'; ), ( Encoding: OP_BRCMP ; CCType: 2; Arity: 3; Name: 'brcmp'; ), ( Encoding: OP_BRTST ; CCType: 1; Arity: 2; Name: 'brtst'; ), ( Encoding: OP_SYSCALL ; CCType: 0; Arity: 2; Name: 'syscall'; ), ( Encoding: OP_STOP ; CCType: 0; Arity: 1; Name: 'stop'; ), ( Encoding: OP_FINCLUMP ; CCType: 0; Arity: 2; Name: 'exit'; ), ( Encoding: OP_FINCLUMPIMMED ; CCType: 0; Arity: 1; Name: 'exitto'; ), ( Encoding: OP_ACQUIRE ; CCType: 0; Arity: 1; Name: 'acquire'; ), ( Encoding: OP_RELEASE ; CCType: 0; Arity: 1; Name: 'release'; ), ( Encoding: OP_SUBCALL ; CCType: 0; Arity: 2; Name: 'subcall'; ), ( Encoding: OP_SUBRET ; CCType: 0; Arity: 1; Name: 'subret'; ), ( Encoding: OP_SETIN ; CCType: 0; Arity: 3; Name: 'setin'; ), ( Encoding: OP_SETOUT ; CCType: 0; Arity: 6; Name: 'setout'; ), ( Encoding: OP_GETIN ; CCType: 0; Arity: 3; Name: 'getin'; ), ( Encoding: OP_GETOUT ; CCType: 0; Arity: 3; Name: 'getout'; ), ( Encoding: OP_WAIT ; CCType: 0; Arity: 1; Name: 'wait'; ), ( Encoding: OP_GETTICK ; CCType: 0; Arity: 1; Name: 'gettick'; ), // enhanced firmware opcodes ( Encoding: OPS_WAITV ; CCType: 0; Arity: 1; Name: 'waitv'; ), ( Encoding: OPS_ABS ; CCType: 0; Arity: 2; Name: 'abs'; ), ( Encoding: OPS_SIGN ; CCType: 0; Arity: 2; Name: 'sign'; ), ( Encoding: OPS_STOPCLUMP ; CCType: 0; Arity: 1; Name: 'stopthread'; ), ( Encoding: OPS_START ; CCType: 0; Arity: 1; Name: 'start'; ), ( Encoding: OPS_PRIORITY ; CCType: 0; Arity: 2; Name: 'priority'; ), ( Encoding: OPS_FMTNUM ; CCType: 0; Arity: 3; Name: 'fmtnum'; ), ( Encoding: OPS_ARROP ; CCType: 0; Arity: 5; Name: 'arrop'; ), ( Encoding: OPS_ACOS ; CCType: 0; Arity: 2; Name: 'acos'; ), ( Encoding: OPS_ASIN ; CCType: 0; Arity: 2; Name: 'asin'; ), ( Encoding: OPS_ATAN ; CCType: 0; Arity: 2; Name: 'atan'; ), ( Encoding: OPS_CEIL ; CCType: 0; Arity: 2; Name: 'ceil'; ), ( Encoding: OPS_EXP ; CCType: 0; Arity: 2; Name: 'exp'; ), ( Encoding: OPS_FABS ; CCType: 0; Arity: 2; Name: 'fabs'; ), ( Encoding: OPS_FLOOR ; CCType: 0; Arity: 2; Name: 'floor'; ), ( Encoding: OPS_SQRT ; CCType: 0; Arity: 2; Name: 'sqrt'; ), ( Encoding: OPS_TAN ; CCType: 0; Arity: 2; Name: 'tan'; ), ( Encoding: OPS_TANH ; CCType: 0; Arity: 2; Name: 'tanh'; ), ( Encoding: OPS_COS ; CCType: 0; Arity: 2; Name: 'cos'; ), ( Encoding: OPS_COSH ; CCType: 0; Arity: 2; Name: 'cosh'; ), ( Encoding: OPS_LOG ; CCType: 0; Arity: 2; Name: 'log'; ), ( Encoding: OPS_LOG10 ; CCType: 0; Arity: 2; Name: 'log10'; ), ( Encoding: OPS_SIN ; CCType: 0; Arity: 2; Name: 'sin'; ), ( Encoding: OPS_SINH ; CCType: 0; Arity: 2; Name: 'sinh'; ), ( Encoding: OPS_ATAN2 ; CCType: 0; Arity: 3; Name: 'atan2'; ), ( Encoding: OPS_FMOD ; CCType: 0; Arity: 3; Name: 'fmod'; ), ( Encoding: OPS_POW ; CCType: 0; Arity: 3; Name: 'pow'; ), // pseudo-opcodes ( Encoding: OPS_THREAD ; CCType: 0; Arity: 0; Name: 'thread'; ), ( Encoding: OPS_ENDT ; CCType: 0; Arity: 0; Name: 'endt'; ), ( Encoding: OPS_SUBROUTINE ; CCType: 0; Arity: 0; Name: 'subroutine'; ), ( Encoding: OPS_REQUIRES ; CCType: 0; Arity: 0; Name: 'follows'; ), ( Encoding: OPS_USES ; CCType: 0; Arity: 0; Name: STR_USES; ), ( Encoding: OPS_SEGMENT ; CCType: 0; Arity: 0; Name: 'segment'; ), ( Encoding: OPS_ENDS ; CCType: 0; Arity: 0; Name: 'ends'; ), ( Encoding: OPS_TYPEDEF ; CCType: 0; Arity: 0; Name: 'typedef'; ), ( Encoding: OPS_STRUCT ; CCType: 0; Arity: 0; Name: 'struct'; ), ( Encoding: OPS_DB ; CCType: 0; Arity: 0; Name: 'db'; ), ( Encoding: OPS_BYTE ; CCType: 0; Arity: 0; Name: 'byte'; ), ( Encoding: OPS_SBYTE ; CCType: 0; Arity: 0; Name: 'sbyte'; ), ( Encoding: OPS_UBYTE ; CCType: 0; Arity: 0; Name: 'ubyte'; ), ( Encoding: OPS_DW ; CCType: 0; Arity: 0; Name: 'dw'; ), ( Encoding: OPS_WORD ; CCType: 0; Arity: 0; Name: 'word'; ), ( Encoding: OPS_SWORD ; CCType: 0; Arity: 0; Name: 'sword'; ), ( Encoding: OPS_UWORD ; CCType: 0; Arity: 0; Name: 'uword'; ), ( Encoding: OPS_DD ; CCType: 0; Arity: 0; Name: 'dd'; ), ( Encoding: OPS_DWORD ; CCType: 0; Arity: 0; Name: 'dword'; ), ( Encoding: OPS_SDWORD ; CCType: 0; Arity: 0; Name: 'sdword'; ), ( Encoding: OPS_UDWORD ; CCType: 0; Arity: 0; Name: 'udword'; ), ( Encoding: OPS_LONG ; CCType: 0; Arity: 0; Name: 'long'; ), ( Encoding: OPS_SLONG ; CCType: 0; Arity: 0; Name: 'slong'; ), ( Encoding: OPS_ULONG ; CCType: 0; Arity: 0; Name: 'ulong'; ), ( Encoding: OPS_VOID ; CCType: 0; Arity: 0; Name: 'void'; ), ( Encoding: OPS_MUTEX ; CCType: 0; Arity: 0; Name: 'mutex'; ), ( Encoding: OPS_FLOAT ; CCType: 0; Arity: 0; Name: 'float'; ), ( Encoding: OPS_CALL ; CCType: 0; Arity: 1; Name: 'call'; ), ( Encoding: OPS_RETURN ; CCType: 0; Arity: 0; Name: 'return'; ), ( Encoding: OPS_STRINDEX ; CCType: 0; Arity: 3; Name: 'strindex'; ), ( Encoding: OPS_STRREPLACE ; CCType: 0; Arity: 4; Name: 'strreplace'; ), ( Encoding: OPS_SHL ; CCType: 0; Arity: 3; Name: 'shl'; ), ( Encoding: OPS_SHR ; CCType: 0; Arity: 3; Name: 'shr'; ), ( Encoding: OPS_STRLEN ; CCType: 0; Arity: 2; Name: 'strlen'; ), ( Encoding: OPS_COMPCHK ; CCType: 0; Arity: 3; Name: 'compchk'; ), ( Encoding: OPS_COMPIF ; CCType: 0; Arity: 3; Name: 'compif'; ), ( Encoding: OPS_COMPELSE ; CCType: 0; Arity: 0; Name: 'compelse'; ), ( Encoding: OPS_COMPEND ; CCType: 0; Arity: 0; Name: 'compend'; ), ( Encoding: OPS_COMPCHKTYPE ; CCType: 0; Arity: 2; Name: 'compchktype'; ) ); StandardOpcodeCount2x = 56; EnhancedOpcodeCount2x = 38; PseudoOpcodeCount2x = 39; NXTInstructionsCount2x = StandardOpcodeCount2x+EnhancedOpcodeCount2x+PseudoOpcodeCount2x; NXTInstructions2x : array[0..NXTInstructionsCount2x-1] of NXTInstruction = ( ( Encoding: OP_ADD ; CCType: 0; Arity: 3; Name: 'add'; ), ( Encoding: OP_SUB ; CCType: 0; Arity: 3; Name: 'sub'; ), ( Encoding: OP_NEG ; CCType: 0; Arity: 2; Name: 'neg'; ), ( Encoding: OP_MUL ; CCType: 0; Arity: 3; Name: 'mul'; ), ( Encoding: OP_DIV ; CCType: 0; Arity: 3; Name: 'div'; ), ( Encoding: OP_MOD ; CCType: 0; Arity: 3; Name: 'mod'; ), ( Encoding: OP_AND ; CCType: 0; Arity: 3; Name: 'and'; ), ( Encoding: OP_OR ; CCType: 0; Arity: 3; Name: 'or'; ), ( Encoding: OP_XOR ; CCType: 0; Arity: 3; Name: 'xor'; ), ( Encoding: OP_NOT ; CCType: 0; Arity: 2; Name: 'not'; ), ( Encoding: OP_CMNT ; CCType: 0; Arity: 2; Name: 'cmnt'; ), ( Encoding: OP_LSL ; CCType: 0; Arity: 3; Name: 'lsl'; ), ( Encoding: OP_LSR ; CCType: 0; Arity: 3; Name: 'lsr'; ), ( Encoding: OP_ASL ; CCType: 0; Arity: 3; Name: 'asl'; ), ( Encoding: OP_ASR ; CCType: 0; Arity: 3; Name: 'asr'; ), ( Encoding: OP_ROTL ; CCType: 0; Arity: 3; Name: 'rotl'; ), ( Encoding: OP_ROTR ; CCType: 0; Arity: 3; Name: 'rotr'; ), ( Encoding: OP_CMP ; CCType: 2; Arity: 3; Name: 'cmp'; ), ( Encoding: OP_TST ; CCType: 1; Arity: 2; Name: 'tst'; ), ( Encoding: OP_CMPSET ; CCType: 2; Arity: 4; Name: 'cmpset'; ), ( Encoding: OP_TSTSET ; CCType: 1; Arity: 3; Name: 'tstset'; ), ( Encoding: OP_INDEX ; CCType: 0; Arity: 3; Name: 'index'; ), ( Encoding: OP_REPLACE ; CCType: 0; Arity: 4; Name: 'replace'; ), ( Encoding: OP_ARRSIZE ; CCType: 0; Arity: 2; Name: 'arrsize'; ), ( Encoding: OP_ARRBUILD ; CCType: 0; Arity: 6; Name: 'arrbuild'; ), ( Encoding: OP_ARRSUBSET ; CCType: 0; Arity: 4; Name: 'arrsubset'; ), ( Encoding: OP_ARRINIT ; CCType: 0; Arity: 3; Name: 'arrinit'; ), ( Encoding: OP_MOV ; CCType: 0; Arity: 2; Name: 'mov'; ), ( Encoding: OP_SET ; CCType: 0; Arity: 2; Name: 'set'; ), ( Encoding: OP_FLATTEN ; CCType: 0; Arity: 2; Name: 'flatten'; ), ( Encoding: OP_UNFLATTEN ; CCType: 0; Arity: 4; Name: 'unflatten'; ), ( Encoding: OP_NUMTOSTRING ; CCType: 0; Arity: 2; Name: 'numtostr'; ), ( Encoding: OP_STRINGTONUM ; CCType: 0; Arity: 5; Name: 'strtonum'; ), ( Encoding: OP_STRCAT ; CCType: 0; Arity: 6; Name: 'strcat'; ), ( Encoding: OP_STRSUBSET ; CCType: 0; Arity: 4; Name: 'strsubset'; ), ( Encoding: OP_STRTOBYTEARR ; CCType: 0; Arity: 2; Name: 'strtoarr'; ), ( Encoding: OP_BYTEARRTOSTR ; CCType: 0; Arity: 2; Name: 'arrtostr'; ), ( Encoding: OP_JMP ; CCType: 0; Arity: 1; Name: 'jmp'; ), ( Encoding: OP_BRCMP ; CCType: 2; Arity: 3; Name: 'brcmp'; ), ( Encoding: OP_BRTST ; CCType: 1; Arity: 2; Name: 'brtst'; ), ( Encoding: OP_SYSCALL ; CCType: 0; Arity: 2; Name: 'syscall'; ), ( Encoding: OP_STOP ; CCType: 0; Arity: 1; Name: 'stop'; ), ( Encoding: OP_FINCLUMP ; CCType: 0; Arity: 2; Name: 'exit'; ), ( Encoding: OP_FINCLUMPIMMED ; CCType: 0; Arity: 1; Name: 'exitto'; ), ( Encoding: OP_ACQUIRE ; CCType: 0; Arity: 1; Name: 'acquire'; ), ( Encoding: OP_RELEASE ; CCType: 0; Arity: 1; Name: 'release'; ), ( Encoding: OP_SUBCALL ; CCType: 0; Arity: 2; Name: 'subcall'; ), ( Encoding: OP_SUBRET ; CCType: 0; Arity: 1; Name: 'subret'; ), ( Encoding: OP_SETIN ; CCType: 0; Arity: 3; Name: 'setin'; ), ( Encoding: OP_SETOUT ; CCType: 0; Arity: 6; Name: 'setout'; ), ( Encoding: OP_GETIN ; CCType: 0; Arity: 3; Name: 'getin'; ), ( Encoding: OP_GETOUT ; CCType: 0; Arity: 3; Name: 'getout'; ), ( Encoding: OP_WAIT ; CCType: 0; Arity: 2; Name: 'wait2'; ), ( Encoding: OP_GETTICK ; CCType: 0; Arity: 1; Name: 'gettick'; ), ( Encoding: OP_SQRT_2 ; CCType: 0; Arity: 2; Name: 'sqrt'; ), ( Encoding: OP_ABS_2 ; CCType: 0; Arity: 2; Name: 'abs'; ), // enhanced firmware opcodes ( Encoding: OPS_WAITI_2 ; CCType: 0; Arity: 1; Name: 'wait'; ), ( Encoding: OPS_WAITV_2 ; CCType: 0; Arity: 1; Name: 'waitv'; ), ( Encoding: OPS_SIGN_2 ; CCType: 0; Arity: 2; Name: 'sign'; ), ( Encoding: OPS_STOPCLUMP_2 ; CCType: 0; Arity: 1; Name: 'stopthread'; ), ( Encoding: OPS_START_2 ; CCType: 0; Arity: 1; Name: 'start'; ), ( Encoding: OPS_PRIORITY_2 ; CCType: 0; Arity: 2; Name: 'priority'; ), ( Encoding: OPS_FMTNUM_2 ; CCType: 0; Arity: 3; Name: 'fmtnum'; ), ( Encoding: OPS_ARROP_2 ; CCType: 0; Arity: 5; Name: 'arrop'; ), ( Encoding: OPS_ACOS_2 ; CCType: 0; Arity: 2; Name: 'acos'; ), ( Encoding: OPS_ASIN_2 ; CCType: 0; Arity: 2; Name: 'asin'; ), ( Encoding: OPS_ATAN_2 ; CCType: 0; Arity: 2; Name: 'atan'; ), ( Encoding: OPS_CEIL_2 ; CCType: 0; Arity: 2; Name: 'ceil'; ), ( Encoding: OPS_EXP_2 ; CCType: 0; Arity: 2; Name: 'exp'; ), ( Encoding: OPS_FLOOR_2 ; CCType: 0; Arity: 2; Name: 'floor'; ), ( Encoding: OPS_TAN_2 ; CCType: 0; Arity: 2; Name: 'tan'; ), ( Encoding: OPS_TANH_2 ; CCType: 0; Arity: 2; Name: 'tanh'; ), ( Encoding: OPS_COS_2 ; CCType: 0; Arity: 2; Name: 'cos'; ), ( Encoding: OPS_COSH_2 ; CCType: 0; Arity: 2; Name: 'cosh'; ), ( Encoding: OPS_LOG_2 ; CCType: 0; Arity: 2; Name: 'log'; ), ( Encoding: OPS_LOG10_2 ; CCType: 0; Arity: 2; Name: 'log10'; ), ( Encoding: OPS_SIN_2 ; CCType: 0; Arity: 2; Name: 'sin'; ), ( Encoding: OPS_SINH_2 ; CCType: 0; Arity: 2; Name: 'sinh'; ), ( Encoding: OPS_TRUNC_2 ; CCType: 0; Arity: 2; Name: 'trunc'; ), ( Encoding: OPS_FRAC_2 ; CCType: 0; Arity: 2; Name: 'frac'; ), ( Encoding: OPS_ATAN2_2 ; CCType: 0; Arity: 3; Name: 'atan2'; ), ( Encoding: OPS_POW_2 ; CCType: 0; Arity: 3; Name: 'pow'; ), ( Encoding: OPS_MULDIV_2 ; CCType: 0; Arity: 4; Name: 'muldiv'; ), ( Encoding: OPS_ACOSD_2 ; CCType: 0; Arity: 2; Name: 'acosd'; ), ( Encoding: OPS_ASIND_2 ; CCType: 0; Arity: 2; Name: 'asind'; ), ( Encoding: OPS_ATAND_2 ; CCType: 0; Arity: 2; Name: 'atand'; ), ( Encoding: OPS_TAND_2 ; CCType: 0; Arity: 2; Name: 'tand'; ), ( Encoding: OPS_TANHD_2 ; CCType: 0; Arity: 2; Name: 'tanhd'; ), ( Encoding: OPS_COSD_2 ; CCType: 0; Arity: 2; Name: 'cosd'; ), ( Encoding: OPS_COSHD_2 ; CCType: 0; Arity: 2; Name: 'coshd'; ), ( Encoding: OPS_SIND_2 ; CCType: 0; Arity: 2; Name: 'sind'; ), ( Encoding: OPS_SINHD_2 ; CCType: 0; Arity: 2; Name: 'sinhd'; ), ( Encoding: OPS_ATAN2D_2 ; CCType: 0; Arity: 3; Name: 'atan2d'; ), ( Encoding: OPS_ADDROF ; CCType: 0; Arity: 3; Name: 'addrof'; ), // pseudo-opcodes ( Encoding: OPS_THREAD ; CCType: 0; Arity: 0; Name: 'thread'; ), ( Encoding: OPS_ENDT ; CCType: 0; Arity: 0; Name: 'endt'; ), ( Encoding: OPS_SUBROUTINE ; CCType: 0; Arity: 0; Name: 'subroutine'; ), ( Encoding: OPS_REQUIRES ; CCType: 0; Arity: 0; Name: 'follows'; ), ( Encoding: OPS_USES ; CCType: 0; Arity: 0; Name: STR_USES; ), ( Encoding: OPS_SEGMENT ; CCType: 0; Arity: 0; Name: 'segment'; ), ( Encoding: OPS_ENDS ; CCType: 0; Arity: 0; Name: 'ends'; ), ( Encoding: OPS_TYPEDEF ; CCType: 0; Arity: 0; Name: 'typedef'; ), ( Encoding: OPS_STRUCT ; CCType: 0; Arity: 0; Name: 'struct'; ), ( Encoding: OPS_DB ; CCType: 0; Arity: 0; Name: 'db'; ), ( Encoding: OPS_BYTE ; CCType: 0; Arity: 0; Name: 'byte'; ), ( Encoding: OPS_SBYTE ; CCType: 0; Arity: 0; Name: 'sbyte'; ), ( Encoding: OPS_UBYTE ; CCType: 0; Arity: 0; Name: 'ubyte'; ), ( Encoding: OPS_DW ; CCType: 0; Arity: 0; Name: 'dw'; ), ( Encoding: OPS_WORD ; CCType: 0; Arity: 0; Name: 'word'; ), ( Encoding: OPS_SWORD ; CCType: 0; Arity: 0; Name: 'sword'; ), ( Encoding: OPS_UWORD ; CCType: 0; Arity: 0; Name: 'uword'; ), ( Encoding: OPS_DD ; CCType: 0; Arity: 0; Name: 'dd'; ), ( Encoding: OPS_DWORD ; CCType: 0; Arity: 0; Name: 'dword'; ), ( Encoding: OPS_SDWORD ; CCType: 0; Arity: 0; Name: 'sdword'; ), ( Encoding: OPS_UDWORD ; CCType: 0; Arity: 0; Name: 'udword'; ), ( Encoding: OPS_LONG ; CCType: 0; Arity: 0; Name: 'long'; ), ( Encoding: OPS_SLONG ; CCType: 0; Arity: 0; Name: 'slong'; ), ( Encoding: OPS_ULONG ; CCType: 0; Arity: 0; Name: 'ulong'; ), ( Encoding: OPS_VOID ; CCType: 0; Arity: 0; Name: 'void'; ), ( Encoding: OPS_MUTEX ; CCType: 0; Arity: 0; Name: 'mutex'; ), ( Encoding: OPS_FLOAT ; CCType: 0; Arity: 0; Name: 'float'; ), ( Encoding: OPS_CALL ; CCType: 0; Arity: 1; Name: 'call'; ), ( Encoding: OPS_RETURN ; CCType: 0; Arity: 0; Name: 'return'; ), ( Encoding: OPS_STRINDEX ; CCType: 0; Arity: 3; Name: 'strindex'; ), ( Encoding: OPS_STRREPLACE ; CCType: 0; Arity: 4; Name: 'strreplace'; ), ( Encoding: OPS_SHL ; CCType: 0; Arity: 3; Name: 'shl'; ), ( Encoding: OPS_SHR ; CCType: 0; Arity: 3; Name: 'shr'; ), ( Encoding: OPS_STRLEN ; CCType: 0; Arity: 2; Name: 'strlen'; ), ( Encoding: OPS_COMPCHK ; CCType: 0; Arity: 3; Name: 'compchk'; ), ( Encoding: OPS_COMPIF ; CCType: 0; Arity: 3; Name: 'compif'; ), ( Encoding: OPS_COMPELSE ; CCType: 0; Arity: 0; Name: 'compelse'; ), ( Encoding: OPS_COMPEND ; CCType: 0; Arity: 0; Name: 'compend'; ), ( Encoding: OPS_COMPCHKTYPE ; CCType: 0; Arity: 2; Name: 'compchktype'; ) ); type ShortOpEncoding = record Encoding : Byte; LongEncoding : TOpCode; GCName : String; ShortOp : String; end; const ShortOpEncodingsCount = 4; ShortOpEncodings : array[0..ShortOpEncodingsCount-1] of ShortOpEncoding = ( ( Encoding: 0; LongEncoding: OP_MOV ; GCName: 'MOV' ; ShortOp: 'OP_MOV'; ), ( Encoding: 1; LongEncoding: OP_ACQUIRE; GCName: 'ACQUIRE'; ShortOp: 'OP_ACQUIRE'; ), ( Encoding: 2; LongEncoding: OP_RELEASE; GCName: 'RELEASE'; ShortOp: 'OP_RELEASE'; ), ( Encoding: 3; LongEncoding: OP_SUBCALL; GCName: 'SUBCALL'; ShortOp: 'OP_SUBCALL'; ) ); const TC_VOID = 0; TC_UBYTE = 1; TC_SBYTE = 2; TC_UWORD = 3; TC_SWORD = 4; TC_ULONG = 5; TC_SLONG = 6; TC_ARRAY = 7; TC_CLUSTER = 8; TC_MUTEX = 9; TC_FLOAT = 10; const SHOP_MASK = $08; // b00001000 INST_MASK = $F0; // b11110000 CC_MASK = $07; // b00000111 function TypeToStr(const TypeDesc : byte) : string; overload; function TypeToStr(const aType : TDSType) : string; overload; function StrToType(const stype : string; bUseCase : Boolean = false) : TDSType; function GenerateTOCName(const TypeDesc : byte; const idx : Int64; const fmt : string = '%s%4.4x') : string; function ShortOpEncoded(const b : byte) : boolean; function CompareCodeToStr(const cc : byte) : string; function ShortOpToLongOp(const op : byte) : TOpCode; function GenericIDToStr(genIDs : array of IDRec; const ID : integer) : string; function SysCallMethodIDToStr(const fver : word; const ID : integer) : string; function InputFieldIDToStr(const ID : integer) : string; function OutputFieldIDToStr(const ID : integer) : string; procedure LoadRXEHeader(H : TRXEHeader; aStream : TStream); procedure LoadRXEDataSpace(H : TRXEHeader; DS : TDSData; aStream : TStream); procedure LoadRXEClumpRecords(H : TRXEHeader; CD : TClumpData; aStream : TStream); procedure LoadRXECodeSpace(H : TRXEHeader; CS : TCodeSpaceAry; aStream : TStream); function GetArgDataType(val : Extended): TDSType; function ExpectedArgType(const firmVer : word; const op : TOpCode; const argIdx: integer): TAsmArgType; function ProcessCluster(aDS : TDSData; Item : TDataspaceEntry; idx : Integer; var staticIndex : Integer) : integer; function GetTypeHint(DSpace : TDataspace; const aLine: TASMLine; const idx : integer; bEnhanced : boolean): TDSType; function CreateConstantVar(DSpace : TDataspace; val : Extended; bIncCount : boolean; aTypeHint : TDSType = dsVoid) : string; procedure InstantiateCluster(DD : TDataDefs; DE: TDataspaceEntry; const clustername: string); procedure HandleVarDecl(DD : TDataDefs; NT : TMapList; bCaseSensitive : boolean; DSE : TDataspaceEntry; albl, aopcode : string; sttFunc : TSTTFuncType); implementation uses StrUtils, Math, uNBCLexer, uCommonUtils, uVersionInfo, uLocalizedStrings, {$IFDEF FAST_MM}FastStrings, {$ENDIF} NBCCommonData, NXTDefsData; const CLUMP_FMT = 't%3.3d'; DWORD_LEN = 4; SubroutineReturnAddressType = dsUByte; type TCardinalObject = class protected fValue : Cardinal; public constructor Create(aValue : Cardinal); property Value : Cardinal read fValue; end; TIntegerObject = class protected fValue : Integer; public constructor Create(aValue : Integer); property Value : Integer read fValue; end; TSpecialFunctionExecute = procedure(Arg : TAsmArgument; const left, right, name : string) of object; TSpecialFunction = class private fFunc: string; fExecute: TSpecialFunctionExecute; public property Func : string read fFunc write fFunc; property Execute : TSpecialFunctionExecute read fExecute write fExecute; end; function RoundToByteSize(addr : Word; size : byte) : Word; var x : Word; begin x := Word(addr mod size); if x <> 0 then Result := Word(addr + size - x) else Result := addr; end; function QuotedString(const sargs : string) : boolean; var p1, len, L1, p2, L2 : integer; begin len := Length(sargs); p1 := Pos('''', sargs); p2 := Pos('"', sargs); L1 := LastDelimiter('''', sargs); L2 := LastDelimiter('"', sargs); Result := ((p1 = 1) and (L1 = len)) or ((p2 = 1) and (L2 = len)); end; function StripExtraQuotes(str : string) : string; var tmp : string; begin Result := str; while true do begin if QuotedString(Result) then begin tmp := Result; System.Delete(tmp, 1, 1); System.Delete(tmp, Length(tmp), 1); if QuotedString(tmp) then begin // we have a string with a duplicate set of quotation marks Result := tmp; end else break; end else break; end; end; function Replace(const str : string; const src, rep : string) : string; begin {$IFDEF FAST_MM} Result := FastReplace(str, src, rep, True); {$ELSE} Result := StringReplace(str, src, rep, [rfReplaceAll]); {$ENDIF} end; function IndexOfIOMapID(iomapID : integer) : integer; var i : integer; begin Result := -1; for i := Low(IOMapFieldIDs) to High(IOMapFieldIDs) do begin if IOMapFieldIDs[i].ID = iomapID then begin Result := i; Break; end; end; end; function IndexOfIOMapName(const aName : string) : integer; var i : integer; begin Result := -1; for i := Low(IOMapFieldIDs) to High(IOMapFieldIDs) do begin if IOMapFieldIDs[i].Name = aName then begin Result := i; Break; end; end; end; function LongOpToShortOp(op : TOpCode) : ShortInt; var i : integer; SOE : ShortOpEncoding; begin Result := -1; for i := Low(ShortOpEncodings) to High(ShortOpEncodings) do begin SOE := ShortOpEncodings[i]; if SOE.LongEncoding = op then begin Result := SOE.Encoding; Break; end; end; end; function TypeToStr(const aType : TDSType) : string; begin Result := TypeToStr(Byte(Ord(aType))); end; const NXTTypes : array[0..17] of NXTInstruction = ( ( Encoding: OPS_DB ; CCType: 0; Arity: 0; Name: 'db'; ), ( Encoding: OPS_BYTE ; CCType: 0; Arity: 0; Name: 'byte'; ), ( Encoding: OPS_SBYTE ; CCType: 0; Arity: 0; Name: 'sbyte'; ), ( Encoding: OPS_UBYTE ; CCType: 0; Arity: 0; Name: 'ubyte'; ), ( Encoding: OPS_DW ; CCType: 0; Arity: 0; Name: 'dw'; ), ( Encoding: OPS_WORD ; CCType: 0; Arity: 0; Name: 'word'; ), ( Encoding: OPS_SWORD ; CCType: 0; Arity: 0; Name: 'sword'; ), ( Encoding: OPS_UWORD ; CCType: 0; Arity: 0; Name: 'uword'; ), ( Encoding: OPS_DD ; CCType: 0; Arity: 0; Name: 'dd'; ), ( Encoding: OPS_DWORD ; CCType: 0; Arity: 0; Name: 'dword'; ), ( Encoding: OPS_SDWORD ; CCType: 0; Arity: 0; Name: 'sdword'; ), ( Encoding: OPS_UDWORD ; CCType: 0; Arity: 0; Name: 'udword'; ), ( Encoding: OPS_LONG ; CCType: 0; Arity: 0; Name: 'long'; ), ( Encoding: OPS_SLONG ; CCType: 0; Arity: 0; Name: 'slong'; ), ( Encoding: OPS_ULONG ; CCType: 0; Arity: 0; Name: 'ulong'; ), ( Encoding: OPS_VOID ; CCType: 0; Arity: 0; Name: 'void'; ), ( Encoding: OPS_MUTEX ; CCType: 0; Arity: 0; Name: 'mutex'; ), ( Encoding: OPS_FLOAT ; CCType: 0; Arity: 0; Name: 'float'; ) ); function StrToType(const stype : string; bUseCase : Boolean = false) : TDSType; var op : TOpCode; i : integer; tmpName : string; begin op := OPS_INVALID; for i := Low(NXTTypes) to High(NXTTypes) do begin if bUseCase then tmpName := stype else tmpName := AnsiLowerCase(stype); if NXTTypes[i].Name = tmpName then begin op := NXTTypes[i].Encoding; break; end; end; case op of OPS_DB, OPS_BYTE, OPS_UBYTE : Result := dsUByte; OPS_SBYTE : Result := dsSByte; OPS_DW, OPS_WORD, OPS_UWORD : Result := dsUWord; OPS_SWORD : Result := dsSWord; OPS_DD, OPS_DWORD, OPS_UDWORD, OPS_LONG, OPS_ULONG : Result := dsULong; OPS_SDWORD, OPS_SLONG : Result := dsSLong; OPS_MUTEX : Result := dsMutex; OPS_FLOAT : Result := dsFloat; else Result := dsVoid; end; end; function ValToStr(const aType : TDSType; aVal : Cardinal) : string; begin if aVal = 0 then Result := '' // don't output question marks needlessly else case aType of dsVoid : Result := ''; dsUByte : Result := Format('%u', [Byte(aVal)]); dsSByte : Result := Format('%d', [Shortint(aVal)]); dsUWord : Result := Format('%u', [Word(aVal)]); dsSWord : Result := Format('%d', [Smallint(aVal)]); dsULong : Result := Format('%u', [aVal]); dsSLong : Result := Format('%d', [Integer(aVal)]); dsMutex : Result := Format('%u', [aVal]); dsArray : Result := ''; dsCluster : Result := ''; dsFloat : Result := NBCFloatToStr(CardinalToSingle(aVal)); else Result := '???'; end; end; function TypeToStr(const TypeDesc : byte) : string; begin case TypeDesc of TC_VOID : Result := 'void'; TC_UBYTE : Result := 'byte'; TC_SBYTE : Result := 'sbyte'; TC_UWORD : Result := 'word'; TC_SWORD : Result := 'sword'; TC_ULONG : Result := 'dword'; TC_SLONG : Result := 'sdword'; TC_ARRAY : Result := 'array'; TC_CLUSTER : Result := 'struct'; TC_MUTEX : Result := 'mutex'; TC_FLOAT : Result := 'float'; else Result := '????'; end; end; function GenerateTOCName(const TypeDesc : byte; const idx : Int64; const fmt : string) : string; var prefix : string; begin case TypeDesc of TC_VOID : prefix := 'v'; TC_UBYTE : prefix := 'ub'; TC_SBYTE : prefix := 'sb'; TC_UWORD : prefix := 'uw'; TC_SWORD : prefix := 'sw'; TC_ULONG : prefix := 'ul'; TC_SLONG : prefix := 'sl'; TC_ARRAY : prefix := 'a'; TC_CLUSTER : prefix := 'c'; TC_MUTEX : prefix := 'm'; TC_FLOAT : prefix := 'f'; else prefix := '?'; end; Result := Format(fmt, [prefix, idx]); end; function ShortOpEncoded(const b : byte) : boolean; begin Result := (SHOP_MASK and b) = SHOP_MASK; end; function CompareCodeToStr(const cc : byte) : string; var i : integer; begin Result := '??'; for i := Low(CCEncodings) to High(CCEncodings) do begin if CCEncodings[i].Encoding = cc then begin Result := CCEncodings[i].Mode; break; end; end; end; function ValidCompareCode(const cc : byte) : boolean; begin Result := CompareCodeToStr(cc) <> '??'; end; function ShortOpToLongOp(const op : byte) : TOpCode; var i : integer; begin Result := TOpCode(op); for i := Low(ShortOpEncodings) to High(ShortOpEncodings) do begin if ShortOpEncodings[i].Encoding = op then begin Result := ShortOpEncodings[i].LongEncoding; break; end; end; end; function TRXEProgram.StrToOpcode(const op : string; bUseCase : boolean) : TOpCode; var i : integer; tmpName : string; begin Result := OPS_INVALID; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if bUseCase then tmpName := op else tmpName := AnsiLowerCase(op); if fNXTInstructions[i].Name = tmpName then begin Result := fNXTInstructions[i].Encoding; break; end; end; end; function TRXEProgram.OpcodeToStr(const op : TOpCode) : string; var i : integer; begin if op <> OPS_INVALID then Result := Format('bad op (%d)', [Ord(op)]) else Result := ''; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if fNXTInstructions[i].Encoding = op then begin Result := fNXTInstructions[i].Name; break; end; end; end; function GenericIDToStr(genIDs : array of IDRec; const ID : integer) : string; var i : integer; begin Result := Format('%d', [ID]); for i := Low(genIDs) to High(genIDs) do begin if genIDs[i].ID = ID then begin Result := genIDs[i].Name; break; end; end; end; function SysCallMethodIDToStr(const fver : word; const ID : integer) : string; begin if fver > MAX_FW_VER1X then Result := GenericIDToStr(SysCallMethodIDs2x, ID) else Result := GenericIDToStr(SysCallMethodIDs1x, ID); end; function InputFieldIDToStr(const ID : integer) : string; begin Result := GenericIDToStr(InputFieldIDs, ID); end; function OutputFieldIDToStr(const ID : integer) : string; begin Result := GenericIDToStr(OutputFieldIDs, ID); end; function LineTypeToStr(lt : TAsmLineType) : string; begin case lt of altBeginDS : Result := 'Begin Datasegment'; altEndDS : Result := 'End Datasegment'; altBeginClump : Result := 'Begin thread'; altEndClump : Result := 'End Thread'; altCode : Result := 'Code'; altVarDecl : Result := 'Variable Declaration'; altTypeDecl : Result := 'Type Declaration'; altBeginStruct : Result := 'Begin Structure'; altEndStruct : Result := 'End Structure'; altBeginSub : Result := 'Begin Subroutine'; altEndSub : Result := 'End Subroutine'; altCodeDepends : Result := 'Thread Relationships'; altInvalid : Result := 'Invalid'; else Result := 'Unknown Line Type'; end; end; function LineTypesToStr(lts : TAsmLineTypes) : string; var i : TAsmLineType; begin Result := '['; for i := Low(TAsmLineType) to High(TAsmLinetype) do begin if i in lts then Result := Result + LineTypeToStr(i) + ', '; end; if Pos(',', Result) <> 0 then Delete(Result, Length(Result)-1, 2); // remove trailing comma + space Result := Result + ']'; end; function AsmStateToStr(asmState : TMainAsmState) : string; begin case asmState of masDataSegment, masDSClump, masDSClumpSub : Result := 'Data Segment'; masCodeSegment : Result := 'Code Segment'; masClump : Result := 'Thread'; masClumpSub : Result := 'Subroutine'; masStruct, masStructDSClump, masStructDSClumpSub : Result := 'Struct Definition'; masBlockComment : Result := 'Block Comment'; else Result := 'Unknown'; end; end; function SizeOfDSTocEntry : Integer; begin Result := SizeOf(Byte)+SizeOf(Byte)+SizeOf(Word); end; procedure LoadRXEClumpRecords(H : TRXEHeader; CD : TClumpData; aStream: TStream); var i, start, stop, depCount : integer; begin if H.Head.Version <> 0 then begin start := SizeOf(RXEHeader)+(SizeOfDSTocEntry*H.Head.DSCount)+H.Head.DSDefaultsSize; // pad if start is an odd number if (start mod 2) <> 0 then inc(start); stop := Integer(aStream.Size-(2*H.Head.CodespaceCount)); aStream.Seek(start, soFromBeginning); SetLength(CD.CRecs, H.Head.ClumpCount); for i := 0 to H.Head.ClumpCount - 1 do begin aStream.Read(CD.CRecs[i].FireCount, 1); aStream.Read(CD.CRecs[i].DependentCount, 1); ReadWordFromStream(aStream, CD.CRecs[i].CodeStart); end; // now read the packed clump dependency list which is an array of byte // the number of bytes to read is stop-start-(4*ClumpCount). depCount := stop-start-(H.Head.ClumpCount*SizeOf(ClumpRecord)); if depCount > 0 then begin aStream.Seek(start+(H.Head.ClumpCount*SizeOf(ClumpRecord)), soFromBeginning); SetLength(CD.ClumpDeps, depCount); i := 0; while i < depCount do begin aStream.Read(CD.ClumpDeps[i], SizeOf(Byte)); inc(i); end; end; end; end; procedure TRXEDumper.DumpRXEClumpRecords(aStrings: TStrings); var i, j, k : integer; tmpStr : string; begin aStrings.Add('ClumpRecords'); aStrings.Add('----------------'); if fHeader.Head.Version <> 0 then begin aStrings.Add(Format('%d record(s) (Fire Cnt, Dependent Cnt, Code Start)', [fHeader.Head.ClumpCount])); for i := 0 to fHeader.Head.ClumpCount - 1 do begin with fClumpData.CRecs[i] do aStrings.Add(Format(CLUMP_FMT+': %2.2x %2.2x %4.4x', [i, FireCount, DependentCount, CodeStart])); end; // now output dependencies by clump k := 0; for i := 0 to Length(fClumpData.CRecs) - 1 do begin if fClumpData.CRecs[i].DependentCount > 0 then begin tmpStr := Format(CLUMP_FMT+' dependencies: ', [i]); for j := 0 to fClumpData.CRecs[i].DependentCount - 1 do begin tmpStr := tmpStr + Format(CLUMP_FMT+' ', [fClumpData.ClumpDeps[k]]); inc(k); end; aStrings.Add(tmpStr); end; end; end; aStrings.Add('----------------'); end; function TRXEDumper.TOCNameFromArg(DS : TDSData; const argValue : word) : string; var DE : TDataspaceEntry; i : integer; begin if (fTmpDataspace.Count > 0) and (argValue < Length(DS.TOCNames)) then begin DE := fTmpDataspace.FindEntryByName(DS.TOCNames[argValue]); if Assigned(DE) then Result := DE.FullPathIdentifier else begin Result := DS.TOCNames[argValue]; end; end else if argValue < Length(DS.TOCNames) then Result := DS.TOCNames[argValue] else begin // maybe an IO Map address??? i := IndexOfIOMapID(argValue); if i <> -1 then Result := IOMapFieldIDs[i].Name else Result := Format(HEX_FMT, [argValue]); end; end; function TRXEDumper.ProcessInstructionArg(DS : TDSData; const addr : integer; const op : TOpCode; const argIdx: integer; const argValue: word): string; var offset : SmallInt; begin // this routine uses special handling for certain opcodes case op of OP_ADD, OP_SUB, OP_NEG, OP_MUL, OP_DIV, OP_MOD, OP_AND, OP_OR, OP_XOR, OP_NOT, OP_CMNT, OP_LSL, OP_LSR, OP_ASL, OP_ASR, OP_ROTL, OP_ROTR, OP_CMP, OP_TST, OP_CMPSET, OP_TSTSET, OP_MOV, OP_ARRSIZE, OP_ARRBUILD, OP_FLATTEN, OP_UNFLATTEN, OP_NUMTOSTRING, OP_STRCAT, OP_STRTOBYTEARR, OP_BYTEARRTOSTR, OP_ACQUIRE, OP_RELEASE, OP_SUBRET, OP_GETTICK : begin Result := TOCNameFromArg(DS, argValue); end; OP_STOP, OP_ARRINIT, OP_INDEX, OP_REPLACE, OP_ARRSUBSET, OP_STRSUBSET, OP_STRINGTONUM : begin if argValue = NOT_AN_ELEMENT then Result := STR_NA else Result := TOCNameFromArg(DS, argValue); end; OP_SET : begin if argIdx > 0 then Result := Format(HEX_FMT, [argValue]) else Result := TOCNameFromArg(DS, argValue); end; OP_SUBCALL : begin if argIdx = 0 then Result := Format(CLUMP_FMT, [argValue]) else Result := TOCNameFromArg(DS, argValue); end; OP_FINCLUMP : begin Result := Format('%d', [SmallInt(argValue)]); end; OP_FINCLUMPIMMED : begin Result := Format(CLUMP_FMT, [SmallInt(argValue)]); end; OP_JMP, OP_BRCMP, OP_BRTST : begin if argIdx = 0 then begin // the first argument is an offset and could be forward or reverse offset := SmallInt(argValue); // Instead of outputting the offset value we want to output a label // specifying the line to jump to Result := Format('lbl%4.4x', [addr+offset]); // we also need to store this address for post processing of the // output fFixups.Add(Format('%d', [addr+offset])); end else Result := TOCNameFromArg(DS, argValue); end; OP_SYSCALL : begin if argIdx = 0 then Result := SysCallMethodIDToStr(FirmwareVersion, argValue) else Result := TOCNameFromArg(DS, argValue); end; OP_SETIN, OP_GETIN : begin if argIdx = 2 then Result := InputFieldIDToStr(argValue) else Result := TOCNameFromArg(DS, argValue); end; OP_SETOUT : begin if (argIdx mod 2) = 1 then Result := OutputFieldIDToStr(argValue) else Result := TOCNameFromArg(DS, argValue); end; OP_GETOUT : begin if argIdx = 2 then Result := OutputFieldIDToStr(argValue) else Result := TOCNameFromArg(DS, argValue); end; OP_WAIT : begin if FirmwareVersion > MAX_FW_VER1X then begin if argValue = NOT_AN_ELEMENT then Result := STR_NA else Result := TOCNameFromArg(DS, argValue); end else Result := Format(HEX_FMT, [argValue]); end; OPS_WAITI_2 : begin Result := Format(HEX_FMT, [argValue]); end; OPS_ADDROF : begin if argIdx = 2 then Result := Format(HEX_FMT, [argValue]) else Result := TOCNameFromArg(DS, argValue); end; OPS_WAITV, OPS_ABS, {OP_SQRT_2, OP_ABS_2, }OPS_SIGN, OPS_FMTNUM, OPS_ACOS, OPS_ASIN, OPS_ATAN, OPS_CEIL, OPS_EXP, OPS_FABS, OPS_FLOOR, OPS_SQRT, OPS_TAN, OPS_TANH, OPS_COS, OPS_COSH, OPS_LOG, OPS_LOG10, OPS_SIN, OPS_SINH, OPS_ATAN2, OPS_FMOD, OPS_POW, OPS_WAITV_2, OPS_SIGN_2, OPS_FMTNUM_2, OPS_ACOS_2, OPS_ASIN_2, OPS_ATAN_2, OPS_CEIL_2, OPS_EXP_2, OPS_FLOOR_2, OPS_TAN_2, OPS_TANH_2, OPS_COS_2, OPS_COSH_2, OPS_LOG_2, OPS_LOG10_2, OPS_SIN_2, OPS_SINH_2, OPS_TRUNC_2, OPS_FRAC_2, OPS_ATAN2_2, OPS_POW_2, OPS_MULDIV_2, OPS_ACOSD_2, OPS_ASIND_2, OPS_ATAND_2, OPS_TAND_2, OPS_TANHD_2, OPS_COSD_2, OPS_COSHD_2, OPS_SIND_2, OPS_SINHD_2, OPS_ATAN2D_2 : begin Result := TOCNameFromArg(DS, argValue); end; OPS_PRIORITY, OPS_PRIORITY_2 : begin if argValue = NOT_AN_ELEMENT then Result := STR_NA else Result := Format(HEX_FMT, [argValue]); end; OPS_ARROP, OPS_ARROP_2 : begin if argValue = NOT_AN_ELEMENT then Result := STR_NA else if argIdx = 0 then Result := Format(HEX_FMT, [argValue]) else Result := TOCNameFromArg(DS, argValue); end; else Result := Format(HEX_FMT, [argValue]); end; end; function TRXEDumper.ProcessInstruction(DS : TDSData; CS : TCodeSpaceAry; const addr : integer; aStrings : TStrings) : integer; var B1, B2, cc, sarg : byte; op : TOpCode; rarg : Shortint; instsize, x, opIdx : integer; NI : NXTInstruction; bShortEncoded, bNotFirst : boolean; tmpStr, TabStr : string; line : integer; begin // initialize variables and begin processing the current instruction TabStr := #9; tmpStr := ''; Result := addr; B1 := Lo(CS.Code[Result]); // xxxxxxxx B2 := Hi(CS.Code[Result]); // iiiifsss instsize := Byte((INST_MASK and B2) shr 4); bShortEncoded := ShortOpEncoded(B2); if bShortEncoded then begin op := ShortOpToLongOp(CC_MASK and B2); cc := 0; sarg := B1; end else begin op := TOpCode(B1); cc := (CC_MASK and B2); sarg := 0; end; // begin to generate the output string bNotFirst := False; opIdx := IndexOfOpcode(op); if opIdx = -1 then raise Exception.CreateFmt(sInvalidOpcode, [Ord(op)]); NI := GetNXTInstruction(opIdx); tmpStr := tmpStr + #9 + NI.Name; inc(Result); // move to next word in array dec(instsize, 2); if NI.CCType <> 0 then begin tmpStr := tmpStr + #9 + CompareCodeToStr(cc); bNotFirst := True; end; if bShortEncoded and (instsize = 0) then begin tmpStr := tmpStr + IfThen(bNotFirst, ', ', #9) + TOCNameFromArg(DS, sarg); bNotFirst := True; end; if instsize > 0 then tmpStr := tmpStr + IfThen(bNotFirst, ', ', TabStr); // we need special handling for 3 opcodes if ((op = OP_STRCAT) or (op = OP_ARRBUILD) or (op = OP_SETOUT)) and (instsize > 0) then begin // handle the extra argument stuff instsize := CS.Code[Result]; dec(instsize, 4); // subtract out the instruction and the instsize arg inc(Result); end; x := 0; while instsize > 0 do begin if bShortEncoded and (x = 0) then begin // special handling if there are multiple arguments and the first // argument was short-op encoded (as a relative offset from // from the second argument) rarg := ShortInt(sarg); tmpStr := tmpStr + ProcessInstructionArg(DS, addr, op, x, Word(CS.Code[Result]+rarg)) + ', '; inc(x); continue; end; // these should be arguments to the opcode we found above tmpStr := tmpStr + ProcessInstructionArg(DS, addr, op, x, CS.code[Result]); inc(x); inc(Result); dec(instsize, 2); if instsize > 0 then tmpStr := tmpStr + ', '; end; line := aStrings.Add(tmpStr); fAddrList.Add(Format('%d=%d', [addr, line])); end; procedure LoadRXECodeSpace(H : TRXEHeader; CS : TCodeSpaceAry; aStream: TStream); var i : integer; begin if H.Head.Version <> 0 then begin aStream.Seek(Integer(aStream.Size-(2*H.Head.CodespaceCount)), soFromBeginning); i := 0; SetLength(CS.Code, H.Head.CodespaceCount); while i < H.Head.CodespaceCount do begin ReadWordFromStream(aStream, CS.Code[i]); inc(i); end; end; end; procedure TRXEDumper.FixupLabelStrings(aStrings: TStrings; const addr, line: integer); var str : string; begin str := Format('lbl%4.4x:', [addr]) + aStrings[line]; aStrings[line] := str; end; function TRXEDumper.GetAddressLine(const str: string): string; begin Result := fAddrList.Values[str]; end; procedure TRXEDumper.OutputByteCodePhaseOne(aStrings: TStrings); var i : integer; begin // format code for output i := 0; while i < Length(fCode.Code) do begin // if we are at the start of a clump we should end the previous clump // (if there is one) and start the new clump. OutputClumpBeginEndIfNeeded(fClumpData, i, aStrings); // now process the current instruction i := ProcessInstruction(fDSData, fCode, i, aStrings); end; aStrings.Add(#9'endt'); // end the last clump end; procedure TRXEDumper.OutputBytecode(aStrings: TStrings); var i, line, addr : integer; str : string; tmpSL : TStringList; begin aStrings.Add('; -------------- program code --------------'); tmpSL := TStringList.Create; try OutputBytecodePhaseOne(tmpSL); // we need to fixup the labels for jumps for i := 0 to fFixups.Count - 1 do begin str := fFixups[i]; addr := StrToIntDef(str, -1); line := StrToIntDef(GetAddressLine(str), -1); if (addr <> -1) and (line <> -1) then begin FixupLabelStrings(tmpSL, addr, line); end; end; aStrings.AddStrings(tmpSL); finally tmpSL.Free; end; end; procedure TRXEDumper.DumpRXECodeSpace(aStrings: TStrings); begin if fHeader.Head.Version <> 0 then begin OutputDataspace(aStrings); OutputBytecode(aStrings); end; end; procedure LoadDVA(dvCount : integer; DS : TDSData; aStream: TStream); var i : integer; begin // now read the Dope Vectors (10 bytes each) i := 0; SetLength(DS.DopeVecs, dvCount); // SetLength(DS.DopeVecs, (H.Head.DynDSDefaultsSize - (H.Head.DVArrayOffset-H.Head.DSStaticSize)) div 10); while i < Length(DS.DopeVecs) do begin with DS.DopeVecs[i] do begin ReadWordFromStream(aStream, offset); ReadWordFromStream(aStream, elemsize); ReadWordFromStream(aStream, count); ReadWordFromStream(aStream, backptr); ReadWordFromStream(aStream, link); end; inc(i); end; end; procedure LoadDynamicDefaultData(dsCount : integer; DS : TDSData; aStream: TStream); var i : integer; B : Byte; begin i := 0; SetLength(DS.DynamicDefaults, dsCount); while i < dsCount do begin aStream.Read(B, SizeOf(Byte)); DS.DynamicDefaults[i] := B; inc(i); end; end; procedure LoadRXEDataSpace(H : TRXEHeader; DS : TDSData; aStream: TStream); var i, dvCount, offset, dsLen : integer; B : Byte; begin if H.Head.Version <> 0 then begin dvCount := 1; // always have 1 Dope Vector in the DVA // dataspace contains DSCount 4 byte structures (the TOC) // followed by the static and dynamic defaults aStream.Seek(SizeOf(RXEHeader), soFromBeginning); SetLength(DS.TOC, H.Head.DSCount); SetLength(DS.TOCNames, H.Head.DSCount); for i := 0 to H.Head.DSCount - 1 do begin aStream.Read(B, 1); DS.TOC[i].TypeDesc := B; aStream.Read(DS.TOC[i].Flags, 1); ReadWordFromStream(aStream, DS.TOC[i].DataDesc); DS.TOCNames[i] := GenerateTOCName(DS.TOC[i].TypeDesc, i); if B = TC_ARRAY then inc(dvCount); end; // static bytes are next offset := SizeOf(RXEHeader)+(SizeOfDSTocEntry*H.Head.DSCount); aStream.Seek(offset, soFromBeginning); i := 0; B := 0; SetLength(DS.StaticDefaults, H.Head.DynDSDefaultsOffset); while i < H.Head.DynDSDefaultsOffset do begin aStream.Read(B, SizeOf(Byte)); DS.StaticDefaults[i] := B; inc(i); end; // now we can read the dynamic default data // aStream.Seek(offset+H.Head.DynDSDefaultsOffset, soFromBeginning); // this should not be necessary // how many bytes of array default data are there to read? dsLen := H.Head.DynDSDefaultsSize-(dvCount*SizeOf(DopeVector)); // figure out whether the Dope Vector Array comes before or after the // dynamic defaults that aren't part of the Dope Vector Array if H.Head.DVArrayOffset = H.Head.DSStaticSize then begin // DVA comes first LoadDVA(dvCount, DS, aStream); // we just read dvCount*10 bytes. If the DVA comes first then we need // to read 0 or 2 padding bytes depending on whether dvCount is even or odd // so that the actual array data is guaranteed to start on an address that // is a multiple of 4. if (dvCount mod 2) = 1 then begin aStream.Read(B, 1); aStream.Read(B, 1); dec(dsLen, 2); end; LoadDynamicDefaultData(dsLen, DS, aStream); end else begin LoadDynamicDefaultData(dsLen, DS, aStream); LoadDVA(dvCount, DS, aStream); end; // set the dataspace memory manager indexes from the header DS.Head := H.Head.MemMgrHead; DS.Tail := H.Head.MemMgrTail; end; end; procedure TRXEDumper.OutputDataspace(aStrings: TStrings); begin fTmpDataspace.LoadFromDSData(self.fDSData); aStrings.Add('; -------------- variable declarations --------------'); fTmpDataspace.SaveToStrings(aStrings); end; procedure TRXEDumper.DumpRXEDataSpace(aStrings: TStrings); var i : integer; tmpStr : string; begin aStrings.Add('DataSpace'); aStrings.Add('----------------'); // dataspace contains DSCount 4 byte structures (the TOC) // followed by the static and dynamic defaults aStrings.Add('DSTOC'); for i := 0 to Length(fDSData.TOC) - 1 do begin with fDSData do aStrings.Add(Format('%8s: %2.2x %2.2x %4.4x', [TOCNames[i], TOC[i].TypeDesc, TOC[i].Flags, TOC[i].DataDesc])); end; // static bytes are next i := 0; tmpStr := ''; aStrings.Add('Static DS Defaults'); while i < Length(fDSData.StaticDefaults) do begin tmpStr := tmpStr + Format('%2.2x ', [fDSData.StaticDefaults[i]]); inc(i); if i mod 16 = 0 then begin aStrings.Add(tmpStr); tmpStr := ''; end; end; if tmpStr <> '' then aStrings.Add(tmpStr); // now we can dump the dynamic default data i := 0; tmpStr := ''; aStrings.Add('Dynamic DS Defaults'); while i < Length(fDSData.DynamicDefaults) do begin tmpStr := tmpStr + Format('%2.2x ', [fDSData.DynamicDefaults[i]]); inc(i); if i mod 16 = 0 then begin aStrings.Add(tmpStr); tmpStr := ''; end; end; if tmpStr <> '' then aStrings.Add(tmpStr); // now output the Dope Vectors (10 bytes each) i := 0; aStrings.Add('Dope Vectors (offset, elem size, count, back ptr, link)'); while i < Length(fDSData.DopeVecs) do begin tmpStr := ''; with fDSData do begin tmpStr := tmpStr + Format('%2.2x %2.2x ', [Hi(DopeVecs[i].offset), Lo(DopeVecs[i].offset)]); tmpStr := tmpStr + Format('%2.2x %2.2x ', [Hi(DopeVecs[i].elemsize), Lo(DopeVecs[i].elemsize)]); tmpStr := tmpStr + Format('%2.2x %2.2x ', [Hi(DopeVecs[i].count), Lo(DopeVecs[i].count)]); tmpStr := tmpStr + Format('%2.2x %2.2x ', [Hi(DopeVecs[i].backptr), Lo(DopeVecs[i].backptr)]); tmpStr := tmpStr + Format('%2.2x %2.2x', [Hi(DopeVecs[i].link), Lo(DopeVecs[i].link)]); end; aStrings.Add(tmpStr); inc(i); end; aStrings.Add('----------------'); end; procedure LoadRXEHeader(H : TRXEHeader; aStream: TStream); begin aStream.Seek(0, soFromBeginning); with H.Head do begin aStream.Read(FormatString, 14); aStream.Read(Skip, 1); aStream.Read(Version, 1); ReadWordFromStream(aStream, DSCount); ReadWordFromStream(aStream, DSSize); ReadWordFromStream(aStream, DSStaticSize); ReadWordFromStream(aStream, DSDefaultsSize); ReadWordFromStream(aStream, DynDSDefaultsOffset); ReadWordFromStream(aStream, DynDSDefaultsSize); ReadWordFromStream(aStream, MemMgrHead); ReadWordFromStream(aStream, MemMgrTail); ReadWordFromStream(aStream, DVArrayOffset); ReadWordFromStream(aStream, ClumpCount); ReadWordFromStream(aStream, CodespaceCount); end; end; procedure TRXEDumper.DumpRXEHeader(aStrings: TStrings); begin aStrings.Add('Header'); aStrings.Add('----------------'); with fHeader.Head do aStrings.Text := aStrings.Text + Format(RXEHeaderText, [FormatString, Version, DSCount, DSSize, DSStaticSize, DSDefaultsSize, DynDSDefaultsOffset, DynDSDefaultsSize, MemMgrHead, MemMgrTail, DVArrayOffset, ClumpCount, CodespaceCount]); aStrings.Add('----------------'); end; procedure TRXEDumper.OutputClumpBeginEndIfNeeded(CD : TClumpData; const addr: integer; aStrings: TStrings); var i, j, depOffset : integer; tmpStr : string; begin // if we are at the start of a clump we should end the previous clump // (if there is one) and start the new clump. depOffset := 0; for i := 0 to Length(CD.CRecs) - 1 do begin if CD.CRecs[i].CodeStart = addr then begin if i > 0 then begin // output the end of the previous clump aStrings.Add(#9'endt'); aStrings.Add(';-----------------------------------'); end; // output the beginning of the new clump aStrings.Add(Format(#9'thread '+CLUMP_FMT, [i])); // while we are at the start of a clump we should also // output our dependency information if CD.CRecs[i].DependentCount > 0 then begin tmpStr := #9 + STR_USES + #9; for j := 0 to CD.CRecs[i].DependentCount - 1 do begin tmpStr := tmpStr + Format(CLUMP_FMT+', ', [fClumpData.ClumpDeps[depOffset+j]]); end; Delete(tmpStr, Length(tmpStr)-1, 2); // remove the last ', ' sequence. aStrings.Add(tmpStr); end; end; inc(depOffset, CD.CRecs[i].DependentCount); end; end; constructor TRXEDumper.Create; begin inherited; fHeader := TRXEHeader.Create; fDSData := TDSData.Create; fClumpData := TClumpData.Create; fCode := TCodeSpaceAry.Create; fAddrList := TStringList.Create; fAddrList.Sorted := True; fAddrList.Duplicates := dupIgnore; fFixups := TStringList.Create; fFixups.Sorted := True; fFixups.Duplicates := dupIgnore; fTmpDataspace := TDataspace.Create; fHeader.Head.DSCount := 0; fOnlyDumpCode := False; FirmwareVersion := 0; end; destructor TRXEDumper.Destroy; begin FreeAndNil(fHeader); FreeAndNil(fDSData); FreeAndNil(fClumpData); FreeAndNil(fCode); FreeAndNil(fAddrList); FreeAndNil(fFixups); FreeAndNil(fTmpDataspace); inherited; end; procedure TRXEDumper.DumpRXE(aStrings : TStrings); var SL : TStringList; begin aStrings.Clear; aStrings.BeginUpdate; try SL := TStringList.Create; try if not OnlyDumpCode then begin SL.Add('/*'); SL.Add(ExtractFileName(Filename)); DumpRXEHeader(SL); DumpRXEDataSpace(SL); DumpRXEClumpRecords(SL); SL.Add('*/'); end; DumpRXECodeSpace(SL); // copy from temporary string list into the provided TStrings class aStrings.AddStrings(SL); finally SL.Free; end; finally aStrings.EndUpdate; end; end; procedure TRXEDumper.Decompile(aStrings: TStrings); begin aStrings.Clear; aStrings.BeginUpdate; try aStrings.Add('; '+ExtractFileName(Filename)); DumpRXECodeSpace(aStrings); finally aStrings.EndUpdate; end; end; procedure TRXEDumper.LoadFromFile(const aFilename : string); var MS : TMemoryStream; begin Filename := aFilename; MS := TMemoryStream.Create; try MS.LoadFromFile(aFilename); LoadFromStream(MS); finally FreeAndNil(MS); end; end; procedure TRXEDumper.LoadFromStream(aStream: TStream); begin aStream.Position := 0; LoadRXEHeader(fHeader, aStream); if FirmwareVersion = 0 then begin // only set the firmware version based on the file contents if // it has not been explicitly set to a non-zero value externally if fHeader.Head.Version > 5 then FirmwareVersion := MIN_FW_VER2X else FirmwareVersion := MAX_FW_VER1X; end; LoadRXEDataSpace(fHeader, fDSData, aStream); LoadRXEClumpRecords(fHeader, fClumpData, aStream); LoadRXECodeSpace(fHeader, fCode, aStream); InitializeRXE; end; procedure TRXEDumper.SaveToFile(const aFilename: string); var MS : TMemoryStream; begin MS := TMemoryStream.Create; try SaveToStream(MS); MS.SaveToFile(aFilename); finally MS.Free; end; end; procedure WriteHeaderToStream(aStream: TStream; Head : RXEHeader); begin with Head do begin aStream.Write(FormatString, 14); aStream.Write(Skip, 1); aStream.Write(Version, 1); WriteWordToStream(aStream, DSCount); WriteWordToStream(aStream, DSSize); WriteWordToStream(aStream, DSStaticSize); WriteWordToStream(aStream, DSDefaultsSize); WriteWordToStream(aStream, DynDSDefaultsOffset); WriteWordToStream(aStream, DynDSDefaultsSize); WriteWordToStream(aStream, MemMgrHead); WriteWordToStream(aStream, MemMgrTail); WriteWordToStream(aStream, DVArrayOffset); WriteWordToStream(aStream, ClumpCount); WriteWordToStream(aStream, CodespaceCount); end; end; procedure TRXEDumper.SaveToStream(aStream: TStream); begin FinalizeRXE; // write the header WriteHeaderToStream(aStream, fHeader.Head); fDSData.SaveToStream(aStream); // write the clump records fClumpData.SaveToStream(aStream); // write the codespace fCode.SaveToStream(aStream); end; procedure TRXEDumper.FinalizeRXE; begin // prepare all the dynamic arrays from the class structure end; procedure TRXEDumper.InitializeRXE; begin // process dynamic arrays and build the class // representation of the code end; function TRXEDumper.GetNXTInstruction(const idx: integer): NXTInstruction; begin Result := fNXTInstructions[idx]; end; procedure TRXEDumper.SetFirmwareVersion(const Value: word); begin fFirmwareVersion := Value; InitializeInstructions; end; procedure TRXEDumper.InitializeInstructions; var i : integer; begin if fFirmwareVersion > MAX_FW_VER1X then begin SetLength(fNXTInstructions, NXTInstructionsCount2x); for i := 0 to NXTInstructionsCount2x - 1 do begin fNXTInstructions[i] := NXTInstructions2x[i]; end; end else begin SetLength(fNXTInstructions, NXTInstructionsCount1x); for i := 0 to NXTInstructionsCount1x - 1 do begin fNXTInstructions[i] := NXTInstructions1x[i]; end; end; end; function TRXEDumper.IndexOfOpcode(op : TOpCode) : integer; var i : integer; begin Result := -1; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if fNXTInstructions[i].Encoding = op then begin Result := i; Break; end; end; end; { TDSBase } function TDSBase.Add: TDataspaceEntry; begin Result := TDataspaceEntry(inherited Add); end; procedure TDSBase.AssignTo(Dest: TPersistent); var i : integer; begin if Dest is TDSBase then begin TDSBase(Dest).Clear; for i := 0 to Self.Count - 1 do begin TDSBase(Dest).Add.Assign(Self[i]); end; end else inherited; end; function TDSBase.GetItem(Index: Integer): TDataspaceEntry; begin Result := TDataspaceEntry(inherited GetItem(Index)); end; function TDSBase.FindEntryByFullName(const path : string): TDataspaceEntry; var i, p : integer; tmp : string; DE : TDataspaceEntry; begin i := fEntryIndex.IndexOf(path); if i <> -1 then Result := TDataspaceEntry(fEntryIndex.Objects[i]) else begin Result := nil; for i := 0 to Self.Count - 1 do begin DE := Items[i]; if DE.Identifier = path then begin Result := DE; Break; end else begin p := Pos(DE.Identifier + '.', path); if p = 1 then // 2009-05-12 JCH: was p > 0 begin tmp := Copy(path, p+Length(DE.Identifier)+1, MaxInt); Result := DE.SubEntries.FindEntryByFullName(tmp); if Result <> nil then Break; end; end; end; end; end; function TDSBase.IndexOfName(const name : string): integer; var DE : TDataspaceEntry; begin DE := FindEntryByFullName(name); if Assigned(DE) then Result := DE.Index else Result := -1; end; function TDSBase.Insert(Index: Integer): TDataspaceEntry; begin result := TDataspaceEntry(inherited Insert(Index)); end; procedure TDSBase.ExchangeItems(Index1, Index2: Integer); var Temp1, Temp2: Integer; de1, de2 : TDataspaceEntry; begin de1 := Items[Index1]; de2 := Items[Index2]; Temp1 := de1.Index; Temp2 := de2.Index; BeginUpdate; try de1.Index := Temp2; de2.Index := Temp1; finally EndUpdate; end; end; procedure TDSBase.QuickSort(L, R: Integer; SCompare: TDSBaseSortCompare); var I, J, P: Integer; begin repeat I := L; J := R; P := (L + R) shr 1; repeat while SCompare(Self, I, P) < 0 do Inc(I); while SCompare(Self, J, P) > 0 do Dec(J); if I <= J then begin ExchangeItems(I, J); if P = I then P := J else if P = J then P := I; Inc(I); Dec(J); end; until I > J; if L < J then QuickSort(L, J, SCompare); L := I; until I >= R; end; procedure TDSBase.SetItem(Index: Integer; Value: TDataspaceEntry); begin inherited SetItem(Index, Value); end; function GetBytesPerType(dt : TDSType) : integer; begin if dt = dsCluster then Result := -10 else if dt = dsArray then Result := -20 else Result := BytesPerType[dt]; end; function IsScalarType(dt : TDSType) : boolean; begin Result := not (dt in [dsArray, dsCluster]); end; function DSBaseCompareSizes(List: TDSBase; Index1, Index2: Integer): Integer; var de1, de2 : TDataspaceEntry; b1, b2 : Integer; // dt1, dt2 : TDSType; // bScalar1, bScalar2 : boolean; begin { -1 if the item identified by Index1 comes before the item identified by Index2 0 if the two are equivalent 1 if the item with Index1 comes after the item identified by Index2. } de1 := List.Items[Index1]; de2 := List.Items[Index2]; b1 := GetBytesPerType(de1.DataType); b2 := GetBytesPerType(de2.DataType); if b1 > b2 then // larger sizes of scalar types come first Result := -1 else if b1 = b2 then Result := 0 else Result := 1; (* { We want to sort the dataspace so that 1. all scalar types come before aggregate types. 2. scalar types are ordered by size with 4 byte types before 2 byte types before 1 byte types 3. All structs come before arrays 4. arrays are last TDSType = (dsVoid, dsUByte, dsSByte, dsUWord, dsSWord, dsULong, dsSLong, dsArray, dsCluster, dsMutex, dsFloat); } dt1 := de1.DataType; dt2 := de2.DataType; bScalar1 := IsScalarType(dt1); bScalar2 := IsScalarType(dt2); if bScalar1 and bScalar2 then begin b1 := GetBytesPerType(dt1); b2 := GetBytesPerType(dt2); if b1 > b2 then // larger sizes of scalar types come first Result := -1 else if b1 = b2 then Result := 0 else Result := 1; end else if bScalar1 then begin // 1 is scalar but 2 is not Result := -1; end else if bScalar2 then begin // 2 is scalar but 1 is not Result := 1; end else begin // neither one is scalar if dt1 < dt2 then Result := 1 else if dt1 = dt2 then Result := 0 else Result := -1; end; *) end; procedure TDSBase.Sort; begin if Count = 0 then Exit; QuickSort(0, Count - 1, @DSBaseCompareSizes); end; constructor TDSBase.Create; begin inherited Create(TDataspaceEntry); fEntryIndex := TStringList.Create; fEntryIndex.CaseSensitive := True; fEntryIndex.Sorted := True; fParent := nil; end; function TDSBase.FullPathName(DE: TDataspaceEntry): string; begin if Parent <> nil then Result := TDataspaceEntry(Parent).FullPathIdentifier + '.' + DE.Identifier else Result := DE.Identifier; end; function TDSBase.FindEntryByAddress(Addr: Word): TDataspaceEntry; var i : integer; begin Result := nil; for i := 0 to Count - 1 do begin if Items[i].DataType = dsCluster then begin Result := Items[i].SubEntries.FindEntryByAddress(Addr); if assigned(Result) then Break; end else if Items[i].Address = Addr then begin Result := Items[i]; Break; end; end; end; function TDSBase.FindEntryByName(name: string): TDataspaceEntry; var i : integer; begin // find the first entry with a matching name (could be duplicates). Result := nil; for i := 0 to Self.Count - 1 do begin if Items[i].Identifier = name then begin Result := Items[i]; Break; end else begin Result := Items[i].SubEntries.FindEntryByName(name); if Result <> nil then Break; end; end; end; procedure TDSBase.CheckEntry(DE: TDataspaceEntry); var X : TDataspaceEntry; begin // identifier must be valid if not IsValidIdent(DE.Identifier) then raise Exception.CreateFmt(sInvalidVarDecl, [DE.Identifier]); // make sure entry is unique X := FindEntryByFullName(DE.FullPathIdentifier); if (X <> nil) and (X <> DE) then raise EDuplicateDataspaceEntry.Create(DE); end; function EqualDopeVectors(DV1, DV2 : DopeVector) : boolean; begin Result := (DV1.offset = DV2.offset) and (DV1.elemsize = DV2.elemsize) and (DV1.count = DV2.count) and (DV1.backptr = DV2.backptr) and (DV1.link = DV2.link); end; function TDSBase.ResolveNestedArrayAddress(DS: TDSData; DV: DopeVector): TDataspaceEntry; var i, addr : integer; begin addr := -1; // find the index of the DV in DS.DopeVectors and look at // the item just before it to get the Dataspace entry address for i := Low(DS.DopeVecs) to High(DS.DopeVecs) do begin if EqualDopeVectors(DS.DopeVecs[i], DV) and (i > Low(DS.DopeVecs)) then begin // found the item addr := DS.DopeVecs[i-1].backptr; Break; end; end; Result := FindEntryByAddress(Word(addr)); end; function TDSBase.GetRoot: TDataspaceEntry; begin Result := nil; if Assigned(Parent) then Result := TDataspaceEntry(Parent).DSBase.Root; if not Assigned(Result) then Result := TDataspaceEntry(Parent); end; destructor TDSBase.Destroy; begin FreeAndNil(fEntryIndex); inherited; end; { TDataspace } constructor TDataspace.Create; begin inherited; fDSIndexMap := TStringList.Create; fDSIndexMap.CaseSensitive := True; fDSIndexMap.Sorted := True; // an unsorted list of all dataspace entries regardless of their nesting level fDSList := TObjectList.Create; end; destructor TDataspace.Destroy; begin FreeAndNil(fDSIndexMap); FreeAndNil(fDSList); inherited; end; function TDataspace.FinalizeDataspace(DS : TDSBase; addr : Word) : Word; var i : integer; DE : TDataspaceEntry; currAddress : Word; begin // run through the dataspace and set the Address property for each entry and // build a map for the dataspace indices currAddress := addr; for i := 0 to DS.Count - 1 do begin DE := DS.Items[i]; fDSIndexMap.AddObject(DE.FullPathIdentifier, DE); fDSList.Add(DE); DE.DSID := fDSList.Count - 1; if DE.DataType = dsCluster then begin DE.Address := Word(DE.SubEntries.Count); currAddress := FinalizeDataspace(DE.SubEntries, RoundToBytesize(currAddress, BytesPerType[dsCluster])); end else if DE.DataType = dsArray then begin DE.Address := RoundToBytesize(currAddress, BytesPerType[dsArray]); FinalizeDataspace(DE.SubEntries, 0); currAddress := Word(DE.Address + BytesPerType[DE.DataType]); end else begin DE.Address := RoundToBytesize(currAddress, BytesPerType[DE.DataType]); currAddress := Word(DE.Address + BytesPerType[DE.DataType]); end; end; Result := currAddress; end; function TDataspace.DataspaceIndex(const ident: string): Integer; var DE : TDataspaceEntry; begin if fDSIndexMap.Count = 0 then FinalizeDataspace(Self, 0); Result := fDSIndexMap.IndexOf(ident); if Result <> -1 then begin DE := TDataspaceEntry(fDSIndexMap.Objects[Result]); Result := DE.DSID; end; end; function TDataspace.GetVector(index: Integer): DopeVector; begin Result := fVectors[index]; end; function TDataspace.IndexOfEntryByAddress(Addr: Word): Integer; var DE : TDataspaceEntry; begin DE := FindEntryByAddress(Addr); if Assigned(DE) then Result := DE.Index else Result := -1; end; function AddArrayItem(aDS : TDSData; Item : TDataspaceEntry; idx : Integer; var staticIndex : Integer) : integer; var Sub : TDataspaceEntry; begin // when this function is called idx is pointing one past the array item Result := idx; // the next entry contains the datatype (which, unfortunately, could be an array) Sub := Item.SubEntries.Add; Sub.Identifier := aDS.TOCNames[Result]; Sub.DataType := TDSType(aDS.TOC[Result].TypeDesc); Sub.DSID := Result; Sub.DefaultValue := 0; Sub.ArrayMember := True; if Sub.DataType = dsArray then begin inc(Result); Result := AddArrayItem(aDS, Sub, Result, staticIndex); end else if Sub.DataType = dsCluster then Result := ProcessCluster(aDS, Sub, Result, staticIndex) else inc(Result); end; procedure GetStaticDefaults(X: TDataspaceEntry; aDS: TDSData; var staticIndex: integer); var val : Cardinal; begin // read the static bytes and convert to default value case BytesPerType[X.DataType] of 1 : val := BytesToCardinal(aDS.StaticDefaults[staticIndex]); 2 : val := BytesToCardinal(aDS.StaticDefaults[staticIndex], aDS.StaticDefaults[staticIndex+1]); 4 : val := BytesToCardinal(aDS.StaticDefaults[staticIndex], aDS.StaticDefaults[staticIndex+1], aDS.StaticDefaults[staticIndex+2], aDS.StaticDefaults[staticIndex+3]); else val := 0; end; X.DefaultValue := val; // increment the static index inc(staticIndex, BytesPerType[X.DataType]); end; function ProcessCluster(aDS : TDSData; Item : TDataspaceEntry; idx : Integer; var staticIndex : Integer) : integer; var n, j : integer; member : TDataspaceEntry; DSE : DSTocEntry; begin Result := idx; inc(Result); n := aDS.TOC[idx].DataDesc; // number of elements in this cluster j := 1; while j <= n do begin // the next entry contains the datatype member := Item.SubEntries.Add; DSE := aDS.TOC[Result]; member.Identifier := aDS.TOCNames[Result]; member.DataType := TDSType(DSE.TypeDesc); member.DSID := Result; member.DefaultValue := 0; member.ArrayMember := Item.ArrayMember; case member.DataType of dsArray : begin inc(Result); // move past the array element to its child // read an extra item member.Address := DSE.DataDesc; // data description is the address Result := AddArrayItem(aDS, member, Result, staticIndex); // if this array is a root level array (i.e., not an ArrayMember) then // get the DVAIndex from the static dataspace if (DSE.Flags = 0) and not Item.ArrayMember then begin GetStaticDefaults(member, aDS, staticIndex); end; end; dsCluster : begin member.Address := DSE.DataDesc; // data description is the number of elements Result := ProcessCluster(aDS, member, Result, staticIndex); end; else inc(Result); member.Address := DSE.DataDesc; // data description is the address if (DSE.Flags = 0) and not Item.ArrayMember then begin GetStaticDefaults(member, aDS, staticIndex); end; end; inc(j); end; end; const INVALID_LINK = $FFFF; NESTED_ARRAY_BACKPTR = $FFFE; procedure TDataspace.LoadArrayValuesFromDynamicData(DS: TDSData); var idx, dp : integer; actualbytes, i, paddedbytes : Word; DV : DopeVector; X : TDataspaceEntry; function ProcessElement(aArray : TDataspaceEntry; DE : TDataspaceEntry; k : word) : word; var b1, b2, b3, b4 : byte; j : integer; begin Result := k; case DE.DataType of dsUByte, dsSByte : begin b1 := DS.DynamicDefaults[dp+k]; if DV.count > 0 then aArray.AddValue(BytesToCardinal(b1)); end; dsUWord, dsSWord : begin b1 := DS.DynamicDefaults[dp+k]; b2 := DS.DynamicDefaults[dp+k+1]; if DV.count > 0 then aArray.AddValue(BytesToCardinal(b1, b2)); end; dsULong, dsSLong : begin b1 := DS.DynamicDefaults[dp+k]; b2 := DS.DynamicDefaults[dp+k+1]; b3 := DS.DynamicDefaults[dp+k+2]; b4 := DS.DynamicDefaults[dp+k+3]; if DV.count > 0 then aArray.AddValue(BytesToCardinal(b1, b2, b3, b4)); end; else if DE.DataType = dsCluster then // an array of cluster begin for j := 0 to DE.SubEntries.Count - 1 do begin k := RoundToByteSize(k, BytesPerType[DE.SubEntries[j].DataType]); k := ProcessElement(DE, DE.SubEntries[j], k); end; end else if DE.DataType = dsArray then // an array of array begin ProcessElement(DE, DE.SubEntries[0], k); end; end; if DE.DataType = dsArray then inc(Result, DV.elemsize) else inc(Result, DE.ElementSize); end; begin dp := 0; idx := 0; while idx < Length(DS.DopeVecs) do begin DV := DS.DopeVecs[idx]; if (DV.backptr <> INVALID_LINK){ and ((DV.count > 0) or (DV.elemsize > 4))} then begin if DV.backptr = NESTED_ARRAY_BACKPTR then begin inc(dp, 4); end else begin X := FindEntryByAddress(DV.backptr); // if X is not assigned it is because this is a nested array if not Assigned(X) then X := ResolveNestedArrayAddress(DS, DV); if (X <> nil) and (X.DataType = dsArray) and ((DV.count > 0) or (X.SubEntries[0].DataType = dsCluster) or // array of cluster or array of array (X.SubEntries[0].DataType = dsArray)) then begin // process the default data for this element // the number of bytes to read from the dynamic defaults array is // (DV.Count * DV.Size) + (4 - ((DV.Count * DV.Size) mod 4)) if DV.count > 0 then actualbytes := Word(DV.count * DV.elemsize) else actualbytes := DV.elemsize; paddedbytes := RoundToByteSize(actualbytes, DWORD_LEN); // read from the current dynamic defaults pointer (dp) i := 0; while i < actualbytes do begin i := ProcessElement(X, X.SubEntries[0], i); end; inc(dp, paddedbytes); end; end; end; inc(idx); end; end; procedure TDataspace.LoadFromDSData(aDS: TDSData); var i : integer; staticIndex : integer; DSE : DSTocEntry; X : TDataspaceEntry; begin Clear; fDSIndexMap.Clear; fDSList.Clear; i := 0; staticIndex := 0; fMMHead := aDS.Head; fMMTail := aDS.Tail; while i < Length(aDS.TOC) do begin DSE := aDS.TOC[i]; X := Self.Add; X.Identifier := aDS.TOCNames[i]; X.DataType := TDSType(DSE.TypeDesc); X.DSID := i; X.DefaultValue := 0; case X.DataType of dsArray : begin inc(i); X.Address := DSE.DataDesc; // data description is the address i := AddArrayItem(aDS, X, i, staticIndex); // root-level arrays have DV index in static dataspace GetStaticDefaults(X, aDS, staticIndex); end; dsCluster : begin // the data descriptor is the number of items in the cluster // we need to process clusters recursively since a cluster // can contain another cluster X.Address := DSE.DataDesc; i := ProcessCluster(aDS, X, i, staticIndex); end; else // all other datatypes are simple scalars X.Address := DSE.DataDesc; // data description is the address // a flags value of 0 for a scalar type means it has a static default value if DSE.Flags = 0 then begin GetStaticDefaults(X, aDS, staticIndex); end; inc(i); end; end; // process dynamic data using dopevectors LoadArrayValuesFromDynamicData(aDS); end; procedure TDataspace.LoadFromStream(aStream: TStream); begin fDSIndexMap.Clear; fDSList.Clear; // TODO: implement TDataspace.LoadFromStream aStream.Position := 0; end; procedure TDataspace.SaveToDSData(aDS: TDSData); var i, j, offset, doffset : integer; cnt, maxAddress, DVAIndex : Word; pTE : ^DSTocEntry; DE : TDataspaceEntry; begin fDSList.Clear; fDSIndexMap.Clear; FinalizeDataspace(self, 0); aDS.Head := 0; aDS.Tail := 0; // add the first dope vector which contains the number of dope vectors // if the dope vector array is empty SetLength(aDS.DopeVecs, 1); with aDS.DopeVecs[0] do begin offset := 0; elemsize := 10; // the size of each dope vector count := 1; // start at 1 backptr := $FFFF; // invalid pointer end; // fill the table of contents maxAddress := 0; doffset := 0; offset := 0; DVAIndex := 1; SetLength(aDS.TOC, fDSList.Count); SetLength(aDS.TOCNames, fDSList.Count); for i := 0 to fDSList.Count - 1 do begin pTE := @(aDS.TOC[i]); DE := TDataspaceEntry(fDSList[i]); aDS.TOCNames[i] := DE.GetFullPathIdentifier; if DE.DataType = dsMutex then DE.DefaultValue := $FFFFFFFF; pTE^.TypeDesc := Byte(Ord(DE.DataType)); if (DE.DefaultValue = 0) and not (DE.DataType in [dsArray, dsCluster]) and not DE.ArrayMember then pTE^.Flags := 1 else pTE^.Flags := 0; pTE^.DataDesc := DE.Address; // these next two fields are only used when outputting the symbol table pTE^.RefCount := Word(DE.RefCount); pTE^.Size := DE.ElementSize; // keep track of the maximum dataspace address if DE.Address >= maxAddress then maxAddress := Word(DE.Address+BytesPerType[DE.DataType]); // generate the static defaults data if (DE.DefaultValue <> 0) and (DE.DataType <> dsArray) then begin // add bytes to static data cnt := BytesPerType[DE.DataType]; SetLength(aDS.StaticDefaults, offset+cnt); for j := 0 to cnt - 1 do begin aDS.StaticDefaults[offset+j] := GetByte(DE.DefaultValue, j); end; inc(offset, cnt); end else if (DE.DataType = dsArray) then begin if not DE.ArrayMember then begin // top-level arrays output DVA index in static data SetLength(aDS.StaticDefaults, offset+BytesPerType[dsArray]); aDS.StaticDefaults[offset] := Lo(Word(DVAIndex)); aDS.StaticDefaults[offset+1] := Hi(Word(DVAIndex)); inc(offset, 2); end; DE.DefaultValue := DVAIndex; inc(DVAIndex); // all arrays get a DVA and we increment the index accordingly end; // generate the dynamic defaults data and dope vectors if (DE.DataType = dsArray) then begin ProcessArray(DE, aDS, doffset); end; end; // now process the dope vectors array and set the offset and link values ProcessDopeVectors(aDS, maxAddress); end; procedure TDataspace.SaveToStream(aStream: TStream); var DS : TDSData; begin DS := TDSData.Create; try SaveToDSData(DS); DS.SaveToStream(aStream); finally DS.Free; end; end; procedure TDataspace.SaveToStrings(aStrings: TStrings); var i : integer; begin aStrings.BeginUpdate; try aStrings.Add('dseg'#9'segment'); // output all unique definitions first aStrings.Add(';------- definitions -------'); for i := 0 to Count - 1 do Items[i].SaveToStrings(aStrings, true); //now output declarations aStrings.Add(';------- declarations -------'); for i := 0 to Count - 1 do Items[i].SaveToStrings(aStrings); aStrings.Add('dseg'#9'ends'); finally aStrings.EndUpdate; end; end; function TDataspace.FindEntryByFullName(const path: string): TDataspaceEntry; var i : integer; begin if fDSIndexMap.Count <> 0 then begin i := fDSIndexMap.IndexOf(path); if i <> -1 then Result := TDataspaceEntry(fDSIndexMap.Objects[i]) else Result := nil; end else Result := inherited FindEntryByFullName(path); end; procedure TDataspace.ProcessDopeVectors(aDS: TDSData; addr: Word); var i, idxEmpty, idxFull : integer; pDV : ^DopeVector; delta : Word; begin // make sure starting address is a 4 byte boundary addr := RoundToByteSize(addr, DWORD_LEN); idxEmpty := 0; idxFull := aDS.Head; for i := 1 to Length(aDS.DopeVecs) - 1 do begin pDV := @(aDS.DopeVecs[i]); if pDV^.count = 0 then begin pDV^.offset := $FFFF; // store the greatest index with an offset of $FFFF as the tail if i > aDS.Tail then aDS.Tail := Word(i); // handle special case of empty arrays of struct or empty nested arrays if pDV^.link <> 0 then begin // increment maxAddress delta := pDV^.elemsize; delta := RoundToByteSize(delta, DWORD_LEN); inc(addr, delta); end; // set link pointer pDV := @(aDS.DopeVecs[idxEmpty]); pDV^.link := Word(i); idxEmpty := i; end else begin pDV^.offset := addr; // if the last element in the array is not empty then link it back to the // first empty element (always 0) // increment maxAddress delta := Word(pDV^.count * pDV^.elemsize); delta := RoundToByteSize(delta, DWORD_LEN); inc(addr, delta); if pDV^.backptr = 0 then begin // a nested array pDV^.backptr := addr; end; // set link pointer if i = idxFull then begin // special case where there is only one non-empty array pDV := @(aDS.DopeVecs[i]); pDV^.link := Word(0); end else begin pDV := @(aDS.DopeVecs[idxFull]); pDV^.link := Word(i); idxFull := i; end; end; end; // link the last Full item back to zero (the first empty item) // unless the last full item is item 0 if idxFull <> 0 then begin pDV := @(aDS.DopeVecs[idxFull]); pDV^.link := 0; end; pDV := @(aDS.DopeVecs[Length(aDS.DopeVecs)-1]); if pDV^.count > 0 then pDV^.link := 0; aDS.DopeVecs[0].offset := RoundToBytesize(addr, DWORD_LEN); aDS.DopeVecs[aDS.Tail].link := $FFFF; end; function TDataspace.GetCaseSensitive: boolean; begin Result := fDSIndexMap.CaseSensitive; end; procedure TDataspace.SetCaseSensitive(const Value: boolean); begin fDSIndexMap.CaseSensitive := Value; end; procedure TDataspace.Compact; var i : integer; begin // this routine removes dataspace entries (root level) // which are not in use. for i := Count - 1 downto 0 do begin if not Items[i].InUse then Delete(i); end; end; function TDataspace.FindEntryAndAddReference(const path: string): TDataspaceEntry; begin Result := FindEntryByFullName(path); if Assigned(Result) then begin AddReference(Result); end; end; procedure TDataspace.RemoveReferenceIfPresent(const path: string); var DE : TDataspaceEntry; begin DE := FindEntryByFullName(path); if Assigned(DE) then RemoveReference(DE); end; procedure TDataspace.ProcessArray(DE: TDataspaceEntry; aDS: TDSData; var doffset : integer); var j, k, bytesWritten : integer; idx, cnt : Word; pDV : ^DopeVector; val : Cardinal; Sub : TDataspaceEntry; begin // 1. Create a new DopeVector entry in our DopeVectorArray idx := Word(Length(aDS.DopeVecs)); // create a dope vector entry for this array SetLength(aDS.DopeVecs, idx+1); pDV := @(aDS.DopeVecs[idx]); // 2. Increment our dope vector count inc(aDS.DopeVecs[0].count); // offset and link values will be calculated after we have finished // 3. Fill in DopeVector values common to all three types of arrays pDV^.elemsize := DE.ArrayElementSize; // NOTE: the backptr value is unused in the 1.03 firmware { TODO: I need to add code here to handle arrays of arrays which output a different backptr value. } if DE.ArrayMember then pDV^.backptr := NESTED_ARRAY_BACKPTR else pDV^.backptr := DE.Address; // the DS address of the array // 4. Fill in the DopeVector values based on array type (array of struct, // array of array, or array of scalar) // 5. Write dynamic default values to the dataspace (by array type) Sub := DE.SubEntries[0]; if (Sub.DataType = dsArray) or DE.ArrayMember then begin // array of array or array of struct or scalar that is itself an array member if DE.ArrayMember and (Sub.DataType <> dsArray) then pDV^.count := 1 else pDV^.count := 0; // an array containing an array always has count of 0 ??? if DE.ArrayMember then k := 2 // nested arrays output DVAIndex ??? else k := 1; // the top level element of a nested array seems to write just one byte (padded) cnt := RoundToByteSize(Word(k), DWORD_LEN); SetLength(aDS.DynamicDefaults, doffset+cnt); pDV^.link := 2; // write to dynamic data bytesWritten := k; if DE.ArrayMember then begin aDS.DynamicDefaults[doffset+0] := GetByte(DE.DefaultValue, 0); aDS.DynamicDefaults[doffset+1] := GetByte(DE.DefaultValue, 1); end else begin aDS.DynamicDefaults[doffset+0] := 1; end; // now write the pad bytes for j := 0 to cnt - bytesWritten - 1 do aDS.DynamicDefaults[doffset+bytesWritten+j] := $FF; end else if Sub.DataType = dsCluster {and not an array member} then begin // array of struct pDV^.count := Word(Sub.ValueCount div Sub.SubEntries.Count); // even if there are not initialization values for an array of struct // we will write out dynamic data for the array anyway if pDV^.count = 0 then cnt := pDV^.elemsize else cnt := Word(pDV^.count * pDV^.elemsize); cnt := RoundToByteSize(cnt, DWORD_LEN); SetLength(aDS.DynamicDefaults, doffset+cnt); // set a flag so that I can tell whether this is an array of struct // or a nested array or an array of scalar pDV^.link := 1; // write to dynamic data // clusters store the initialization data one level down // and it is organized by cluster member DE.SaveToDynamicDefaults(aDS, cnt, doffset); end else begin // non-nested array of scalars pDV^.count := DE.ValueCount; cnt := Word(pDV^.count * pDV^.elemsize); cnt := RoundToByteSize(cnt, DWORD_LEN); SetLength(aDS.DynamicDefaults, doffset+cnt); pDV^.link := 0; // write to dynamic data bytesWritten := 0; for j := 0 to pDV^.count - 1 do begin val := DE.Values[j]; for k := 0 to pDV^.elemsize - 1 do begin aDS.DynamicDefaults[doffset+(j*pDV^.elemsize)+k] := GetByte(val, k); inc(bytesWritten); end; end; // now write the pad bytes for j := 0 to cnt - bytesWritten - 1 do aDS.DynamicDefaults[doffset+bytesWritten+j] := $FF; end; // 6. Update the Memory Manager Head pointer (if needed) // Point the head at this entry if it a) hasn't been set yet and // b) this entry has a count > 0 if (aDS.Head = 0) and (pDV^.count > 0) then aDS.Head := idx; // the index of this entry in the array // 7. Finally, increment the dynamic default data offset pointer inc(doffset, cnt); end; procedure TDataspace.AddReference(DE: TDataspaceEntry); begin // if this item has a parent then incref at the parent level if DE.DSBase.Root <> nil then DE.DSBase.Root.IncRefCount else DE.IncRefCount; end; procedure TDataspace.RemoveReference(DE: TDataspaceEntry); begin if DE.DSBase.Root <> nil then DE.DSBase.Root.DecRefCount else DE.DecRefCount; end; { TDataspaceEntry } procedure TDataspaceEntry.AddValue(aValue: Cardinal); begin fArrayValues.Add(TCardinalObject.Create(aValue)); end; function StripArrayAndStructDelimiters(const str : string) : string; begin Result := Trim(Replace(Replace(Replace(Replace(str, '{', ''), '}', ''), '[', ''), ']', '')); // if the string either starts or ends with a comma then delete it. if Pos(',', Result) = 1 then System.Delete(Result, 1, 1); if LastDelimiter(',', Result) = Length(Result) then System.Delete(Result, Length(Result), 1); Result := Trim(Result); end; function ValueAsCardinal(aValue : Extended; aDST : TDSType = dsVoid) : Cardinal; var iVal : Int64; sVal : Single; begin iVal := Trunc(aValue); if (iVal = aValue) and (aDST <> dsFloat) then Result := Cardinal(iVal) else begin sVal := aValue; Result := SingleToCardinal(sVal); end; end; function CalcDSType(aDSType : TDSType; aValue : Extended) : TDSType; var oldBPT, newBPT : byte; begin Result := GetArgDataType(aValue); if Result <> aDSType then begin oldBPT := BytesPerType[aDSType]; newBPT := BytesPerType[Result]; if oldBPT >= newBPT then begin // we will return the old type since it is >= new type if (Result in [dsSByte, dsSWord, dsSLong]) and (aDSType in [dsUByte, dsUWord, dsULong]) then begin // if new type is signed but old is unsigned then switch to equivalent signed type Result := TDSType(Ord(aDSType)+1); // signed is always unsigned+1 end else begin // in all other cases (old signed, new unsigned or both same) // just return old type Result := aDSType; end; end; end; end; function TDataspaceEntry.AddValuesFromString(Calc : TNBCExpParser; sargs: string) : TDSType; var i : integer; SL : TStringList; x : Byte; fVal : Extended; begin Result := dsUByte; // default value type is unsigned byte sargs := Trim(sargs); // sargs is a comma-separated list of values // it could also be a ? or a {} pair if (sargs = '') or (sargs = '?') or (sargs = '{}') then Exit; SL := TStringList.Create; try // is sargs a quoted string? if QuotedString(sargs) then begin sargs := Copy(sargs, 2, Length(sargs)-2); // remove quotes at both ends for i := 1 to Length(sargs) do begin x := Ord(sargs[i]); case x of 3 : AddValue(9); // tab 4 : AddValue(10); // lf 5 : AddValue(13); // cr 6 : AddValue(Ord('\')); 7 : AddValue(Ord('''')); 8 : AddValue(Ord('"')); else AddValue(x); end; end; // add a null terminator AddValue(0); end else begin sargs := StripArrayAndStructDelimiters(sargs); SL.CommaText := sargs; if DataType = dsCluster then begin // initialize cluster members if Self.ArrayMember then begin for i := 0 to SL.Count - 1 do begin Calc.Expression := SL[i]; fVal := Calc.Value; AddValue(ValueAsCardinal(fVal)); Result := CalcDSType(Result, fVal); end; end else begin for i := 0 to Self.SubEntries.Count - 1 do begin if i < SL.Count then begin Calc.Expression := SL[i]; fVal := Calc.Value; SubEntries[i].DefaultValue := ValueAsCardinal(fVal, SubEntries[i].DataType); Result := CalcDSType(dsUByte, fVal); end; end; end; end else if DataType = dsArray then begin // initialize array // first check whether this is an array of scalars or an array // of structs or array of array if Self.SubEntries[0].DataType in [dsCluster, dsArray] then SubEntries[0].AddValuesFromString(Calc, sargs) else begin for i := 0 to SL.Count - 1 do begin Calc.Expression := SL[i]; fVal := Calc.Value; AddValue(ValueAsCardinal(fVal, Self.SubEntries[0].DataType)); Result := CalcDSType(Result, fVal); end; end; end else begin // initialize scalar types // if there is only one value then used DefaultValue rather // than AddValue Calc.Expression := SL[0]; fVal := Calc.Value; DefaultValue := ValueAsCardinal(fVal, DataType); Result := CalcDSType(dsUByte, fVal); end; end; finally SL.Free; end; end; function TDataspaceEntry.ElementSize(bPad : boolean) : Word; var i, bpt, padBytes : integer; DE : TDataspaceEntry; begin Result := 0; if DataType in [dsVoid..dsSLong, dsMutex, dsFloat] then begin Result := Word(BytesPerType[DataType]); end else begin // handle special cases (arrays of clusters and arrays of arrays) if DataType = dsCluster then begin // calculate the padded size of a cluster for i := 0 to SubEntries.Count - 1 do begin DE := SubEntries[i]; bpt := DE.ElementSize(bPad); // 2006-10-02 JCH recursively calculate the element size // this fixes a problem with the size of arrays containing nested aggregate types if bPad then begin padBytes := bpt - (Result mod bpt); if padBytes < bpt then begin Result := Word(Result + padBytes); end; end; Result := Word(Result + bpt); end; if bPad then Result := RoundToBytesize(Result, DWORD_LEN); end else if DataType = dsArray then begin // TODO: check validity of array of array element size calculation // Result := ArrayElementSize + 4; Result := 4; end else Result := 4; end; end; function TDataspaceEntry.ArrayElementSize(bPad : boolean) : Word; begin Result := 0; if DataType <> dsArray then Exit; if SubEntries[0].DataType = dsArray then Result := 2 else Result := SubEntries[0].ElementSize(bPad); end; procedure TDataspaceEntry.AssignTo(Dest: TPersistent); var i : integer; begin if Dest is TDataspaceEntry then begin TDataspaceEntry(Dest).Identifier := Self.Identifier; TDataspaceEntry(Dest).DataType := Self.DataType; TDataspaceEntry(Dest).DefaultValue := Self.DefaultValue; TDataspaceEntry(Dest).ArrayMember := Self.ArrayMember; TDataspaceEntry(Dest).SubEntries := Self.SubEntries; TDataspaceEntry(Dest).fArrayValues.Clear; for i := 0 to Self.ValueCount - 1 do TDataspaceEntry(Dest).AddValue(Self.Values[i]); end else inherited; end; constructor TDataspaceEntry.Create(ACollection: TCollection); begin inherited; fThreadNames := TStringList.Create; TStringList(fThreadNames).Sorted := True; TStringList(fThreadNames).Duplicates := dupIgnore; fSubEntries := TDSBase.Create; fSubEntries.Parent := Self; fArrayValues := TObjectList.Create; fArrayMember := False; fRefCount := 0; end; destructor TDataspaceEntry.Destroy; begin FreeAndNil(fThreadNames); FreeAndNil(fArrayValues); FreeAndNil(fSubEntries); inherited; end; function TDataspaceEntry.GetInitializationString: string; begin if DataType = dsArray then Result := GetArrayInit else if DataType = dsCluster then Result := GetClusterInit else Result := ValToStr(DataType, DefaultValue); end; function TDataspaceEntry.GetArrayInit: string; var i : integer; bIsString : boolean; Sub : TDataspaceEntry; x : Char; begin Result := ''; if DataType <> dsArray then Exit; // no output if this isn't an array if Self.ArrayMember then Exit; Sub := SubEntries[0]; if Sub.DataType = dsCluster then begin // the values are each considered to be the values of cluster members // so group the values using {} around N elements based on the // cluster definition for i := 0 to Sub.ValueCount - 1 do begin if (i mod Sub.SubEntries.Count) = 0 then begin if Length(Result) > 0 then Delete(Result, Length(Result)-1, MaxInt); if i > 0 then Result := Result + '}, {' else Result := Result + '{'; end; Result := Result + '0x' + IntToHex(Sub.Values[i], 1) + ', '; end; Delete(Result, Length(Result)-1, MaxInt); if Length(Result) > 0 then Result := Result + '}'; end else if Sub.DataType = dsArray then begin Result := Sub.InitializationString; // ???? if Trim(Result) <> '' then Result := '['+Result+']'; end else begin // an array of scalars bIsString := False; if (ValueCount > 1) and (Values[ValueCount - 1] = 0) and (Sub.DataType in [dsUByte, dsSByte]) then begin // at least 2 items and the last one is zero and it is an array of byte // Maybe this is a string??? bIsString := True; for i := 0 to ValueCount - 2 do // skip the 0 at the end begin // check that all values are in the alphanumeric ASCII range if not (Values[i] in [9, 10, 13, 32..126]) then // if (Values[i] < 32) or (Values[i] > 126) then begin bIsString := False; break; end; end; end; if bIsString then begin Result := ''''; for i := 0 to ValueCount - 2 do // skip null begin x := Chr(Values[i]); case x of '"', '''', '\' : Result := Result + '\' + x; #9 : Result := Result + '\t'; #10 : Result := Result + '\n'; #13 : Result := Result + '\r'; else Result := Result + x; end; end; Result := Result + ''''; end else begin for i := 0 to ValueCount - 1 do begin Result := Result + '0x' + IntToHex(Values[i], 1) + ', '; end; Delete(Result, Length(Result)-1, MaxInt); end; end; end; function TDataspaceEntry.GetClusterInit: string; var i : integer; Sub : TDataspaceEntry; begin Result := ''; if DataType <> dsCluster then Exit; // no output if this isn't a cluster for i := 0 to SubEntries.Count - 1 do begin Sub := SubEntries[i]; if Result = '' then Result := Sub.InitializationString else Result := Result + ', ' + Sub.InitializationString; end; if Result <> '' then Result := '{' + Result + '}'; end; function TDataspaceEntry.GetDataTypeAsString: string; begin if DataType = dsCluster then Result := Identifier + '_def' else if DataType = dsArray then begin if SubEntries[0].DataType = dsCluster then Result := SubEntries[0].Identifier + '_def[]' else if SubEntries[0].DataType = dsArray then Result := SubEntries[0].DataTypeAsString + '[]' else Result := TypeToStr(SubEntries[0].DataType) + '[]'; end else Result := TypeToStr(DataType); end; function TDataspaceEntry.GetDSBase: TDSBase; begin Result := TDSBase(Collection); end; function TDataspaceEntry.GetFullPathIdentifier: string; begin // ask my collection what my full path identifier is Result := DSBase.FullPathName(self); end; function TDataspaceEntry.GetValue(idx: integer): Cardinal; begin Result := TCardinalObject(fArrayValues[idx]).Value; end; procedure TDataspaceEntry.LoadFromStream(aStream: TStream); var X : DSTOCEntry; begin X.TypeDesc := 0; X.Flags := 0; X.DataDesc := 0; aStream.Read(X.TypeDesc, 1); aStream.Read(X.Flags, 1); ReadWordFromStream(aStream, X.DataDesc); // copy DSTOCEntry values to collection item X.TypeDesc := Byte(Ord(Self.DataType)); end; procedure TDataspaceEntry.SaveToStream(aStream: TStream); var X : DSTOCEntry; begin // copy collection item values to DSTOCEntry X.TypeDesc := Byte(Ord(DataType)); if DefaultValue <> 0 then X.Flags := 0 else X.Flags := 1; case DataType of dsCluster : X.DataDesc := Word(SubEntries.Count); else X.DataDesc := Address; end; aStream.Write(X.TypeDesc, 1); aStream.Write(X.Flags, 1); WriteWordToStream(aStream, X.DataDesc); end; function Replicate(const str : string; const times : integer) : string; var i : integer; begin Result := ''; for i := 0 to times - 1 do Result := Result + str; end; procedure TDataspaceEntry.SaveToStrings(aStrings: TStrings; bDefine, bInCluster : boolean); var tmpStr : string; i : integer; begin // write self and subentries to strings if bDefine then begin for i := 0 to SubEntries.Count - 1 do SubEntries[i].SaveToStrings(aStrings, True); end; case DataType of dsArray : begin // arrays should have only one sub entry if SubEntries.Count > 0 then begin // if the array type is a structure then define it first and then output // the array declaration tmpStr := Format('%s'#9'%s', [Identifier, DataTypeAsString]); if not bInCluster then tmpStr := tmpStr + Format(#9'%s', [InitializationString]); if not bDefine or bInCluster then aStrings.Add(tmpStr); end; end; dsCluster : begin // definitions are only needed for items which are clusters if bDefine then begin if DataType = dsCluster then begin // only output a definition if this item is the first of its type tmpStr := Format('%s_def'#9'%s', [Identifier, 'struct']); aStrings.Add(tmpStr); for i := 0 to SubEntries.Count - 1 do SubEntries[i].SaveToStrings(aStrings, False, True); tmpStr := Format('%s_def'#9'%s', [Identifier, 'ends']); aStrings.Add(tmpStr); end; end else begin tmpStr := Format('%s'#9'%s'#9'%s', [Identifier, DataTypeAsString, InitializationString]); aStrings.Add(tmpStr); end; end; dsVoid, dsMutex : begin tmpStr := Format('%s'#9'%s', [Identifier, DataTypeAsString]); if not bDefine or bInCluster then aStrings.Add(tmpStr); end; else // scalars & floats tmpStr := Format('%s'#9'%s', [Identifier, DataTypeAsString]); if not {bDefine}bInCluster then tmpStr := tmpStr + Format(#9'%s', [InitializationString]); if not bDefine or bInCluster then aStrings.Add(tmpStr); end; end; procedure TDataspaceEntry.SetArrayMember(const Value: boolean); var i : integer; begin fArrayMember := Value; // iterate through all sub entries for i := 0 to SubEntries.Count - 1 do SubEntries[i].ArrayMember := Value; end; procedure TDataspaceEntry.SetIdentifier(const Value: string); begin fIdentifier := Value; DSBase.fEntryIndex.AddObject(Self.FullPathIdentifier, Self); DSBase.CheckEntry(self); end; procedure TDataspaceEntry.SetSubEntries(const Value: TDSBase); begin fSubEntries.Assign(Value); end; function TDataspaceEntry.ValueCount: Word; begin Result := Word(fArrayValues.Count); end; procedure TDataspaceEntry.SaveToDynamicDefaults(aDS: TDSData; const cnt, doffset: integer); var elemsize : integer; X : TDataspaceEntry; procedure DoSaveToDynDefaults; var idx, vc : integer; val : Cardinal; j, bytesWritten : word; bpt : Byte; i, k : integer; begin if X.ValueCount = 0 then vc := X.SubEntries.Count else vc := X.ValueCount; // we need to write a total of cnt bytes to aDS.DynamicDefaults at // offset == doffset // the values come from SubEntries[0].Values[n] bytesWritten := 0; j := 0; for i := 0 to vc - 1 do begin if X.ValueCount = 0 then val := 0 else val := X.Values[i]; idx := i mod X.SubEntries.Count; // calculate the field index bpt := BytesPerType[X.SubEntries[idx].DataType]; if (idx = 0) and (i <> 0) then begin // we have wrapped around to another element in the array // pad to full structure size. // j must be within 0..elemsize-1 j := Word((elemsize - (j mod elemsize)) mod elemsize); for k := 0 to j - 1 do aDS.DynamicDefaults[doffset+bytesWritten+k] := $FF; inc(bytesWritten, j); j := bytesWritten; end; // are we at the right boundary for the next (current) struct field? j := RoundToBytesize(j, bpt); if j > bytesWritten then for k := 0 to j - bytesWritten - 1 do aDS.DynamicDefaults[doffset+bytesWritten+k] := $FF; bytesWritten := j; // now we are ready to output this field's value for k := 0 to bpt - 1 do begin aDS.DynamicDefaults[doffset+j+k] := GetByte(val, k); inc(bytesWritten); end; j := bytesWritten; end; // if we haven't written the full cnt bytes out then pad. for k := 0 to cnt - bytesWritten - 1 do aDS.DynamicDefaults[doffset+bytesWritten+k] := $FF; end; begin // this routine is for saving array of struct or array of arrays to dynamic data if DataType <> dsArray then Exit; if SubEntries.Count <> 1 then Exit; elemsize := ArrayElementSize; X := SubEntries[0]; if X.DataType in [dsCluster, dsArray] then begin DoSaveToDynDefaults; end; end; function TDataspaceEntry.GetInUse: boolean; var i : integer; begin Result := fRefCount > 0; if not Result and (DataType = dsCluster) then begin for i := 0 to SubEntries.Count - 1 do begin Result := SubEntries[i].InUse; if Result then Break; end; end; end; function TDataspaceEntry.GetRefCount: integer; begin Result := fRefCount; end; procedure TDataspaceEntry.IncRefCount; var i : integer; begin inc(fRefCount); // check sub entries if this entry is a cluster if DataType = dsCluster then begin for i := 0 to SubEntries.Count - 1 do begin SubEntries[i].IncRefCount; end; end; end; procedure TDataspaceEntry.DecRefCount; var i : integer; begin dec(fRefCount); if DataType = dsCluster then begin for i := 0 to SubEntries.Count - 1 do begin SubEntries[i].DecRefCount; end; end; end; function TDataspaceEntry.GetArrayBaseType: TDSType; begin Result := DataType; if IsArray then Result := SubEntries[0].BaseDataType; end; function TDataspaceEntry.GetIsArray: boolean; begin Result := DataType = dsArray; end; procedure TDataspaceEntry.AddThread(const aThreadName: string); begin fThreadNames.Add(aThreadName); end; function TDataspaceEntry.ThreadCount: integer; begin Result := fThreadNames.Count; end; { TRXEProgram } constructor TRXEProgram.Create; begin inherited; fMaxPreprocDepth := 10; fMaxErrors := 0; fIgnoreSystemFile := False; fEnhancedFirmware := False; fWarningsOff := False; fReturnRequired := False; fCaseSensitive := True; fStandardDefines := True; fExtraDefines := True; fCompVersion := 5; fProductVersion := GetProductVersion; CreateObjects; InitializeHeader; FirmwareVersion := 128; // 1.28 NXT 2.0 firmware end; destructor TRXEProgram.Destroy; begin FreeObjects; inherited; end; procedure TRXEProgram.LoadFromStream(aStream: TStream); begin // TODO: implement loadfromstream aStream.Position := 0; end; function TRXEProgram.SaveToFile(const filename: string) : boolean; var MS : TMemoryStream; begin MS := TMemoryStream.Create; try Result := SaveToStream(MS); MS.SaveToFile(filename); finally MS.Free; end; end; function TRXEProgram.SaveToStream(aStream: TStream) : boolean; begin Result := False; if fBadProgram then begin fMsgs.Add(Format(sProgramError, [fProgErrorCount])); end else begin DoCompilerStatusChange(sNBCFinalizeDepends); // make sure our dependencies are finalized Codespace.FinalizeDependencies; // possibly optimize if Optimize level > 0 if OptimizeLevel >= 1 then begin DoCompilerStatusChange(Format(sNBCOptimizeLevel, [OptimizeLevel])); DoCompilerStatusChange(sNBCBuildRefs); // build references if we are optimizing Codespace.BuildReferences; DoCompilerStatusChange(sNBCOptMutexes); // optimize mutexes Codespace.OptimizeMutexes; DoCompilerStatusChange(sNBCCompactCode); // compact the codespace before codespace optimizations Codespace.Compact; DoCompilerStatusChange(sNBCRemoveLabels); // also get rid of extra labels Codespace.RemoveUnusedLabels; // 2009-03-18 JCH: I have restored the level 2 optimizations // As defects are revealed they will be fixed Some optimizations // will be only performed at levels higher than 2 so I now pass the // level into the optimization function itself. if OptimizeLevel >= 2 then begin DoCompilerStatusChange(sNBCRunCodeOpts); Codespace.Optimize(OptimizeLevel); DoCompilerStatusChange(sNBCCompactAfterOpt); // after optimizations we should re-compact the codespace Codespace.Compact; end; // after optimizing and compacting the codespace we remove // unused variables from the dataspace DoCompilerStatusChange(sNBCCompactData); Dataspace.Compact; end else begin // level zero (no optimizations) DoCompilerStatusChange(sNBCRemoveLabels); // also get rid of extra labels Codespace.RemoveUnusedLabels; // after optimizing and compacting the codespace we remove // unused variables from the dataspace DoCompilerStatusChange(sNBCCompactData); Dataspace.Compact; end; if not WarningsOff then OutputUnusedItemWarnings; DoCompilerStatusChange(sNBCSortDataspace); // sort the dataspace Dataspace.Sort; DoCompilerStatusChange(sNBCGenerateRawDS); // write the dataspace to DSData Dataspace.SaveToDSData(fDSData); DoCompilerStatusChange(sNBCFillCodeArrays); // fill the clumprecords and codespace array Codespace.SaveToCodeData(fClumpData, fCode); DoCompilerStatusChange(sNBCUpdateHeader); // having done that I can now update the header UpdateHeader; // and write everything to the stream aStream.Position := 0; DoCompilerStatusChange(sNBCWriteHeader); WriteHeaderToStream(aStream, fHeader); DoCompilerStatusChange(sNBCWriteDataspace); fDSData.SaveToStream(aStream); DoCompilerStatusChange(sNBCWriteClumpData); fClumpData.SaveToStream(aStream); DoCompilerStatusChange(sNBCWriteCodespace); fCode.SaveToStream(aStream); Result := not fBadProgram; if Result then begin DoCompilerStatusChange(sNBCWriteOptSource); // replace the original "compiler output" with the optimized version SaveToStrings(CompilerOutput); end; end; DoCompilerStatusChange(sNBCFinished, True); end; function TRXEProgram.GetVersion: byte; begin Result := fHeader.Version; end; procedure TRXEProgram.SetVersion(const Value: byte); begin fHeader.Version := Value; end; function TRXEProgram.GetFormat: string; begin Result := fHeader.FormatString; end; procedure TRXEProgram.SetFormat(const Value: string); var i : integer; begin for i := 0 to 12 do fHeader.FormatString[i] := Value[i]; fHeader.FormatString[13] := #0; end; function TRXEProgram.GetClumpCount: Word; begin Result := fHeader.ClumpCount; end; function TRXEProgram.GetCodespaceCount: Word; begin Result := fHeader.CodespaceCount; end; function TRXEProgram.GetDSCount: Word; begin Result := fHeader.DSCount; end; function TRXEProgram.GetDSDefaultsSize: Word; begin Result := fHeader.DSDefaultsSize; end; function TRXEProgram.GetDSSize: Word; begin Result := fHeader.DSSize; end; function TRXEProgram.GetDVArrayOffset: Word; begin Result := fHeader.DVArrayOffset; end; function TRXEProgram.GetDynDSDefaultsOffset: Word; begin Result := fHeader.DynDSDefaultsOffset; end; function TRXEProgram.GetDynDSDefaultsSize: Word; begin Result := fHeader.DynDSDefaultsSize; end; function TRXEProgram.GetMemMgrHead: Word; begin Result := fHeader.MemMgrHead; end; function TRXEProgram.GetMemMgrTail: Word; begin Result := fHeader.MemMgrTail; end; function TRXEProgram.Parse(aStream: TStream) : string; var S : TStrings; begin S := TStringList.Create; try S.LoadFromStream(aStream); Result := Parse(S); finally S.Free; end; end; procedure TRXEProgram.LoadSystemFile(S : TStream); var tmp : string; begin // load fMS with the contents of NBCCommon.h followed by NXTDefs.h tmp := '#line 0 "NXTDefs.h"'#13#10; S.Write(PChar(tmp)^, Length(tmp)); S.Write(nbc_common_data, High(nbc_common_data)+1); S.Write(nxt_defs_data, High(nxt_defs_data)+1); tmp := '#reset'#13#10; S.Write(PChar(tmp)^, Length(tmp)); end; function TRXEProgram.Parse(aStrings: TStrings) : string; var i, idx : integer; P : TLangPreprocessor; S : TMemoryStream; tmpFile, tmpMsg : string; begin DoCompilerStatusChange(sNBCCompBegin); DoCompilerStatusChange(Format(sCompileTargets, [FirmwareVersion, BoolToString(EnhancedFirmware)])); Result := ''; try if not IgnoreSystemFile then begin S := TMemoryStream.Create; try DoCompilerStatusChange(sNBCLoadSystemFiles); LoadSystemFile(S); aStrings.SaveToStream(S); S.Position := 0; aStrings.LoadFromStream(S); finally S.Free; end; end; fBadProgram := False; fProgErrorCount := 0; LineCounter := 0; fAbsCount := 0; fSignCount := 0; fShiftCount := 0; fMainStateLast := masCodeSegment; // used only when we enter a block comment fMainStateCurrent := masCodeSegment; // default state P := TLangPreprocessor.Create(TNBCLexer, ExtractFilePath(ParamStr(0)), lnNBC, MaxPreprocessorDepth); try P.OnPreprocessorStatusChange := HandlePreprocStatusChange; P.Defines.AddDefines(Defines); if EnhancedFirmware then P.Defines.Define('__ENHANCED_FIRMWARE'); P.Defines.AddEntry('__FIRMWARE_VERSION', IntToStr(FirmwareVersion)); P.AddIncludeDirs(IncludeDirs); if not IgnoreSystemFile then begin P.SkipIncludeFile('NBCCommon.h'); P.SkipIncludeFile('NXTDefs.h'); end; DoCompilerStatusChange(sNBCPreprocess); // Preprocess returns a list of files from #download statements Result := P.Preprocess(GetCurrentFile(true), aStrings); for i := 0 to P.Warnings.Count - 1 do begin tmpMsg := P.Warnings.ValueFromIndex[i]; idx := Pos('|', tmpMsg); tmpFile := Copy(tmpMsg, 1, idx-1); Delete(tmpMsg, 1, idx); ReportProblem(StrToIntDef(P.Warnings.Names[i], 0), tmpFile, '', tmpMsg, false); end; finally P.Free; end; // aStrings.SaveToFile('preproc.txt'); DoCompilerStatusChange(sNBCCompilingSource); i := 0; while i < aStrings.Count do begin if fSkipCount = 0 then LineCounter := LineCounter + 1; ProcessASMLine(aStrings, i); inc(i); if fSkipCount > 0 then Dec(fSkipCount); end; DoCompilerStatusChange(sNBCCompFinished); CheckMainThread; if not fBadProgram then fBadProgram := Codespace.Count = 0; if not fBadProgram then fCompilerOutput.Assign(aStrings); except on E : EAbort do begin fBadProgram := True; // end processing file due to Abort in ReportProblem end; on E : EPreprocessorException do begin fBadProgram := True; ReportProblem(E.LineNo, GetCurrentFile(true), sException, E.Message, true); end; on E : Exception do begin fBadProgram := True; ReportProblem(LineCounter, GetCurrentFile(true), sException, E.Message, true); end; end; end; function GetValidLineTypes(const state : TMainAsmState) : TAsmLineTypes; begin case state of masClump : Result := [altEndClump, altBeginDS, altCode, altCodeDepends]; masClumpSub : Result := [altEndSub, altBeginDS, altCode]; masCodeSegment : Result := [altBeginClump, altBeginDS, altBeginSub]; masStruct : Result := [altEndStruct, altVarDecl]; masDSClump : Result := [altEndDS, altVarDecl, altTypeDecl, altBeginStruct]; masStructDSClump : Result := [altEndStruct, altVarDecl]; masDSClumpSub : Result := [altEndDS, altVarDecl, altTypeDecl, altBeginStruct]; masStructDSClumpSub : Result := [altEndStruct, altVarDecl]; else // masDataSegment Result := [altEndDS, altVarDecl, altTypeDecl, altBeginStruct]; end; end; function CommasToSpaces(const line : string) : string; var i, len : integer; bInString : boolean; ch : Char; begin i := Pos('''', line); // is there a string initializer on this line? if i > 0 then begin // if there is a string on this line then process a character at a time bInString := False; Result := ''; len := Length(line); for i := 1 to len do begin ch := line[i]; if (ch = ',') and not bInString then ch := ' ' // else if (not bInString and (ch = '''')) or // (bInString and (ch = '''') and // ((i = len) or (line[i+1] <> ''''))) then else if ch = '''' then bInString := not bInString; Result := Result + ch; end; end else Result := Replace(line, ',', ' '); end; function TRXEProgram.DetermineLineType(const state : TMainAsmState; namedTypes: TMapList; op : string; bUseCase : boolean) : TAsmLineType; begin // special handling for [] at end of opcode op := Replace(op, '[]', ''); case StrToOpcode(op, bUseCase) of OP_ADD..OP_GETTICK : Result := altCode; OPS_WAITV..OPS_POW : Result := altCode; // pseudo opcodes // OPS_SQRT_2..OPS_ABS_2 : Result := altCode; // standard 1.26+ opcodes (included in OPS_WAITV..OPS_POW due to overlap) OPS_WAITI_2..OPS_ADDROF : Result := altCode; // enhanced 1.26+ opcodes OPS_SEGMENT : Result := altBeginDS; OPS_ENDS : if state in [masStruct, masStructDSClump, masStructDSClumpSub] then Result := altEndStruct else if state = masClumpSub then Result := altEndSub else Result := altEndDS; OPS_TYPEDEF : Result := altTypeDecl; OPS_THREAD : Result := altBeginClump; OPS_ENDT : Result := altEndClump; OPS_SUBROUTINE : Result := altBeginSub; OPS_STRUCT : Result := altBeginStruct; OPS_REQUIRES, OPS_USES : Result := altCodeDepends; OPS_DB..OPS_FLOAT : Result := altVarDecl; OPS_CALL..OPS_COMPCHKTYPE : Result := altCode; // pseudo opcodes else // if the opcode isn't known perhaps it is a typedef if state in [masDataSegment, masStruct, masDSClump, masStructDSClump, masDSClumpSub, masStructDSClumpSub] then begin if namedTypes.IndexOf(op) <> -1 then Result := altVarDecl else Result := altInvalid; end else Result := altInvalid; end; end; procedure TrimComments(var line : string; p : integer; const sub : string); var k, j, x : integer; tmp : string; begin // before we decide to trim these comment we need to know whether they are // embedded in a string or not. tmp := line; while (p > 0) do begin k := Pos('''', tmp); j := 0; if k < p then begin // hmmm, is there another single quote? tmp := Copy(tmp, k+1, MaxInt); j := Pos('''', tmp); tmp := Copy(tmp, j+1, MaxInt); j := j + k; end; if not ((p > k) and (p < j)) then begin Delete(line, p, MaxInt); // trim off any trailing comment line := TrimRight(line); // trim off any trailing whitespace tmp := line; p := 0; end else p := j; x := Pos(sub, tmp); if x > 0 then inc(p, x-1) else p := 0; end; end; function NBCExtractStrings(str : string; values : TStrings) : integer; var s, p : integer; begin // between 0 and 3 entries in values when I'm done values.Clear; str := Replace(str, #9, ' '); s := Pos(' ', str); p := Pos(',', str); while (s > 0) and (s < p) do begin if values.Count > 1 then Break; values.Add(Copy(str, 1, s-1)); System.Delete(str, 1, s); str := Trim(str); s := Pos(' ', str); p := Pos(',', str); end; if str <> '' then values.Add(str); Result := values.Count; end; procedure TRXEProgram.ChunkLine(const state : TMainAsmState; namedTypes: TMapList; line : string; bUseCase : boolean; var lbl, opcode, args : string; var lineType : TAsmLineType; var bIgnoreDups : boolean); var i : integer; tmp : string; values : TStringList; begin bIgnoreDups := True; lbl := ''; opcode := ''; args := ''; lineType := altInvalid; // break apart the line into its constituent parts // whitespace at the beginning and end of the line has already been trimmed. // if the first word in the line is an opcode (of any kind) then // the label is blank and everything after the opcode is the args // if the first word is NOT an opcode then we assume it is a label // and we check the second word for whether it is an opcode or not // if it is not then the line is invalid. If it is then everything after // the second word is the args i := Pos(';', line); if i <> 0 then TrimComments(line, i, ';'); i := Pos('//', line); if i <> 0 then TrimComments(line, i, '//'); values := TStringList.Create; try line := CommasToSpaces(line); i := JCHExtractStrings([' ', #9], [], PChar(line), values); if i = 1 then begin if StrToOpcode(values[0], bUseCase) = OPS_INVALID then begin // if there is only one item in the line and it isn't an opcode // then it should be a label // with an required trailing ':'. If the colon is missing then // the line is invalid i := Pos(':', line); if i = Length(line) then begin lbl := Copy(line, 1, i-1); lineType := altCode; end; end else begin // it could be an endt or ends opcode to end the current thread/subroutine lbl := ''; opcode := values[0]; lineType := DetermineLineType(state, namedTypes, opcode, bUseCase); end; end else if (i > 1) and (i < 3) then begin // special case is the dseg segment and dseg ends lines tmp := values[0]; if tmp = 'dseg' then begin lbl := tmp; opcode := values[1]; bIgnoreDups := (values.Count = 3) and (values[2] = '1'); if opcode = OpcodeToStr(OPS_SEGMENT) then lineType := altBeginDS else if opcode = OpcodeToStr(OPS_ENDS) then lineType := altEndDS; end else begin // if the first item is a known opcode then assume no label // exists in this line if StrToOpcode(values[0], bUseCase) = OPS_INVALID then begin // label + opcode and no args lbl := values[0]; opcode := values[1]; end else begin // no label - just opcode and args lbl := ''; opcode := values[0]; values.Delete(0); args := Trim(values.CommaText); end; lineType := DetermineLineType(state, namedTypes, opcode, bUseCase); end; end else begin // i >= 3 // if the first item is a known opcode then assume no label // exists in this line if StrToOpcode(values[0]) = OPS_INVALID then begin lbl := values[0]; opcode := values[1]; values.Delete(0); values.Delete(0); end else begin lbl := ''; opcode := values[0]; values.Delete(0); end; if values.Count = 1 then args := Trim(values[0]) else args := Trim(values.CommaText); lineType := DetermineLineType(state, namedTypes, opcode, bUseCase); end; finally values.Free; end; end; procedure InstantiateCluster(DD : TDataDefs; DE: TDataspaceEntry; const clustername: string); var idx : integer; Def : TDataspaceEntry; begin DE.TypeName := clustername; // find an entry in the datadefs collection with clustername idx := DD.IndexOfName(clustername); if idx <> -1 then begin Def := DD[idx]; DE.SubEntries := Def.SubEntries; end; end; procedure HandleVarDecl(DD : TDataDefs; NT : TMapList; bCaseSensitive : boolean; DSE : TDataspaceEntry; albl, aopcode : string; sttFunc : TSTTFuncType); var stype : string; idx, p, len : integer; Sub : TDataspaceEntry; begin DSE.Identifier := albl; stype := aopcode; p := Pos('[]', stype); len := Length(stype); // calculate the named type index without [] if there are any if p > 0 then begin Delete(aopcode, len-1, 2); // assumes that [] are last two characters stype := aopcode; end; idx := NT.IndexOf(stype); if idx <> -1 then stype := NT.MapValue[idx]; if (p > 0) then begin // this is an array type DSE.DataType := dsArray; DSE.TypeName := stype; Sub := DSE.SubEntries.Add; Sub.Identifier := DSE.Identifier + '_type'; // could be an array of structs (yuck!) if (idx <> -1) and (aopcode = stype) then begin // must be a struct type Sub.DataType := dsCluster; InstantiateCluster(DD, Sub, stype); end else begin HandleVarDecl(DD, NT, bCaseSensitive, Sub, Sub.Identifier, aopcode, sttFunc); end; Sub.DefaultValue := 0; Sub.ArrayMember := True; end else if (idx <> -1) and (aopcode = stype) then begin DSE.DataType := dsCluster; InstantiateCluster(DD, DSE, stype); end else begin // a simple type DSE.DataType := sttFunc(stype, bCaseSensitive); end; end; procedure TRXEProgram.ProcessASMLine(aStrings: TStrings; var idx : integer); var i, endBCPos, cPos, len, oldIdx : integer; lbl, opcode, args, errMsg, tmpFile, tmpLine, line, varName : string; lineType : TASMLineType; ValidLineTypes : TASMLineTypes; DE : TDataspaceEntry; AL : TAsmLine; inBlockComment : boolean; theOp : TOpCode; begin try lineType := altInvalid; args := ''; opcode := ''; lbl := ''; line := aStrings[idx]; oldIdx := idx; // check for and handle the case where the line ends with \ indicating that // the line continues on the next line. len := Length(line); if len > 0 then begin while (line[len] = '\') and (idx < aStrings.Count - 1) do begin System.Delete(line, len, 1); // delete the '\' inc(idx); line := line + aStrings[idx]; len := Length(line); aStrings[idx] := ''; // clear the current line end; if line[len] = '\' then System.Delete(line, len, 1); end; line := ReplaceTokens(Trim(line)); aStrings[oldIdx] := line; // do nothing if line is blank or a comment if (line = '') or (Pos(';', line) = 1) or (Pos('//', line) = 1) then Exit; line := ReplaceSpecialStringCharacters(line); i := Pos('#line ', line); if i = 1 then begin // this is a special preprocessor line tmpLine := line; Delete(line, 1, 6); i := Pos(' ', line); LineCounter := StrToIntDef(Copy(line, 1, i - 1), LineCounter); Delete(line, 1, i); tmpFile := Replace(line, '"', ''); tmpFile := Replace(tmpFile, '''', ''); CurrentFile := tmpFile; if fMainStateCurrent in [masClump, masClumpSub] then begin // add code to the current clump AL := fCurrentClump.ClumpCode.Add; AL.AsString := tmpLine; AL.LineNum := LineCounter; end; end else if Pos('#download', line) = 1 then begin // ignore #download lines // if we are in a clump then add a special asm line for the #download // otherwise just skip it. if fMainStateCurrent in [masClump, masClumpSub] then begin // add code to the current clump AL := fCurrentClump.ClumpCode.Add; AL.AsString := line; AL.LineNum := LineCounter; end; end else if Pos('#reset', line) = 1 then begin tmpLine := line; LineCounter := 1; if fMainStateCurrent in [masClump, masClumpSub] then begin // add code to the current clump AL := fCurrentClump.ClumpCode.Add; AL.AsString := tmpLine; AL.LineNum := LineCounter; end; end else if Pos('#pragma ', line) = 1 then begin // this is a special preprocessor line // if we are in a clump then add a special asm line for the #pragma // otherwise just skip it. if fMainStateCurrent in [masClump, masClumpSub] then begin // add code to the current clump AL := fCurrentClump.ClumpCode.Add; AL.AsString := line; AL.LineNum := LineCounter; if Pos('safecalling', line) > 0 then CodeSpace.Multithread(fCurrentClump.Name); end; // is this a special #pragma macro line? if Pos('macro', line) = 9 then begin System.Delete(line, 1, 14); fSkipCount := StrToIntDef(line, 0)+1; end; end else begin // check for the possibility that we are starting or ending a block comment on this line // nesting block comments is not supported and will result in compiler errors i := Pos('/*', line); endBCPos := Pos('*/', line); if (endBCPos = 0) or ((fMainStateCurrent <> masBlockComment) and (endBCPos = 0)) then inBlockComment := i > 0 else if endBCPos <> 0 then inBlockComment := i > endBCPos+1 else inBlockComment := False; if (endBCPos > 0) and (fMainStateCurrent = masBlockComment) then begin // remove everything from line up to end block comment Delete(line, 1, endBCPos+1); // revert to previous state fMainStateCurrent := fMainStateLast; end; if inBlockComment then begin Delete(line, i, MaxInt); // delete to end of line end else if (i > 0) and (endBCPos > i+1) then begin // just remove the block comment portion of the line Delete(line, i, endBCPos-i+2); // we don't want a block comment remove to result in a valid // identifier or function Insert(' ', line, i); end; // if we were already in a block comment before starting this line // and we still are in a block comment after the above processing // then we can skip the rest of this routine if fMainStateCurrent = masBlockComment then Exit; // double check for a blank line since we have manipulated it if Trim(line) <> '' then begin // go ahead and process this line as normal // chunk the line into its consituent parts ChunkLine(fMainStateCurrent, fNamedTypes, line, CaseSensitive, lbl, opcode, args, lineType, fIgnoreDupDefs); // what state are we in? ValidLineTypes := GetValidLineTypes(fMainStateCurrent); if lineType in ValidLineTypes then begin case fMainStateCurrent of masClump, masClumpSub : begin // 1. end of clump/sub // 2. start of datasegment // 3. code if (lineType = altEndClump) or (lineType = altEndSub) then begin fIgnoreLines := False; fCurrentClump.LastLine := LineCounter; fMainStateCurrent := masCodeSegment; // at the end of the current clump we can validate labels ValidateLabels(fCurrentClump); if ReturnRequiredInSubroutine and (lineType = altEndSub) then begin // the last line of a subroutine must be a return!!! if (fCurrentClump.ClumpCode.Count > 0) then begin AL := fCurrentClump.ClumpCode[fCurrentClump.ClumpCode.Count-1]; if AL.Command <> OP_SUBRET then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sNoReturnAtEndOfSub, true); end else ReportProblem(LineCounter, GetCurrentFile(true), line, sNoReturnAtEndOfSub, true); end; ProcessSpawnedThreads; // if we have just ended a clump we may need to create a new // one if the clump uses the wait opcode. if fClumpUsesWait then CreateWaitClump(fCurrentClump.Name); fClumpName := ''; end else if lineType = altBeginDS then begin if fMainStateCurrent = masClump then fMainStateCurrent := masDSClump else fMainStateCurrent := masDSClumpSub; end else if lineType = altCode then begin // add code to the current clump AL := fCurrentClump.ClumpCode.Add; cPos := Pos(':', lbl); if cPos > 0 then System.Delete(lbl, cPos, MaxInt); lbl := Trim(lbl); if lbl <> '' then begin AL.LineLabel := lbl; if fCurrentClump.IndexOfLabel(lbl) = -1 then fCurrentClump.AddLabel(lbl, AL) else begin errMsg := Format(sDuplicateLabel, [lbl]); ReportProblem(LineCounter, GetCurrentFile(true), line, errMsg, true); end; end; AL.LineNum := LineCounter; theOp := StrToOpcode(opcode, CaseSensitive); AL.Command := theOp; AL.AddArgs(args); HandleConstantExpressions(AL); if not fIgnoreLines then CheckArgs(AL); HandlePseudoOpcodes(AL, theOp{, args}); if fIgnoreLines then AL.Command := OPS_INVALID; end else if (lineType = altCodeDepends) then begin if not fIgnoreLines then fCurrentClump.AddClumpDependencies(opcode, args); end; end; masCodeSegment : begin // 1. start of clump/sub // 2. start of datasegment if lineType = altBeginDS then fMainStateCurrent := masDataSegment else begin if lineType = altBeginSub then fMainStateCurrent := masClumpSub else fMainStateCurrent := masClump; // starting a clump so define one fClumpUsesWait := False; fClumpUsesSign := False; fClumpUsesShift := False; fIgnoreLines := False; fVarI := 0; // each clump starts with I and J reset to 0. fVarJ := 0; fCurrentClump := CodeSpace.Add; fCurrentClump.Name := args; fClumpName := fCurrentClump.Name; fCurrentClump.IsSubroutine := fMainStateCurrent = masClumpSub; fCurrentClump.Filename := GetCurrentFile(true); if fCurrentClump.IsSubroutine then begin varName := Format('__%s_return', [fCurrentClump.Name]); // subroutines each have their own unsigned byte variable in // the dataspace to store the return address DefineVar(varName, SubroutineReturnAddressType); end; end; end; masStruct, masStructDSClump, masStructDSClumpSub : begin // we are inside a structure definition // the only valid line type are: // 1. end of structure definition // 2. variable declaration if lineType = altEndStruct then begin if fMainStateCurrent = masStructDSClump then fMainStateCurrent := masDSClump else if fMainStateCurrent = masStructDSClumpSub then fMainStateCurrent := masDSClumpSub else fMainStateCurrent := masDataSegment end else if lineType = altVarDecl then begin // add a member to the current structure definition DE := fCurrentStruct.SubEntries.Add; HandleVarDecl(DataDefinitions, fNamedTypes, CaseSensitive, DE, lbl, opcode, @StrToType); // the args value is an initializer DE.AddValuesFromString(Calc, args); end; end; masDatasegment, masDSClump, masDSClumpSub : begin // 1. end of datasegment // 2. variable declaration // 3. type declaration // 4. start of struct definition if lineType = altEndDS then begin if fMainStateCurrent = masDataSegment then fMainStateCurrent := masCodeSegment else if fMainStateCurrent = masDSClumpSub then fMainStateCurrent := masClumpSub else fMainStateCurrent := masClump; end else if lineType = altVarDecl then begin // add a variable declaration to the dataspace DE := Dataspace.Add; HandleVarDecl(DataDefinitions, fNamedTypes, CaseSensitive, DE, lbl, opcode, @StrToType); // the args value is an initializer if args <> '' then args := StripExtraQuotes(args); DE.AddValuesFromString(Calc, args); end else if lineType = altTypeDecl then begin // add a named type alias if fNamedTypes.IndexOf(lbl) = -1 then fNamedTypes.AddEntry(lbl, args) else raise Exception.CreateFmt(sDuplicateType, [lbl]); end else if lineType = altBeginStruct then begin if fMainStateCurrent = masDataSegment then fMainStateCurrent := masStruct else if fMainStateCurrent = masDSClumpSub then fMainStateCurrent := masStructDSClumpSub else fMainStateCurrent := masStructDSClump; // add a named type alias if fNamedTypes.IndexOf(lbl) = -1 then fNamedTypes.AddEntry(lbl, lbl) else raise Exception.CreateFmt(sDuplicateType, [lbl]); // create a new structure definition fCurrentStruct := DataDefinitions.Add; fCurrentStruct.Identifier := lbl; end; end; end; end else begin if not fIgnoreLines then begin // tell the user what type of line was found and // what the current state is if lineType = altInvalid then errMsg := sInvalidStatement else errMsg := Format(sInvalidLine, [LineTypeToStr(lineType), ASMStateToStr(fMainStateCurrent)]); ReportProblem(LineCounter, GetCurrentFile(true), line, errMsg, true); end; end; end; // now handle the fact that we may have stated a block comment on this line if inBlockComment then begin fMainStateLast := fMainStateCurrent; fMainStateCurrent := masBlockComment; end; end; except on E : Exception do begin ReportProblem(LineCounter, GetCurrentFile(true), line, E.Message, true); end; end; end; procedure TRXEProgram.ReportProblem(const lineNo: integer; const fName, line, msg: string; err : boolean); var tmp, tmp1, tmp2, tmp3, tmp4 : string; stop : boolean; begin // exit without doing anything if this is not an error and warnings are off if WarningsOff and not err then Exit; if lineNo = -1 then begin tmp := msg; fMsgs.Add(tmp); end else begin if err then tmp1 := Format('# Error: %s', [msg]) else tmp1 := Format('# Warning: %s', [msg]); fMsgs.Add(tmp1); tmp2 := Format('File "%s" ; line %d', [fName, lineNo]); fMsgs.Add(tmp2); tmp3 := Format('# %s', [line]); fMsgs.Add(tmp3); tmp4 := '#----------------------------------------------------------'; fMsgs.Add(tmp4); tmp := tmp1+#13#10+tmp2+#13#10+tmp3+#13#10+tmp4; end; fBadProgram := err; if err then inc(fProgErrorCount); stop := (MaxErrors > 0) and (fProgErrorCount >= MaxErrors); if assigned(fOnCompMsg) then fOnCompMsg(tmp, stop); if stop then Abort; end; function ExpectedArgType(const firmVer : word; const op : TOpCode; const argIdx: integer): TAsmArgType; begin case op of OP_ADD, OP_SUB, OP_NEG, OP_MUL, OP_DIV, OP_MOD, OP_AND, OP_OR, OP_XOR, OP_NOT, OP_CMNT, OP_LSL, OP_LSR, OP_ASL, OP_ASR, OP_ROTL, OP_ROTR, OP_MOV, OPS_ACOS, OPS_ASIN, OPS_ATAN, OPS_CEIL, OPS_EXP, OPS_FABS, OPS_FLOOR, OPS_SQRT, OPS_TAN, OPS_TANH, OPS_COS, OPS_COSH, OPS_LOG, OPS_LOG10, OPS_SIN, OPS_SINH, OPS_ATAN2, OPS_FMOD, OPS_POW, OPS_ACOS_2, OPS_ASIN_2, OPS_ATAN_2, OPS_CEIL_2, OPS_EXP_2, OPS_FLOOR_2, OPS_TAN_2, OPS_TANH_2, OPS_COS_2, OPS_COSH_2, OPS_LOG_2, OPS_LOG10_2, OPS_SIN_2, OPS_SINH_2, OPS_TRUNC_2, OPS_FRAC_2, OPS_ATAN2_2, OPS_POW_2, OPS_MULDIV_2, OPS_ACOSD_2, OPS_ASIND_2, OPS_ATAND_2, OPS_COSD_2, OPS_COSHD_2, OPS_TAND_2, OPS_TANHD_2, OPS_SIND_2, OPS_SINHD_2, OPS_ATAN2D_2 : begin if argIdx > 0 then Result := aatVariable else Result := aatVarNoConst; end; OP_ARRBUILD : begin if argIdx > 0 then Result := aatVariable else Result := aatArray; end; OP_FLATTEN : begin if argIdx > 0 then Result := aatVariable else // 0 Result := aatStringNoConst; end; OP_STRCAT : begin if argIdx > 0 then Result := aatString else Result := aatStringNoConst; end; OP_NUMTOSTRING : begin if argIdx > 0 then Result := aatScalar else // 0 Result := aatStringNoConst; end; OP_ARRSIZE : begin if argIdx = 1 then Result := aatArray else // 0 Result := aatScalarNoConst; end; OP_UNFLATTEN : begin if argIdx > 2 then Result := aatVariable else if argIdx = 2 then Result := aatString else if argIdx = 1 then Result := aatScalarNoConst else // 0 Result := aatVarNoConst; end; OP_INDEX : begin if argIdx > 2 then Result := aatVariable else if argIdx = 2 then Result := aatScalarOrNull else if argIdx = 1 then Result := aatArray else // 0 Result := aatVarNoConst; end; OP_REPLACE : begin if argIdx = 2 then Result := aatScalarOrNull else if argIdx > 2 then Result := aatVariable else // 0 or 1 Result := aatArray; end; OP_CMP, OP_TST, OP_CMPSET, OP_TSTSET : begin if argIdx = 0 then Result := aatConstant else if argIdx > 1 then Result := aatVariable else Result := aatVarNoConst; end; OP_STRTOBYTEARR : begin if argIdx = 0 then Result := aatArray else // 1 Result := aatString; end; OP_BYTEARRTOSTR : begin if argIdx = 1 then Result := aatArray else // 0 Result := aatStringNoConst; end; OP_ACQUIRE, OP_RELEASE : begin Result := aatMutex; end; OP_SUBRET : begin Result := aatScalarNoConst; end; OP_GETTICK : begin Result := aatScalarNoConst; end; OP_STOP : begin Result := aatScalarorNull; end; OP_ARRSUBSET : begin if argIdx >= 2 then Result := aatScalarOrNull else Result := aatArray; end; OPS_ARROP, OPS_ARROP_2 : begin if argIdx = 0 then Result := aatConstant else if argIdx = 1 then Result := aatVarNoConst else if argIdx >= 3 then Result := aatScalarOrNull else Result := aatArray; end; OP_STRSUBSET : begin if argIdx >= 2 then Result := aatScalarOrNull else if argIdx = 1 then Result := aatString else // 0 Result := aatStringNoConst; end; OP_SET : begin if argIdx > 0 then Result := aatConstant else Result := aatScalarNoConst; end; OP_SUBCALL : begin if argIdx = 0 then Result := aatClumpID else Result := aatScalarNoConst; end; OP_FINCLUMP : begin Result := aatConstant; end; OP_FINCLUMPIMMED : begin Result := aatClumpID; end; OP_JMP : begin Result := aatLabelID; end; OP_BRCMP, OP_BRTST : begin if argIdx = 0 then Result := aatConstant else if argIdx = 1 then Result := aatLabelID else Result := aatVariable; end; OP_SYSCALL : begin if argIdx = 0 then Result := aatConstant else Result := aatCluster; end; OP_SETIN, OP_GETIN : begin if argIdx = 2 then Result := aatConstant else if (op = OP_GETIN) and (argIdx = 0) then Result := aatScalarNoConst else Result := aatScalar; end; OP_SETOUT : begin if argIdx = 0 then Result := aatVariable // could be a scalar or an array else if (argIdx mod 2) = 1 then Result := aatConstant else // argIdx > 0 and even Result := aatScalar; end; OP_GETOUT : begin if argIdx = 2 then Result := aatConstant else if argIdx = 1 then Result := aatScalar else Result := aatScalarNoConst; end; OP_ARRINIT : begin if argIdx = 2 then Result := aatScalarOrNull else if argIdx = 1 then Result := aatVariable else // arg 0 Result := aatArray; end; OP_STRINGTONUM : begin if argIdx >= 3 then Result := aatScalarOrNull else if argIdx = 2 then Result := aatString else // 0 or 1 Result := aatScalarNoConst; end; OP_WAIT : begin if firmVer > MAX_FW_VER1X then begin Result := aatScalarOrNull; end else Result := aatConstant; end; OPS_WAITV{, OP_SQRT_2} : begin if firmVer > MAX_FW_VER1X then begin // OPS_WAITV == OP_SQRT_2 in 2.x firmware if argIdx > 0 then Result := aatVariable else Result := aatVarNoConst; end else Result := aatScalar; end; OPS_WAITV_2 : begin Result := aatScalar; end; OPS_CALL : begin Result := aatClumpID; end; OPS_ABS{, OP_ABS_2}, OPS_SIGN, OPS_SIGN_2 : begin if argIdx = 1 then Result := aatScalar else // 0 Result := aatScalarNoConst; end; OPS_SHL, OPS_SHR : begin if argIdx >= 1 then Result := aatScalar else // 0 Result := aatScalarNoConst; end; OPS_STRINDEX : begin if argIdx > 2 then Result := aatVariable else if argIdx = 2 then Result := aatScalarOrNull else if argIdx = 1 then Result := aatString else // 0 Result := aatVarNoConst; end; OPS_STRREPLACE : begin if argIdx = 2 then Result := aatScalarOrNull else if argIdx > 2 then Result := aatVariable else // 0 or 1 Result := aatString; end; OPS_STRLEN : begin if argIdx = 1 then Result := aatString else // 0 Result := aatScalarNoConst; end; OPS_COMPCHK : begin if argIdx > 2 then Result := aatString else Result := aatConstant; end; OPS_COMPIF : begin Result := aatConstant; end; OPS_COMPCHKTYPE : begin if argIdx = 0 then Result := aatVariable else Result := aatTypeName; end; OPS_START, OPS_START_2 : begin Result := aatClumpID; end; OPS_STOPCLUMP, OPS_STOPCLUMP_2 : begin Result := aatClumpID; end; OPS_PRIORITY, OPS_PRIORITY_2 : begin if argIdx = 0 then Result := aatClumpID else Result := aatConstant; end; OPS_FMTNUM, OPS_FMTNUM_2 : begin if argIdx > 1 then Result := aatScalar else if argIdx = 1 then Result := aatString else // 0 Result := aatStringNoConst; end; OPS_ADDROF : begin if argIdx = 1 then Result := aatVariable else if argIdx = 2 then Result := aatConstant else Result := aatVarNoConst; end; else Result := aatConstant; end; end; procedure TRXEProgram.HandleConstantExpressions(AL: TAsmLine); var expected : TAsmArgType; i, j, delta : integer; // n : integer; arg : TAsmArgument; val : Extended; iVal : Int64; tmpName, tmpValue : string; DE, Sub : TDataspaceEntry; bValidCC : boolean; // newLine : TAsmLine; tmpType : TDSType; begin // if this line requires a reference to a temporary scalar variable // then define a constant variable reference and use it whereever this value // needs to be used // The new asm line calls the "set" opcode setting the temporary variable // to the constant value. // check all the arguments for this line to see if their argument type // matches the expected argument type. If it does then do nothing. // if it doesn't and the expected type allows for a temporary then create one // and adjust the argument appropriately. // n := 0; ProcessSpecialFunctions(AL); if AL.Command in [OP_CMP, OP_TST, OP_CMPSET, OP_TSTSET, OP_BRCMP, OP_BRTST] then begin if AL.Args.Count > 0 then begin FixupComparisonCodes(AL.Args[0]); arg := AL.Args[0]; bValidCC := False; Calc.SilentExpression := arg.Value; if not Calc.ParserError then begin iVal := Trunc(Calc.Value); bValidCC := ValidCompareCode(Byte(iVal)); if bValidCC then arg.Value := IntToStr(iVal); end; if Calc.ParserError or not bValidCC then begin ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidCompareCode, [arg.Value]), true); arg.Value := '-1'; // set to a valid numeric string constant end; end; // skip the comparison argument delta := 1; end else delta := 0; for i := delta to AL.Args.Count - 1 do begin // the optional 4th argument of the compchk opcode is a special case if (AL.Command = OPS_COMPCHK) and (i = 3) then Continue; expected := ExpectedArgType(FirmwareVersion, AL.Command, i); arg := AL.Args[i]; if expected in [aatVariable, aatVarOrNull, aatArray, aatString, aatScalar, aatScalarOrNull] then begin // look at the argument and see if it is of the variable type // if not then create temporary. j := Dataspace.IndexOfName(arg.Value); if j = -1 then begin // the current argument is not a known variable and it is supposed to be one // argument could also be a constant expression which needs to be evaluated. // but first we need to rule out the possibility that the argument is a // IO Map address macro j := IndexOfIOMapName(arg.Value); if j = -1 then begin // is it a string? if (arg.IsQuoted('''') or arg.IsQuoted('"')) and not (expected in [aatScalar, aatScalarOrNull]) then begin // maintain a map between string constants and variable names tmpValue := StripQuotes(arg.Value); j := fConstStrMap.IndexOf(tmpValue); if j = -1 then begin tmpName := Format('__constStr%4.4d', [fConstStrMap.Count]); fConstStrMap.AddEntry(tmpValue, tmpName); DE := DataSpace.Add; // this is an array type DE.Identifier := tmpName; DE.DataType := dsArray; Sub := DE.SubEntries.Add; Sub.Identifier := DE.Identifier + '_type'; Sub.DataType := dsUByte; // the args value is an initializer DE.AddValuesFromString(Calc, arg.Value); end else tmpName := fConstStrMap.MapValue[j]; // we have a temporary called 'tmpName' in the dataspace // so switch our line to use it instead arg.Value := tmpName; end else if (IsDelimiter('{', arg.Value, 1) and IsDelimiter('}', arg.Value, Length(arg.Value))) and not (expected in [aatScalar, aatScalarOrNull]) then begin // maintain a map between constants and variable names tmpValue := StripQuotes(arg.Value); // removes '{' and '}' j := fConstStrMap.IndexOf(tmpValue); if j = -1 then begin tmpName := Format('__constStr%4.4d', [fConstStrMap.Count]); fConstStrMap.AddEntry(tmpValue, tmpName); DE := DataSpace.Add; // this is an array type DE.Identifier := tmpName; DE.DataType := dsArray; Sub := DE.SubEntries.Add; Sub.Identifier := DE.Identifier + '_type'; // constant array type defaults to signed long Sub.DataType := dsSLong; // the args value is an initializer tmpType := DE.AddValuesFromString(Calc, arg.Value); Sub.DataType := tmpType; end else tmpName := fConstStrMap.MapValue[j]; // we have a temporary called 'tmpName' in the dataspace // so switch our line to use it instead arg.Value := tmpName; end else begin // now we can assume the arg is supposed to be a constant expression val := arg.Evaluate(Calc); iVal := Trunc(val); // one more check with respect to IOMap Addresses. j := IndexOfIOMapID(Integer(iVal)); if ((expected in [aatVarOrNull, aatScalarOrNull]) and (iVal = NOT_AN_ELEMENT)) or (j <> -1) then begin // we have an IO Map address as a constant expression arg.Value := IntToStr(iVal); end else begin // definitely not an IO Map Address // what type should this temporary be? tmpName := CreateConstantVar(DataSpace, val, False, GetTypeHint(DataSpace, AL, i, EnhancedFirmware)); // we have a temporary called 'tmpName' in the dataspace // so switch our line to use it instead arg.Value := tmpName; end; end; end; end; end else if expected = aatConstant then begin Calc.SilentExpression := arg.Value; if Calc.ParserError then begin if not fIgnoreLines then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sBadConstExpression, [arg.Value]), true); arg.Value := '-1'; // set to a valid numeric string end else arg.Value := NBCFloatToStr(Calc.Value); // arg.Value := IntToStr(Trunc(Calc.Value)); end; end; end; function GetArgDataType(val : Extended): TDSType; var iVal : Int64; begin iVal := Trunc(val); if iVal = val then begin val := iVal; // see if this works. if not then figure out the // type based on the size of the value if (val >= Low(ShortInt)) and (val <= High(ShortInt)) then Result := dsSByte else if (val >= Low(SmallInt)) and (val <= High(SmallInt)) then Result := dsSWord else if (val >= Low(Integer)) and (val <= High(Integer)) then Result := dsSLong else if (val > High(Cardinal)) or (val < Low(Integer)) then Result := dsFloat else Result := dsULong; end else Result := dsFloat; // else if ((val >= 0) and (val <= High(Byte)) then // Result := dsUByte // else if ((val >= 0) and (val <= High(Word)) then // Result := dsUWord end; procedure TRXEProgram.UpdateHeader; begin fHeader.DSCount := fDSData.DSCount; fHeader.DSStaticSize := fDSData.DSStaticSize; fHeader.DynDSDefaultsOffset := fDSData.DynDSDefaultsOffset; fHeader.DynDSDefaultsSize := fDSData.DynDSDefaultsSize; fHeader.DVArrayOffset := fDSData.DVArrayOffset; fHeader.ClumpCount := Word(Codespace.Count); fHeader.CodespaceCount := fCode.CodespaceCount; fHeader.MemMgrHead := fDSData.Head; fHeader.MemMgrTail := fDSData.Tail; fHeader.DSDefaultsSize := Word(fHeader.DynDSDefaultsOffset + fHeader.DynDSDefaultsSize); fHeader.DSSize := Word(fHeader.DSStaticSize + fHeader.DynDSDefaultsSize); end; procedure TRXEProgram.CheckArgs(AL: TAsmLine); var arg : string; NI : NXTInstruction; i : integer; val : integer; argType : TAsmArgType; de, de2 : TDataspaceEntry; begin if AL.Command <> OPS_INVALID then begin i := IndexOfOpcode(AL.Command); if i = -1 then begin ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidOpcode, [OpcodeToStr(Al.Command)]), true); end else begin NI := GetNXTInstruction(i); case AL.Command of OP_CMP, OP_TST, OP_CMPSET, OP_TSTSET, OP_BRCMP, OP_BRTST : begin if AL.Args.Count <> NI.Arity+1 then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgs, [NI.Arity+1, AL.Args.Count]), true); end; OP_FINCLUMP : begin // can have 2 or zero arguments if (AL.Args.Count <> NI.Arity) and (AL.Args.Count <> 0) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgs, [NI.Arity, AL.Args.Count]), true); end; OP_ARRBUILD, OP_STRCAT : begin // must have at least 2 arguments if (AL.Args.Count < 2) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgsVar, [2, AL.Args.Count]), true); end; OP_SETOUT : begin // must have at least 3 arguments if (AL.Args.Count < 3) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgsVar, [3, AL.Args.Count]), true) else if (AL.Args.Count mod 2) = 0 then begin // total number of args must be odd ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidNumArgsOdd, true); end; end; OP_DIV : begin // if second argument is signed and third is unsigned then // bad things might happen if AL.Args.Count = NI.Arity then begin de := Dataspace.FindEntryByFullName(AL.Args[1].Value); de2 := Dataspace.FindEntryByFullName(AL.Args[2].Value); if Assigned(de) and Assigned(de2) then begin if (de.DataType in [dsSByte, dsSWord, dsSLong]) and (de2.DataType in [dsUByte, dsUWord, dsULong]) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sUnsafeDivision, false); end else begin if not Assigned(de) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [AL.Args[1].Value]), true) else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [AL.Args[2].Value]), true); end; end; end; OP_SET : begin // must have 2 arguments if AL.Args.Count <> NI.Arity then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgs, [NI.Arity, AL.Args.Count]), true); // the first argument must not be anything other than an integer datatype de := Dataspace.FindEntryByFullName(AL.Args[0].Value); if Assigned(de) then begin if de.DataType = dsFloat then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidSetStatement, true); end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [AL.Args[0].Value]), true); // second argument must be a constant within the range of UWORD // or SWORD arg := AL.Args[1].Value; // should be a number Calc.SilentExpression := arg; if Calc.ParserError then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sBadConstExpression, [arg]), true) else begin // make sure it is in range val := Integer(Trunc(Calc.Value)); if (val < Low(SmallInt)) or (val > High(Word)) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sConstOutOfRange, [val, Low(SmallInt), High(Word)]), true) end; end; OPS_COMPCHK : begin // can have 3 or 4 arguments if (AL.Args.Count <> NI.Arity) and (AL.Args.Count <> NI.Arity+1) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgs, [NI.Arity, AL.Args.Count]), true); end; else // case if (NI.Arity < 6) and (AL.Args.Count <> NI.Arity) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidNumArgs, [NI.Arity, AL.Args.Count]), true); end; for i := 0 to AL.Args.Count - 1 do begin // the optional 4th argument of the compchk opcode is a special case if (AL.Command = OPS_COMPCHK) and (i = 3) then Continue; arg := AL.Args[i].Value; argType := ExpectedArgType(FirmwareVersion, Al.Command, i); case argType of aatVariable, aatVarNoConst, aatVarOrNull, aatScalar, aatScalarNoConst, aatScalarOrNull : begin // arg must be in list of known variables de := Dataspace.FindEntryAndAddReference(arg); if (de = nil) and (IndexOfIOMapName(arg) = -1) then begin Calc.SilentExpression := arg; val := Integer(Trunc(Calc.Value)); if IndexOfIOMapID(val) = -1 then begin if (not (argType in [aatVarOrNull, aatScalarOrNull])) or ((val <> NOT_AN_ELEMENT) and (val <> -1)) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [arg]), true); end; end else if Assigned(de) and (argType in [aatScalar, aatScalarNoConst, aatScalarOrNull]) then begin // a known variable name but is it a scalar if de.DataType in [dsVoid, dsArray, dsCluster, dsMutex] then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidScalarArg, [arg]), true); end; end; aatArray : begin de := Dataspace.FindEntryAndAddReference(arg); if (de = nil) or (de.DataType <> dsArray) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidArrayArg, [arg]), true); end; aatString, aatStringNoConst : begin // arg must be in list of known variables de := Dataspace.FindEntryAndAddReference(arg); if (de = nil) or (de.DataType <> dsArray) or not (de.SubEntries[0].DataType in [dsUByte, dsSByte]) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidStringArg, [arg]), true); end; aatConstant : begin // if it is a constant then I should be able to evaluate it Calc.SilentExpression := arg; if Calc.ParserError then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sBadConstExpression, [arg]), true); end; aatLabelID : begin // Labels are checked elsewhere (ValidateLabels) end; aatClumpID : begin // can't check clumpIDs yet since it could be not yet defined // but we can at least require them to be valid identifiers if not IsValidIdent(arg) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidClumpArg, [arg]), true); end; aatCluster : begin de := Dataspace.FindEntryAndAddReference(arg); if (de = nil) or (de.DataType <> dsCluster) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidClusterArg, [arg]), true); end; aatMutex : begin de := Dataspace.FindEntryAndAddReference(arg); // we want to keep a list of all the threads that reference a // mutex in order to help us correctly optimize them later on. if Assigned(de) and (de.DataType = dsMutex) then begin de.AddThread(fClumpName); end else // if (de = nil) or (de.DataType <> dsMutex) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidMutexArg, [arg]), true); end; end; end; end; end; end; procedure TRXEProgram.HandleNameToDSID(const aName: string; var aId: integer); begin aId := Dataspace.DataspaceIndex(aName); end; procedure TRXEProgram.CreateObjects; begin fCalc := TNBCExpParser.Create(nil); fCalc.CaseSensitive := fCaseSensitive; fCalc.OnParserError := HandleCalcParserError; fCalc.StandardDefines := fStandardDefines; fCalc.ExtraDefines := fExtraDefines; fDD := TDataDefs.Create; fDS := TDataspace.Create; fDS.CaseSensitive := fCaseSensitive; fCS := TCodeSpace.Create(self, fDS); fCS.CaseSensitive := fCaseSensitive; fCS.OnNameToDSID := HandleNameToDSID; fDSData := TDSData.Create; fClumpData := TClumpData.Create; fCode := TCodeSpaceAry.Create; fNamedTypes := TMapList.Create; fNamedTypes.CaseSensitive := fCaseSensitive; fNamedTypes.Duplicates := dupError; fConstStrMap := TMapList.Create; fMsgs := TStringList.Create; fCS.Calc := fCalc; fIncDirs := TStringList.Create; fCompilerOutput := TStringList.Create; fSymbolTable := TStringList.Create; fDefines := TStringList.Create; fSpawnedThreads := TStringList.Create; TStringList(fSpawnedThreads).CaseSensitive := True; TStringList(fSpawnedThreads).Duplicates := dupIgnore; fSpecialFunctions := TObjectList.Create; LoadSpecialFunctions; fVarI := 0; fVarJ := 0; fOptimizeLevel := 0; end; procedure TRXEProgram.FreeObjects; begin fConstStrMap.Clear; fNamedTypes.Clear; FreeAndNil(fDD); FreeAndNil(fDS); FreeAndNil(fCS); FreeAndNil(fNamedTypes); FreeAndNil(fConstStrMap); FreeAndNil(fDSData); FreeAndNil(fClumpData); FreeAndNil(fCode); FreeAndNil(fMsgs); FreeAndNil(fCalc); FreeAndNil(fIncDirs); FreeAndNil(fCompilerOutput); FreeAndNil(fSymbolTable); FreeAndNil(fDefines); FreeAndNil(fSpawnedThreads); FreeAndNil(fSpecialFunctions); end; procedure TRXEProgram.Clear; begin FreeObjects; CreateObjects; InitializeHeader; end; procedure TRXEProgram.InitializeHeader; begin fHeader.FormatString := 'MindstormsNXT'; fHeader.Version := CompilerVersion; fHeader.DSCount := 0; fHeader.DSSize := 0; fHeader.DSStaticSize := 0; fHeader.DSDefaultsSize := 0; fHeader.DynDSDefaultsOffset := 0; fHeader.DynDSDefaultsSize := 0; fHeader.MemMgrHead := 0; fHeader.MemMgrTail := 0; fHeader.ClumpCount := 0; fHeader.CodespaceCount := 0; end; procedure TRXEProgram.HandleCalcParserError(Sender: TObject; E: Exception); begin if Assigned(Sender) and not fIgnoreLines then ReportProblem(LineCounter, GetCurrentFile(true), '', E.Message, True); end; procedure TRXEProgram.SetCaseSensitive(const Value: boolean); begin fCaseSensitive := Value; fCalc.CaseSensitive := Value; fNamedTypes.CaseSensitive := Value; fDS.CaseSensitive := fCaseSensitive; fCS.CaseSensitive := fCaseSensitive; end; procedure TRXEProgram.SetStandardDefines(const Value: boolean); begin fCalc.StandardDefines := Value; fStandardDefines := Value; end; procedure TRXEProgram.SetExtraDefines(const Value: boolean); begin fCalc.ExtraDefines := Value; fExtraDefines := Value; end; procedure TRXEProgram.SetCompVersion(const Value: byte); begin fCompVersion := Value; fHeader.Version := Value; end; procedure TRXEProgram.ValidateLabels(aClump: TClump); var arg : string; i, j : integer; argType : TAsmArgType; AL : TAsmLine; begin for j := 0 to aCLump.ClumpCode.Count - 1 do begin AL := aClump.ClumpCode[j]; if AL.Command <> OPS_INVALID then begin for i := 0 to AL.Args.Count - 1 do begin arg := AL.Args[i].Value; argType := ExpectedArgType(FirmwareVersion, Al.Command, i); case argType of aatLabelID : begin // check labels if (aClump.IndexOfLabel(arg) = -1) or not IsValidIdent(arg) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidLabelArg, [arg]), true); end; end; end; end; end; end; procedure TRXEProgram.SetIncDirs(const Value: TStrings); begin fIncDirs.Assign(Value); end; function TRXEProgram.GetSymbolTable: TStrings; begin Result := fSymbolTable; Result.Clear; Result.BeginUpdate; try fDSData.SaveToSymbolTable(Result); Codespace.SaveToSymbolTable(Result); finally Result.EndUpdate; end; end; procedure TRXEProgram.CreateWaitClump(const basename: string); var C : TClump; AL : TAsmLine; begin C := CodeSpace.Add; C.Name := Format('__%s_wait', [basename]); C.Filename := GetCurrentFile(true); AL := C.ClumpCode.Add; AL.Command := OP_GETTICK; AL.AddArgs(Format('%s_now', [C.Name])); AL := C.ClumpCode.Add; AL.Command := OP_ADD; AL.AddArgs(Format('%0:s_then, %0:s_now, %0:s_ms', [C.Name])); AL := C.ClumpCode.Add; AL.LineLabel := Format('%sing', [C.Name]); C.AddLabel(AL.LineLabel, AL); AL.Command := OP_GETTICK; AL.AddArgs(Format('%s_now', [C.Name])); AL := C.ClumpCode.Add; AL.Command := OP_BRCMP; AL.AddArgs(Format('LT, %0:sing, %0:s_now, %0:s_then', [C.Name])); AL := C.ClumpCode.Add; AL.Command := OP_SUBRET; AL.AddArgs(Format('%s_return', [C.Name])); end; procedure TRXEProgram.CreateSpawnerClump(const basename: string); var C : TClump; AL : TAsmLine; begin C := CodeSpace.Add; C.Name := Format('__%s_Spawner', [basename]); C.Filename := GetCurrentFile(true); C.AddClumpDependencies('precedes', Format('%0:s, __%0:s_Returner', [basename])); // exit AL := C.ClumpCode.Add; AL.Command := OP_FINCLUMP; end; procedure TRXEProgram.CreateReturnerClump(const basename: string); var C : TClump; AL : TAsmLine; begin C := CodeSpace.Add; C.Name := Format('__%s_Returner', [basename]); C.Filename := GetCurrentFile(true); // subret __x_Spawner_return AL := C.ClumpCode.Add; AL.Command := OP_SUBRET; AL.AddArgs(Format('__%s_Spawner_return', [basename])); end; procedure TRXEProgram.DefineWaitArgs(const basename: string); var DE : TDataspaceEntry; idstr : string; begin idstr := Format('__%s_wait_', [basename]); DE := Dataspace.Add; DE.DataType := SubroutineReturnAddressType; DE.Identifier := idstr + 'return'; // refcount is 1+caller DE.IncRefCount; DE := Dataspace.Add; DE.DataType := dsUWord; DE.Identifier := idstr + 'ms'; // refcount is 1+caller DE.IncRefCount; DE := Dataspace.Add; DE.DataType := dsULong; DE.Identifier := idstr + 'now'; // refcount is 3 DE.IncRefCount; DE.IncRefCount; DE.IncRefCount; DE := Dataspace.Add; DE.DataType := dsULong; DE.Identifier := idstr + 'then'; // refcount is 2 DE.IncRefCount; DE.IncRefCount; end; procedure TRXEProgram.HandlePseudoOpcodes(AL: TAsmLine; op: TOpCode{; const args: string}); var Arg : TAsmArgument; a1, a2, a3, a4, a5, c1, c2 : string; de1, de2, de3, de4, de5 : TDataspaceEntry; tmpLine, shiftConst : integer; begin tmpLine := AL.LineNum; case op of OP_WAIT, OPS_WAITV, OPS_WAITI_2, OPS_WAITV_2 : begin // 2.x firmwares support wait and OPS_WAITV == OP_SQRT_2 if (FirmwareVersion > MAX_FW_VER1X) then begin if op in [OP_WAIT, OP_SQRT_2{, OPS_WAITV}] then Exit; if not EnhancedFirmware then begin // opcode is either OPS_WAITI_2 or OPS_WAITV_2 // convert it to OP_WAIT with 2 args if op = OPS_WAITI_2 then begin //AL == waiti 12345 c1 := CreateConstantVar(DataSpace, StrToIntDef(AL.Args[0].Value, 0), True); Arg := AL.Args[0]; Arg.Value := c1; end; Arg := AL.Args.Insert(0); Arg.Value := STR_NA; AL.Command := OP_WAIT; end; end else begin if not EnhancedFirmware then begin // convert OPS_WAITV // if this is a wait opcode we replace it with two lines of code if not fClumpUsesWait then DefineWaitArgs(fCurrentClump.Name); fClumpUsesWait := True; if op = OP_WAIT then AL.Command := OP_SET else AL.Command := OP_MOV; Arg := AL.Args.Insert(0); Arg.Value := Format('__%s_wait_ms', [fCurrentClump.Name]); Dataspace.FindEntryAndAddReference(Arg.Value); // inc refcount AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_SUBCALL; AL.LineNum := tmpLine; Arg := AL.Args.Add; Arg.Value := Format('__%s_wait', [fCurrentClump.Name]); Arg := AL.Args.Add; Arg.Value := Format('__%0:s_wait_return', [fCurrentClump.Name]); Dataspace.FindEntryAndAddReference(Arg.Value); // inc refcount end; end; end; OPS_STRINDEX : begin // just replace opcode AL.Command := OP_INDEX; end; OPS_STRREPLACE : begin // just replace opcode AL.Command := OP_REPLACE; end; OPS_COMPCHK : begin AL.Command := OPS_INVALID; // make this line a no-op DoCompilerCheck(AL, False); end; OPS_COMPCHKTYPE : begin AL.Command := OPS_INVALID; // make this line a no-op DoCompilerCheckType(AL); end; OPS_COMPIF : begin AL.Command := OPS_INVALID; // make this line a no-op DoCompilerCheck(AL, True); end; OPS_COMPELSE : begin AL.Command := OPS_INVALID; // make this line a no-op fIgnoreLines := not fIgnoreLines; end; OPS_COMPEND : begin AL.Command := OPS_INVALID; // make this line a no-op fIgnoreLines := False; end; OPS_STRLEN : begin if AL.Args.Count = 2 then begin c1 := CreateConstantVar(DataSpace, 1, True); a1 := AL.Args[0].Value; de1 := Dataspace.FindEntryByFullName(a1); AL.Command := OP_ARRSIZE; // sub AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_SUB; AL.LineNum := tmpLine; AL.AddArgs(Format('%0:s, %0:s, %s', [a1, c1])); if Assigned(de1) then begin de1.IncRefCount; de1.IncRefCount; end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [AL.Args[0].Value]), true); end; end; OPS_START, OPS_START_2 : begin if AL.Args.Count < 1 then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidStatement, true) else begin a1 := AL.Args[0].Value; // base thread name if not EnhancedFirmware then begin // replace start with subcall and automatic return address variable. AL.Command := OP_SUBCALL; AL.Args[0].Value := Format('__%s_Spawner', [a1]); Arg := AL.Args.Add; Arg.Value := Format('%s_return', [AL.Args[0].Value]); DefineVar(Arg.Value, SubroutineReturnAddressType); RegisterThreadForSpawning(a1); end; // need to mark clumps as multi-threaded CodeSpace.Multithread(fCurrentClump.Name); CodeSpace.Multithread(a1); end; end; OPS_STOPCLUMP, OPS_PRIORITY, OPS_FMTNUM, OPS_STOPCLUMP_2, OPS_PRIORITY_2, OPS_FMTNUM_2 : begin if not EnhancedFirmware then begin // replace with no-op if not running enhanced firmware and report error ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidOpcode, [OpcodeToStr(Al.Command)]), true); AL.Command := OPS_INVALID; end; end; OPS_CALL : begin // subcall with automatic return address variable. AL.Command := OP_SUBCALL; Arg := AL.Args.Add; Arg.Value := Format('__%s_return', [AL.Args[0].Value]); if not fIgnoreLines then DefineVar(Arg.Value, SubroutineReturnAddressType); end; OPS_RETURN : begin // first make sure it only is present in a subroutine if not fCurrentClump.IsSubroutine then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sReturnNotInSub, true); // subret with automatic return address variable AL.Command := OP_SUBRET; Arg := AL.Args.Add; Arg.Value := Format('__%s_return', [fCurrentClump.Name]); if not fIgnoreLines then DefineVar(Arg.Value, SubroutineReturnAddressType); end; OPS_ABS{, OP_ABS_2} : begin // 2.x standard firmware supports ABS opcode if FirmwareVersion > MAX_FW_VER1X then Exit; if not EnhancedFirmware then begin if AL.Args.Count = 2 then begin a1 := AL.Args[0].Value; a2 := AL.Args[1].Value; de1 := Dataspace.FindEntryByFullName(a1); de2 := Dataspace.FindEntryByFullName(a2); AL.Command := OP_MOV; AL.Args.Clear; AL.AddArgs(Format('%s, %s', [a1, a2])); AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_BRTST; AL.LineNum := tmpLine; AL.AddArgs(Format('GTEQ, __abs_%d, %s', [fAbsCount, a2])); AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_NEG; AL.LineNum := tmpLine; AL.AddArgs(Format('%s, %s', [a1, a2])); AL := fCurrentClump.ClumpCode.Add; AL.Command := OPS_INVALID; // OPS_MOV; AL.LineNum := tmpLine; AL.LineLabel := Format('__abs_%d', [fAbsCount]); fCurrentClump.AddLabel(AL.LineLabel, AL); inc(fAbsCount); if Assigned(de1) and Assigned(de2) then begin de1.IncRefCount; de2.IncRefCount; de2.IncRefCount; end else begin if not Assigned(de1) then ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [a1]), true) else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [a2]), true); end; end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidStatement, true); end; end; OPS_SIGN, OPS_SIGN_2 : begin if not EnhancedFirmware then begin if AL.Args.Count = 2 then begin a1 := AL.Args[0].Value; a2 := AL.Args[1].Value; de2 := Dataspace.FindEntryByFullName(a2); a3 := Format('__%s_sign_tmp', [fCurrentClump.Name]); if not fClumpUsesSign then begin with Dataspace.Add do begin DataType := dsSByte; // only needs to store -1, 0, or 1 Identifier := a3; end; end; de3 := Dataspace.FindEntryByFullName(a3); fClumpUsesSign := True; AL.Command := OP_SET; AL.Args.Clear; AL.AddArgs(Format('%s, 0', [a3])); de3.IncRefCount; AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_BRTST; AL.LineNum := tmpLine; AL.AddArgs(Format('EQ, __sign_%d, %s', [fSignCount, a2])); AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_SET; AL.LineNum := tmpLine; AL.AddArgs(Format('%s, -1', [a3])); de3.IncRefCount; AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_BRTST; AL.LineNum := tmpLine; AL.AddArgs(Format('LT, __sign_%d, %s', [fSignCount, a2])); AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_SET; AL.LineNum := tmpLine; AL.AddArgs(Format('%s, 1', [a3])); de3.IncRefCount; AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_MOV; AL.LineNum := tmpLine; AL.LineLabel := Format('__sign_%d', [fSignCount]); AL.AddArgs(Format('%s, %s', [a1, a3])); de3.IncRefCount; fCurrentClump.AddLabel(AL.LineLabel, AL); inc(fSignCount); if Assigned(de2) then de2.IncRefCount else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [a2]), true); end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidStatement, true); end; end; OPS_SHL, OPS_SHR : begin if AL.Args.Count = 3 then begin a1 := AL.Args[0].Value; a2 := AL.Args[1].Value; a3 := AL.Args[2].Value; // is this argument a constant??? if Pos('__constVal', a3) = 1 then begin // if the argument is a constant then generate a single mul or div // shLR a1, a2, a3 // first get the constant value de3 := Dataspace.FindEntryByFullName(a3); if Assigned(de3) then begin de3.DecRefCount; // this constant is used 1 less time than it used to be shiftConst := Integer(de3.DefaultValue); end else begin ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sInvalidVarArg, [a3]), true); shiftConst := 0; end; if shiftConst >= 0 then begin if shiftConst = 0 then AL.Command := OPS_INVALID else if AL.Command = OPS_SHL then AL.Command := OP_MUL else AL.Command := OP_DIV; shiftConst := Trunc(Power(2,shiftConst)); c1 := CreateConstantVar(DataSpace, shiftConst, True); AL.Args.Clear; AL.AddArgs(Format('%s, %s, %s', [a1, a2, c1])); end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sNoNegShifts, true); end else begin if not EnhancedFirmware then begin // what about shifting by a variable containing a negative value??? c1 := CreateConstantVar(DataSpace, 1, True); c2 := CreateConstantVar(DataSpace, 2, True); if not fClumpUsesShift then DefineShiftArgs(fCurrentClump.Name); fClumpUsesShift := True; a4 := Format('__%s_shift_cnt', [fCurrentClump.Name]); a5 := Format('__%s_shift_tmp', [fCurrentClump.Name]); de1 := Dataspace.FindEntryByFullName(a1); de4 := Dataspace.FindEntryByFullName(a4); de5 := Dataspace.FindEntryByFullName(a5); if assigned(de1) and assigned(de4) and assigned(de5) then begin // shLR a1, a2, a3 // mov __shift_cnt, a3 AL.Command := OP_MOV; AL.Args.Clear; AL.AddArgs(Format('%s, %s', [a4, a3])); de4.IncRefCount; // mov __shift_tmp, a2 AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_MOV; AL.LineNum := tmpLine; AL.AddArgs(Format('%s, %s', [a5, a2])); de5.IncRefCount; // label: brtst LTEQ, __shiftdone_NN, __shift_cnt AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_BRTST; AL.LineNum := tmpLine; AL.AddArgs(Format('LTEQ, __shiftdone_%d, %s', [fShiftCount, a4])); AL.LineLabel := Format('__shiftstart_%d', [fShiftCount]); fCurrentClump.AddLabel(AL.LineLabel, AL); de4.IncRefCount; // mul/div __shift_tmp, __shift_tmp, 2 AL := fCurrentClump.ClumpCode.Add; if op = OPS_SHR then AL.Command := OP_DIV else AL.Command := OP_MUL; AL.LineNum := tmpLine; AL.AddArgs(Format('%0:s, %0:s, %s', [a5, c2])); de5.IncRefCount; de5.IncRefCount; // sub __shift_cnt, __shift_cnt, 1 AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_SUB; AL.LineNum := tmpLine; AL.AddArgs(Format('%0:s, %0:s, %s', [a4, c1])); de4.IncRefCount; de4.IncRefCount; // jmp __shiftstart_NNN AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_JMP; AL.LineNum := tmpLine; AL.AddArgs(Format('__shiftstart_%d', [fShiftCount])); // label __shiftdone_NNN AL := fCurrentClump.ClumpCode.Add; AL.Command := OPS_INVALID; AL.LineNum := tmpLine; AL.LineLabel := Format('__shiftdone_%d', [fShiftCount]); fCurrentClump.AddLabel(AL.LineLabel, AL); // mov a1, __shift_tmp AL := fCurrentClump.ClumpCode.Add; AL.Command := OP_MOV; AL.LineNum := tmpLine; AL.AddArgs(Format('%s, %s', [a1, a5])); de1.IncRefCount; de5.IncRefCount; inc(fShiftCount); end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidStatement, true); end else begin if op = OPS_SHL then AL.Command := OP_ASL else AL.Command := OP_ASR; end; end; end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidStatement, true); end; end; end; function TRXEProgram.ReplaceTokens(const line: string): string; var p : integer; begin Result := line; // line is already trimmed if Length(Result) = 0 then Exit; // Result := Replace(Result, '##', ''); if Length(Result) = 0 then Exit; if Pos('__ResetI__', Result) > 0 then begin Result := Replace(Result, '__ResetI__', ''); fVarI := 0; end; if Length(Result) = 0 then Exit; p := Pos('__IncI__', Result); while p > 0 do begin inc(fVarI); System.Delete(Result, p, 8); p := Pos('__IncI__', Result); end; if Length(Result) = 0 then Exit; p := Pos('__DecI__', Result); while p > 0 do begin dec(fVarI); System.Delete(Result, p, 8); p := Pos('__DecI__', Result); end; if Length(Result) = 0 then Exit; if Pos('__ResetJ__', Result) > 0 then begin Result := Replace(Result, '__ResetJ__', ''); fVarJ := 0; end; if Length(Result) = 0 then Exit; p := Pos('__IncJ__', Result); while p > 0 do begin inc(fVarJ); System.Delete(Result, p, 8); p := Pos('__IncJ__', Result); end; if Length(Result) = 0 then Exit; p := Pos('__DecJ__', Result); while p > 0 do begin dec(fVarJ); System.Delete(Result, p, 8); p := Pos('__DecJ__', Result); end; if Length(Result) = 0 then Exit; Result := Replace(Result, '__I__', IntToStr(fVarI)); Result := Replace(Result, '__J__', IntToStr(fVarJ)); Result := Replace(Result, '__THREADNAME__', fClumpName); Result := Replace(Result, '__LINE__', IntToStr(LineCounter)); Result := Replace(Result, '__FILE__', GetCurrentFile(false)); Result := Replace(Result, '__VER__', fProductVersion); end; function TRXEProgram.GetCurrentFile(bFullPath: boolean): string; begin Result := fCurrentFile; if bFullPath and (GetCurrentPath <> '') then Result := IncludeTrailingPathDelimiter(GetCurrentPath) + Result; end; function TRXEProgram.GetCurrentPath: string; begin Result := fCurrentPath; end; procedure TRXEProgram.SetCurrentFile(const Value: string); begin if fCurrentPath + fCurrentFile <> Value then begin fCurrentFile := ExtractFilename(Value); fCurrentPath := ExtractFilePath(Value); // DoCompilerStatusChange(Format(sCurrentFile, [Value])); end; end; procedure TRXEProgram.FixupComparisonCodes(Arg: TAsmArgument); var val : string; begin val := Arg.Value; if val = '<' then Arg.Value := '0' else if val = '>' then Arg.Value := '1' else if val = '<=' then Arg.Value := '2' else if val = '>=' then Arg.Value := '3' else if val = '==' then Arg.Value := '4' else if val = '!=' then Arg.Value := '5' else if val = '<>' then Arg.Value := '5'; end; procedure TRXEProgram.ProcessSpecialFunctions(AL: TAsmLine); var i, j, p : integer; Arg : TAsmArgument; name, leftstr, rightstr : string; SF : TSpecialFunction; begin for i := 0 to AL.Args.Count - 1 do begin Arg := AL.Args[i]; for j := 0 to fSpecialFunctions.Count - 1 do begin SF := TSpecialFunction(fSpecialFunctions[j]); p := Pos(SF.Func, Arg.Value); while p > 0 do begin name := Arg.Value; leftstr := Copy(name, 1, p-1); // everything before the first "sizeof(" System.Delete(name, 1, p+Length(SF.Func)-1); p := Pos(')', name); rightstr := Copy(name, p+1, MaxInt); // everything after the first ")" System.Delete(name, p, MaxInt); SF.Execute(Arg, leftstr, rightstr, name); p := Pos(SF.Func, Arg.Value); end; end; end; end; procedure TRXEProgram.DefineShiftArgs(const basename: string); var DE : TDataspaceEntry; begin DE := Dataspace.Add; DE.DataType := dsSByte; DE.Identifier := Format('__%s_shift_cnt', [basename]); DE := Dataspace.Add; DE.DataType := dsSLong; DE.Identifier := Format('__%s_shift_tmp', [basename]); end; procedure TRXEProgram.DoCompilerCheck(AL: TAsmLine; bIfCheck : boolean); var i1, i2, i3 : integer; bCheckOkay : boolean; errMsg : string; begin if fIgnoreLines then Exit; bCheckOkay := False; if AL.Args.Count >= 3 then begin i2 := StrToIntDef(AL.Args[0].Value, OPCC1_EQ); i1 := StrToIntDef(AL.Args[1].Value, 0); i3 := StrToIntDef(AL.Args[2].Value, 0); case i2 of OPCC1_LT : bCheckOkay := i1 < i3; OPCC1_GT : bCheckOkay := i1 > i3; OPCC1_LTEQ : bCheckOkay := i1 <= i3; OPCC1_GTEQ : bCheckOkay := i1 >= i3; OPCC1_EQ : bCheckOkay := i1 = i3; OPCC1_NEQ : bCheckOkay := i1 <> i3; end; if not bCheckOkay then begin if bIfCheck then fIgnoreLines := True else begin if AL.Args.Count > 3 then errMsg := AL.Args[3].Value else errMsg := Format(sCompCheckFailed, [i1, CCToStr(i2), i3]); ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, errMsg, true); end; end else if bIfCheck then fIgnoreLines := False; end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidCompCheck, true); end; procedure TRXEProgram.DefineVar(aVarName: string; dt :TDSType); var DE : TDataspaceEntry; begin DE := Dataspace.FindEntryByFullName(aVarName); if not Assigned(DE) then begin DE := Dataspace.Add; DE.DataType := dt; DE.Identifier := aVarName; end; DE.IncRefCount; end; procedure TRXEProgram.RegisterThreadForSpawning(aThreadName: string); begin fSpawnedThreads.Add(aThreadName); end; procedure TRXEProgram.ProcessSpawnedThreads; var i : integer; t, spawner : string; begin for i := 0 to fSpawnedThreads.Count - 1 do begin t := fSpawnedThreads[i]; spawner := Format('__%s_Spawner', [t]); if Codespace.IndexOf(spawner) = -1 then begin // need to create Spawner and Returner threads CreateReturnerClump(t); CreateSpawnerClump(t); end; end; fSpawnedThreads.Clear; end; procedure TRXEProgram.OutputUnusedItemWarnings; var i : integer; de : TDataspaceEntry; begin for i := DataSpace.Count - 1 downto 0 do begin de := DataSpace.Items[i]; if not de.InUse then ReportProblem(0, GetCurrentFile(true), '', Format(sUnusedVar, [de.FullPathIdentifier]), false); end; end; procedure TRXEProgram.SetDefines(const Value: TStrings); begin fDefines.Assign(Value); end; procedure TRXEProgram.LoadSpecialFunctions; var SF : TSpecialFunction; begin // sizeof SF := TSpecialFunction.Create; fSpecialFunctions.Add(SF); SF.Func := 'sizeof('; SF.Execute := HandleSpecialFunctionSizeOf; // isconst SF := TSpecialFunction.Create; fSpecialFunctions.Add(SF); SF.Func := 'isconst('; SF.Execute := HandleSpecialFunctionIsConst; // valueof SF := TSpecialFunction.Create; fSpecialFunctions.Add(SF); SF.Func := 'valueof('; SF.Execute := HandleSpecialFunctionValueOf; // typeof SF := TSpecialFunction.Create; fSpecialFunctions.Add(SF); SF.Func := 'typeof('; SF.Execute := HandleSpecialFunctionTypeOf; end; procedure TRXEProgram.HandleSpecialFunctionSizeOf(Arg: TAsmArgument; const left, right, name: string); var de1 : TDataspaceEntry; dt : TDSType; begin // is name a constant value? Calc.SilentExpression := name; if Calc.ParserError then begin de1 := Dataspace.FindEntryByFullName(name); if Assigned(de1) then Arg.Value := left + IntToStr(de1.ElementSize(False)) + right else begin Arg.Value := left + '0' + right; ReportProblem(LineCounter, GetCurrentFile(true), '', Format(sInvalidVarArg, [name]), true); end end else begin dt := GetArgDataType(Calc.Value); Arg.Value := left + IntToStr(BytesPerType[dt]) + right; end; end; procedure TRXEProgram.HandleSpecialFunctionIsConst(Arg: TAsmArgument; const left, right, name: string); begin // is name a constant value (i.e., can it be evaluated)? Calc.SilentExpression := name; if Calc.ParserError then begin Arg.Value := left + '0' + right; end else begin Arg.Value := left + '1' + right; end; end; procedure TRXEProgram.HandleSpecialFunctionValueOf(Arg: TAsmArgument; const left, right, name: string); begin // is name a constant value? Calc.SilentExpression := name; if Calc.ParserError then begin Arg.Value := left + '0' + right; ReportProblem(LineCounter, GetCurrentFile(true), '', Format(sBadConstExpression, [name]), true); end else begin Arg.Value := left + NBCFloatToStr(Calc.Value) + right; end; end; procedure TRXEProgram.HandleSpecialFunctionTypeOf(Arg: TAsmArgument; const left, right, name: string); var de1 : TDataspaceEntry; dt : TDSType; begin // is name a constant value? Calc.SilentExpression := name; if Calc.ParserError then begin de1 := Dataspace.FindEntryByFullName(name); if Assigned(de1) then Arg.Value := left + IntToStr(Ord(de1.DataType)) + right else begin Arg.Value := left + '0' + right; ReportProblem(LineCounter, GetCurrentFile(true), '', Format(sInvalidVarArg, [name]), true); end end else begin dt := GetArgDataType(Calc.Value); Arg.Value := left + IntToStr(Ord(dt)) + right; end; end; procedure TRXEProgram.DoCompilerCheckType(AL: TAsmLine); var s1, s2, s3 : string; bCheckOkay : boolean; de : TDataspaceEntry; begin if fIgnoreLines then Exit; if AL.Args.Count = 2 then begin de := Dataspace.FindEntryByFullName(AL.Args[0].Value); if Assigned(de) then begin s1 := AL.Args[1].Value; s2 := de.TypeName; s3 := de.GetDataTypeAsString; bCheckOkay := (s1 = s2) or (s1 = s3); if not bCheckOkay then begin ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, Format(sCompCheckTypFailed, [AL.Args[0].Value, s1]), true); end; end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidCompCheckTyp, true); end else ReportProblem(AL.LineNum, GetCurrentFile(true), AL.AsString, sInvalidCompCheckTyp, true); end; procedure TRXEProgram.SetLineCounter(const Value: integer); begin fLineCounter := Value; end; function TRXEProgram.GetNXTInstruction(const idx: integer): NXTInstruction; begin Result := fNXTInstructions[idx]; end; procedure TRXEProgram.SetFirmwareVersion(const Value: word); begin fFirmwareVersion := Value; CodeSpace.FirmwareVersion := Value; if fFirmwareVersion > MAX_FW_VER1X then CompilerVersion := 6 else CompilerVersion := 5; InitializeInstructions; end; function TRXEProgram.IndexOfOpcode(op : TOpCode) : integer; var i : integer; begin Result := -1; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if fNXTInstructions[i].Encoding = op then begin Result := i; Break; end; end; end; procedure TRXEProgram.InitializeInstructions; var i : integer; begin if fFirmwareVersion > MAX_FW_VER1X then begin SetLength(fNXTInstructions, NXTInstructionsCount2x); for i := 0 to NXTInstructionsCount2x - 1 do begin fNXTInstructions[i] := NXTInstructions2x[i]; end; end else begin SetLength(fNXTInstructions, NXTInstructionsCount1x); for i := 0 to NXTInstructionsCount1x - 1 do begin fNXTInstructions[i] := NXTInstructions1x[i]; end; end; end; procedure TRXEProgram.CheckMainThread; var i : integer; X : TClump; begin i := Codespace.IndexOf(Codespace.InitialClumpName); if i = -1 then begin i := Codespace.IndexOf('t000'); if i > -1 then begin X := Codespace.Items[i]; X.Index := 0; end else ReportProblem(LineCounter, GetCurrentFile(true), '', sMainUndefined, false); end; end; procedure TRXEProgram.SaveToStrings(aStrings: TStrings); begin // write source code to aStrings aStrings.Clear; DataSpace.SaveToStrings(aStrings); Codespace.SaveToStrings(aStrings); end; procedure TRXEProgram.DoCompilerStatusChange(const Status: string; const bDone : boolean); begin if Assigned(fOnCompilerStatusChange) then fOnCompilerStatusChange(Self, Status, bDone); end; function TRXEProgram.ReplaceSpecialStringCharacters(const line: string): string; begin Result := line; if Pos('#', line) = 1 then Exit; // replace \\ with #06 Result := Replace(Result, '\\', #06); // replace \" with #08 Result := Replace(Result, '\"', #08); // replace \' with #07 Result := Replace(Result, '\''', #07); // replace \t with #03 Result := Replace(Result, '\t', #03); // replace \n with #04 Result := Replace(Result, '\n', #04); // replace \r with #05 Result := Replace(Result, '\r', #05); // replace " with ' Result := Replace(Result, '"', ''''); end; procedure TRXEProgram.HandlePreprocStatusChange(Sender: TObject; const StatusMsg: string); begin DoCompilerStatusChange(StatusMsg); end; { TAsmLine } procedure TAsmLine.AddArgs(sargs: string); var i : integer; SL : TStringList; Arg : TAsmArgument; tmp : string; begin // args is a comma-separated list of opcode arguments if Trim(sargs) = '' then Exit; SL := TStringList.Create; try // arguments can be delimited by single quotes, double quotes, or braces. // In any of those cases the entire contents of // the delimited item is a single argument if Pos('{', sargs) <> 0 then begin while sargs <> '' do begin // is the start of the next argument a delimiter? if IsDelimiter('{"''', sargs, 1) then begin tmp := Copy(sargs, 1, 1);//'{'; if tmp = '{' then begin System.Delete(sargs, 1, 1); // remove the delimiter i := Pos('}', sargs); if i = 0 then begin tmp := tmp + Copy(sargs, 1, MaxInt) + '}'; end else tmp := tmp + Copy(sargs, 1, i); System.Delete(sargs, 1, i); end else begin // the argument string starts with " or ' // let's just try adding the rest using CommaText. UGLY KLUDGE!!!! SL.CommaText := sargs; for i := 0 to SL.Count - 1 do begin Arg := Args.Add; Arg.Value := Trim(SL[i]); end; sargs := ''; break; end; end else begin i := Pos(',', sargs); if i = 0 then tmp := sargs else tmp := Copy(sargs, 1, i-1); System.Delete(sargs, 1, Length(tmp)); end; sargs := Trim(sargs); // remove comma between this arg and next if there is one if Pos(',', sargs) = 1 then begin System.Delete(sargs, 1, 1); sargs := Trim(sargs); end; Arg := Args.Add; Arg.Value := Trim(tmp); end; end else begin SL.CommaText := sargs; for i := 0 to SL.Count - 1 do begin Arg := Args.Add; Arg.Value := Trim(SL[i]); end; end; finally SL.Free; end; end; constructor TAsmLine.Create(ACollection: TCollection); begin inherited; fOpCode := OPS_INVALID; fInstrSize := -1; fMacroExpansion := False; fIsSpecial := False; fArgs := TAsmArguments.Create; end; function TAsmLine.InstructionSize: integer; begin if fInstrSize = -1 then FinalizeASMInstrSize; Result := fInstrSize; end; destructor TAsmLine.Destroy; begin FreeAndNil(fArgs); inherited; end; function TAsmLine.GetClumpCode: TClumpCode; begin Result := TClumpCode(Collection); end; procedure TAsmLine.SetArgs(const Value: TAsmArguments); begin fArgs.Assign(Value); end; function TAsmLine.CanBeShortOpEncoded: boolean; var rarg : ShortInt; w : word; tmpInt : integer; begin Result := False; fsop := LongOpToShortOp(Command); if fsop <> -1 then begin case Args.Count of 1 : begin { If the arg array has only 1 item and when the U16 value is converted to an I8 the two are equal then short ops are allowed and the relative arg output is the I8 value. } rarg := ShortInt(Args[0].DSID); w := Word(Args[0].DSID); Result := w = Word(rarg); end; 2 : begin { If there are two args in the array then take (arg 0 - arg 1), convert to I8, add arg 1, compare arg 0 to the result. If equal the short op is allowed. relative arg output is the I8 difference between arg 0 and arg 1. } tmpInt := (Args[0].DSID - Args[1].DSID); rarg := ShortInt(tmpInt); tmpInt := Args[1].DSID + rarg; Result := Args[0].DSID = tmpInt; end; else Result := False; end; end; end; procedure TAsmLine.FinalizeASMInstrSize; var idx : integer; NI : NXTInstruction; begin FinalizeArgs(False); fInstrSize := 0; fArity := 0; fCC := 0; if Command = OPS_INVALID then Exit; idx := CodeSpace.IndexOfOpcode(Command); if idx <> -1 then begin NI := CodeSpace.GetNXTInstruction(idx); fArity := NI.Arity; fCC := NI.CCType; if fArity = 6 then begin // opcodes with an arity of 6 have to be handled in a special manner fInstrSize := (2+Args.Count)*2; end else begin fInstrSize := (fArity + 1) * 2; if CanBeShortOpEncoded then Dec(fInstrSize, 2); end; end; end; procedure TAsmLine.HandleNameToDSID(const name: string; var aId: integer); var i : integer; begin // check whether the name matches an IO Map macro name i := IndexOfIOMapName(name); if i <> -1 then aId := IOMapFieldIDs[i].ID else ClumpCode.HandleNameToDSID(name, aId); end; procedure TAsmLine.SaveToCode(var Store: CodeArray); var i, len, start : integer; begin if Length(fCode) = 0 then FinalizeCode; len := Length(fCode); start := Length(Store); // copy data from our local array to the passed in array SetLength(Store, start + len); for i := 0 to len - 1 do begin Store[start+i] := fCode[i]; end; end; procedure TAsmLine.FinalizeCode; var i, argidx, isize : integer; b1, b2, cc : byte; rarg : ShortInt; bShort : boolean; arg0, arg1 : word; begin FinalizeArgs(True); SetLength(fCode, fInstrSize div 2); bShort := CanBeShortOpEncoded; argidx := 0; isize := (farity+1)*2; if bShort then dec(isize, 2); for i := 0 to Length(fCode) - 1 do begin if (i = 0) and bShort then begin // first word short //iiiifsss xxxxxxxx b2 := (Byte(isize shl 4) and INST_MASK) or SHOP_MASK or (Byte(fsop) and CC_MASK); if farity = 1 then begin b1 := Byte(Args[argidx].DSID); // low byte // eat the first argument inc(argidx); fCode[i] := Word((Word(b1) and $FF) + (Word(b2) shl 8)); end else begin arg0 := Word(Args[argidx].DSID); // eat the first argument inc(argidx); // peek at the second argument as well and calculate a temporary word // for the next slot in fCode arg1 := Word(Args[argidx].DSID); // the low byte in the first slot is a relative argument rarg := ShortInt(arg0 - arg1); fCode[i] := Word((Word(rarg) and $FF) + (Word(b2) shl 8)); end; end else if i = 0 then begin // first word long b1 := Byte(Ord(Command)); // low byte b2 := (Byte(isize shl 4) and INST_MASK); if fCC <> 0 then begin // first argument should be comparison code cc := Byte(Args[argidx].DSID); inc(argidx); b2 := b2 or (cc and CC_MASK); end; fCode[i] := Word((Word(b1) and $FF) + (Word(b2) shl 8)); end else begin // special handling for opcodes with arity = 6 if (fArity = 6) and (i = 1) then begin fCode[i] := Word(fInstrSize); end else begin // all other words (regardless of encoding type) fCode[i] := Word(Args[argidx].DSID); inc(argidx); end; end; end; end; procedure TAsmLine.FinalizeArgs(bResolveDSIDs : Boolean); var i, dsid, x, fsop : integer; Arg : TAsmArgument; argType : TAsmArgType; begin if Command = OPS_INVALID then Exit; if (Command = OP_FINCLUMP) and (Args.Count <> 2) then begin FixupFinClump; end else begin // commands which can be short op encoded need to have their arguments // finalized regardless of the bResolveDSIDs value fsop := LongOpToShortOp(Command); if (fsop <> -1) or bResolveDSIDs then begin for i := 0 to Args.Count - 1 do begin Arg := Args[i]; x := 0; Val(Arg.Value, dsid, x); // Val was interpreting variables such as 'xd' and 'xcb' as hexadecimal // numbers. By checking also whether Arg.Value is a valid identifier // we can correctly resolve the variable (2006-05-04 JCH) if (x <> 0) or IsValidIdent(Arg.Value) then begin // some opcodes have clump IDs as their arguments. Those need // special handling. if ((Command in [OP_SUBCALL, OPS_CALL, OPS_PRIORITY, OPS_PRIORITY_2]) and (i = 0)) or (Command in [OP_FINCLUMPIMMED, OPS_START, OPS_STOPCLUMP, OPS_START_2, OPS_STOPCLUMP_2]) then begin // try to lookup the clump # from the clump name dsid := CodeSpace.IndexOf(Arg.Value); end else begin // argument is not a valid integer (in string form) // could this argument be a label? argType := ExpectedArgType(FirmwareVersion, Self.Command, i); if argType = aatLabelID then begin if IsLabel(Arg.Value, dsid) then begin // id is start address of line containing label // we need to calculate positive or negative offset dsid := dsid - StartAddress; end else HandleNameToDSID(Arg.Value, dsid); end else HandleNameToDSID(Arg.Value, dsid); end; end; // if we have a dsid of -1 then try to resolve it one last time as // a constant expression if dsid = -1 then dsid := Integer(Trunc(Arg.Evaluate(CodeSpace.Calc))); Arg.fDSID := dsid; end; end; end; end; function TAsmLine.IsLabel(const name: string; var aID : integer): boolean; var i : integer; AL : TAsmLine; begin aID := 0; i := Clump.IndexOfLabel(name); Result := i <> -1; if Result then begin AL := Clump.AsmLineFromLabelIndex(i); aID := AL.StartAddress; end; end; function TAsmLine.GetAsString: string; begin if fIsSpecial then Result := fSpecialStr else begin Result := LineLabel; if Result <> '' then Result := Result + ':'; if Command <> OPS_INVALID then begin Result := Result + #9; Result := Result + CodeSpace.OpcodeToStr(Command) + ' ' + Args.AsString; end; end; end; function TAsmLine.GetClump: TClump; begin Result := ClumpCode.Clump; end; function TAsmLine.GetCodeSpace: TCodeSpace; begin Result := Clump.CodeSpace; end; procedure TAsmLine.FixupFinClump; var A1, A2 : TAsmArgument; begin Args.Clear; A1 := Args.Add; A2 := Args.Add; // automatically generate the correct arguments and DSID values if Clump.DownstreamCount > 0 then A1.fDSID := 0 else A1.fDSID := -1; A2.fDSID := Clump.DownstreamCount - 1; A1.Value := IntToStr(A1.DSID); A2.Value := IntToStr(A2.DSID); end; procedure TAsmLine.RemoveVariableReferences; var i : integer; begin for i := 0 to Args.Count - 1 do begin RemoveVariableReference(Args[i].Value, i); end; end; procedure TAsmLine.RemoveVariableReference(const arg: string; const idx : integer); var argType : TAsmArgType; begin argType := ExpectedArgType(FirmwareVersion, Command, idx); case argType of aatVariable, aatVarNoConst, aatVarOrNull, aatScalar, aatScalarNoConst, aatScalarOrNull, aatMutex, aatCluster, aatArray, aatString, aatStringNoConst : begin CodeSpace.Dataspace.RemoveReferenceIfPresent(arg); end; aatClumpID : begin CodeSpace.RemoveReferenceIfPresent(arg); end; end; end; function TAsmLine.GetPC: word; begin Result := Word(StartAddress); end; procedure TAsmLine.SetAsString(const Value: string); begin fIsSpecial := True; Command := OPS_INVALID; fSpecialStr := Value; end; function TAsmLine.FirmwareVersion: word; begin Result := CodeSpace.FirmwareVersion; end; function TAsmLine.GetOptimizable: boolean; var op : TOpCode; begin Result := False; op := Command; if (op in [OP_ADD..OP_ROTR]) or (op in [OP_GETIN, OP_GETOUT, OP_GETTICK]) or (op in [OP_INDEX..OP_BYTEARRTOSTR]) or ((FirmwareVersion > MAX_FW_VER1X) and (op in [OP_SQRT_2, OP_ABS_2, OPS_SIGN_2, OPS_FMTNUM_2, OPS_ACOS_2..OPS_ADDROF])) or ((FirmwareVersion <= MAX_FW_VER1X) and (op in [OPS_ABS, OPS_SIGN, OPS_FMTNUM, OPS_ACOS..OPS_POW])) then begin Result := True; end; end; { TAsmArguments } function TAsmArguments.Add: TAsmArgument; begin Result := TAsmArgument(inherited Add); end; procedure TAsmArguments.AssignTo(Dest: TPersistent); var i : integer; arg : TAsmArgument; begin if Dest is TAsmArguments then begin TAsmArguments(Dest).Clear; for i := 0 to Self.Count - 1 do begin arg := TAsmArguments(Dest).Add; arg.Value := Self[i].Value; end; end else inherited; end; constructor TAsmArguments.Create; begin inherited Create(TAsmArgument); end; function TAsmArguments.GetAsString: string; var i : integer; begin Result := ''; for i := 0 to Count - 1 do Result := Result + Items[i].Value + ', '; if Count > 0 then System.Delete(Result, Length(Result)-1, 2); end; function TAsmArguments.GetItem(Index: Integer): TAsmArgument; begin Result := TAsmArgument(inherited GetItem(Index)); end; function TAsmArguments.Insert(Index: Integer): TAsmArgument; begin Result := TAsmArgument(inherited Insert(Index)); end; procedure TAsmArguments.SetItem(Index: Integer; const Value: TAsmArgument); begin inherited SetItem(Index, Value); end; { TCodeSpace } function TCodeSpace.Add: TClump; begin Result := TClump(inherited Add); end; procedure TCodeSpace.BuildReferences; var i, j : integer; C : TClump; AL : TAsmLine; begin // build references for i := 0 to Count - 1 do begin C := Items[i]; if i = 0 then C.IncRefCount; // the first clump is required for j := 0 to C.ClumpCode.Count - 1 do begin AL := C.ClumpCode.Items[j]; if AL.Command in [OP_SUBCALL, OPS_CALL, OP_FINCLUMPIMMED, OPS_START, OPS_STOPCLUMP, OPS_PRIORITY, OPS_START_2, OPS_STOPCLUMP_2, OPS_PRIORITY_2] then begin // a clump name argument if AL.Args.Count > 0 then AddReferenceIfPresent(C, AL.Args[0].Value); end; end; // downstream clumps for j := 0 to C.DownstreamCount - 1 do begin AddReferenceIfPresent(C, C.DownstreamClumps[j]); end; end; end; procedure TCodeSpace.Compact; var bDone : boolean; i : integer; C : TClump; begin // remove any unused clumps from the codespace bDone := False; while not bDone do begin bDone := True; // never check clump 0 since it is the main clump for i := 1 to Count - 1 do begin C := Items[i]; if not C.InUse then begin // remove this clump from the codespace C.RemoveReferences; Delete(i); bDone := False; break; end; end; end; end; constructor TCodeSpace.Create(rp : TRXEProgram; ds : TDataspace); begin inherited Create(TClump); fRXEProg := rp; fDS := ds; fInitName := 'main'; fAddresses := TObjectList.Create; fFireCounts := TObjectList.Create; fMultiThreadedClumps := TStringList.Create; TStringList(fMultiThreadedClumps).CaseSensitive := True; TStringList(fMultiThreadedClumps).Duplicates := dupIgnore; FirmwareVersion := 128; end; destructor TCodeSpace.Destroy; begin FreeAndNil(fAddresses); FreeAndNil(fFireCounts); FreeAndNil(fMultiThreadedClumps); inherited; end; procedure TCodeSpace.FinalizeDependencies; var i, j, idx : integer; X : TClump; cName : string; begin // if there is a clump called main make it the first clump i := IndexOf(InitialClumpName); if i <> -1 then begin X := Items[i]; X.Index := 0; end; // update dependencies for i := 0 to Count - 1 do begin X := Items[i]; for j := 0 to X.UpstreamCount - 1 do begin // add myself to each (thread in my upstream list)'s downstream list cName := X.UpstreamClumps[j]; idx := IndexOf(cName); if idx <> -1 then Items[idx].AddDependant(X.Name); end; for j := 0 to X.DownstreamCount - 1 do begin // add myself to each (thread in my downstream list)'s upstream list cName := X.DownstreamClumps[j]; idx := IndexOf(cName); if idx <> -1 then Items[idx].AddAncestor(X.Name); end; end; end; function TCodeSpace.GetAddress(aIndex: Integer): Word; begin if fAddresses.Count <> Count then FinalizeAddressesAndFireCounts; Result := Word(TIntegerObject(fAddresses[aIndex]).Value); end; function TCodeSpace.GetCaseSensitive: boolean; begin Result := fCaseSensitive; end; function TCodeSpace.GetFireCount(aIndex: integer): Byte; begin if fFireCounts.Count <> Count then FinalizeAddressesAndFireCounts; Result := Byte(TIntegerObject(fFireCounts[aIndex]).Value); end; function TCodeSpace.GetItem(aIndex: Integer): TClump; begin Result := TClump(inherited GetItem(aIndex)); end; procedure TCodeSpace.HandleNameToDSID(const aName: string; var aId: integer); begin aId := 0; if Assigned(fOnNameToDSID) then fOnNameToDSID(aName, aId); end; function TCodeSpace.IndexOf(const aName: string): integer; var i : integer; begin Result := -1; for i := 0 to Count - 1 do begin if Items[i].Name = aName then begin Result := i; Break; end; end; end; procedure TCodeSpace.AddReferenceIfPresent(aClump : TClump; const aName: string); var i : integer; C : TClump; begin i := IndexOf(aName); if i <> -1 then begin C := Items[i]; C.IncRefCount; if C.IsSubroutine then C.AddCaller(aClump.Name); end; end; procedure TCodeSpace.RemoveReferenceIfPresent(const aName: string); var i : integer; begin i := IndexOf(aName); if i <> -1 then Items[i].DecRefCount; end; procedure TCodeSpace.SaveToCodeData(aCD: TClumpData; aCode : TCodeSpaceAry); var pX : ^ClumpRecord; C : TClump; i : integer; begin if (fAddresses.Count <> Count) or (fFireCounts.Count <> Count) then FinalizeAddressesAndFireCounts; SetLength(aCD.ClumpDeps, 0); // start with an empty array SetLength(aCode.Code, 0); SetLength(aCD.CRecs, Count); for i := 0 to Count - 1 do begin pX := @(aCD.CRecs[i]); C := Items[i]; pX^.FireCount := FireCounts[i]; pX^.DependentCount := C.DownstreamCount; pX^.CodeStart := StartingAddresses[i]; C.SaveDependencies(aCD.ClumpDeps); C.SaveToCode(aCode.Code); end; end; procedure TCodeSpace.SetCaseSensitive(const Value: boolean); var i : integer; begin fCaseSensitive := Value; for i := 0 to Count - 1 do begin Items[i].fLabelMap.CaseSensitive := Value; Items[i].fUpstream.CaseSensitive := Value; Items[i].fDownstream.CaseSensitive := Value; end; end; procedure TCodeSpace.SetItem(aIndex: Integer; const aValue: TClump); begin inherited SetItem(aIndex, aValue); end; procedure TCodeSpace.FinalizeAddressesAndFireCounts; var i : integer; X : TClump; addr : integer; begin // calculate addresses for all the clumps addr := 0; fAddresses.Clear; fFireCounts.Clear; for i := 0 to Count - 1 do begin X := Items[i]; fAddresses.Add(TIntegerObject.Create(addr)); inc(addr, X.DataSize); fFireCounts.Add(TIntegerObject.Create(X.FireCount)); end; end; procedure TCodeSpace.Optimize(const level : Integer); var i : integer; C : TClump; begin // level 2 optimizations are buggy so don't do them. // have each clump optimize itself for i := 0 to Count - 1 do begin C := Items[i]; // skip clumps starting with '__' under the assumption that // they are API-level (hand optimized) clumps if Pos('__', C.Name) = 1 then Continue; RXEProgram.DoCompilerStatusChange(Format(sNBCOptClump, [C.Name])); C.Optimize(level); end; end; procedure TCodeSpace.OptimizeMutexes; var i : integer; begin // have each clump optimize itself for i := 0 to Count - 1 do Items[i].OptimizeMutexes; end; procedure TCodeSpace.SaveToSymbolTable(aStrings: TStrings); var i, j : integer; C : TClump; AL : TAsmLine; begin aStrings.Add('#SOURCES'); aStrings.Add('Clump'#9'Line'#9'PC'#9'Source'); for i := 0 to Count - 1 do begin C := Items[i]; for j := 0 to C.ClumpCode.Count - 1 do begin AL := C.ClumpCode.Items[j]; if not AL.IsPartOfMacroExpansion and ((AL.Command <> OPS_INVALID) or (AL.IsSpecial)) then aStrings.Add(Format('%d'#9'%d'#9'%d'#9'%s', [i, AL.LineNum, AL.ProgramCounter, AL.AsString])); end; end; aStrings.Add('#CLUMPS'); aStrings.Add('Clump'#9'Name'#9'Offset'#9'File'); for i := 0 to Count - 1 do begin C := Items[i]; aStrings.Add(Format('%d'#9'%s'#9'%d'#9'%s', [i, C.Name, C.StartAddress, C.Filename])); end; end; procedure TCodeSpace.MultiThread(const aName: string); begin fMultiThreadedClumps.Add(aName); end; function TCodeSpace.GetNXTInstruction(const idx: integer): NXTInstruction; begin Result := fNXTInstructions[idx]; end; procedure TCodeSpace.InitializeInstructions; var i : integer; begin if fFirmwareVersion > MAX_FW_VER1X then begin SetLength(fNXTInstructions, NXTInstructionsCount2x); for i := 0 to NXTInstructionsCount2x - 1 do begin fNXTInstructions[i] := NXTInstructions2x[i]; end; end else begin SetLength(fNXTInstructions, NXTInstructionsCount1x); for i := 0 to NXTInstructionsCount1x - 1 do begin fNXTInstructions[i] := NXTInstructions1x[i]; end; end; end; function TCodeSpace.IndexOfOpcode(op: TOpCode): integer; var i : integer; begin Result := -1; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if fNXTInstructions[i].Encoding = op then begin Result := i; Break; end; end; end; procedure TCodeSpace.SetFirmwareVersion(const Value: word); begin fFirmwareVersion := Value; InitializeInstructions; end; function TCodeSpace.OpcodeToStr(const op: TOpCode): string; var i : integer; begin if op <> OPS_INVALID then Result := Format('bad op (%d)', [Ord(op)]) else Result := ''; for i := Low(fNXTInstructions) to High(fNXTInstructions) do begin if fNXTInstructions[i].Encoding = op then begin Result := fNXTInstructions[i].Name; break; end; end; end; procedure TCodeSpace.RemoveUnusedLabels; var i : integer; begin // now remove any labels that are not targets of a branch/jump for i := 0 to Count - 1 do Items[i].RemoveUnusedLabels; end; procedure TCodeSpace.SaveToStrings(aStrings: TStrings); var i, j : integer; C : TClump; AL : TAsmLine; tmpStr : string; begin aStrings.Add(';------- code -------'); for i := 0 to Count - 1 do begin C := Items[i]; if C.IsSubroutine then aStrings.Add('subroutine ' + C.Name) else aStrings.Add('thread ' + C.Name); for j := 0 to C.ClumpCode.Count - 1 do begin AL := C.ClumpCode.Items[j]; // skip blank lines tmpStr := AL.AsString; if Trim(tmpStr) <> '' then aStrings.Add(tmpStr); end; if C.IsSubroutine then aStrings.Add('ends') else aStrings.Add('endt'); aStrings.Add(';------------------------'); end; end; { TClump } procedure TClump.AddClumpDependencies(const opcode, args: string); var tmpSL : TStringList; i : integer; begin // clumps with no downstream dependencies finalize -1, -1 // clumps with downstream dependencies finalize and conditionally schedule // all their downstream dependants with 0..N where N is the number of // dependants - 1. tmpSL := TStringList.Create; try tmpSL.CommaText := args; if opcode = CodeSpace.OpcodeToStr(OPS_REQUIRES) then begin // upstream clumps fUpstream.AddStrings(tmpSL); end else if opcode = CodeSpace.OpcodeToStr(OPS_USES) then begin // downstream clumps // fDownstream.AddStrings(tmpSL); // this seems to do the same as the for loop does for i := 0 to tmpSL.Count - 1 do AddDependant(tmpSL[i]); end; finally tmpSL.Free; end; end; constructor TClump.Create(ACollection: TCollection); begin inherited; fDatasize := -1; fIsSub := False; fRefCount := 0; fLabelMap := TStringList.Create; fLabelMap.CaseSensitive := CodeSpace.CaseSensitive; fLabelMap.Sorted := True; fUpstream := TStringList.Create; fUpstream.CaseSensitive := CodeSpace.CaseSensitive; fUpstream.Sorted := False; // do not sort dependencies fUpstream.Duplicates := dupIgnore; fDownstream := TStringList.Create; fDownstream.CaseSensitive := CodeSpace.CaseSensitive; fDownstream.Sorted := False; // do not sort dependencies fDownstream.Duplicates := dupIgnore; fClumpCode := TClumpCode.Create(Self); fClumpCode.OnNameToDSID := HandleNameToDSID; fCallers := TStringList.Create; fCallers.CaseSensitive := CodeSpace.CaseSensitive; fCallers.Sorted := True; fCallers.Duplicates := dupIgnore; end; destructor TClump.Destroy; begin FreeAndNil(fLabelMap); FreeAndNil(fUpstream); FreeAndNil(fDownstream); FreeAndNil(fClumpCode); FreeAndNil(fCallers); inherited; end; function TClump.GetUpstream(aIndex: integer): string; begin Result := fUpstream[aIndex]; end; function TClump.GetCodeSpace: TCodeSpace; begin Result := TCodeSpace(Collection); end; function TClump.GetDataSize: Word; begin // calculate the datasize from the code contained in this clump if fDatasize = -1 then FinalizeClump; Result := Word(fDatasize); end; function TClump.GetStartAddress: Word; begin // the starting address of a clump is determined by the codespace Result := CodeSpace.StartingAddresses[Self.Index]; end; function TClump.GetDownstream(aIndex: integer): string; begin Result := fDownstream[aIndex]; end; function TClump.GetDownCount: Byte; begin Result := Byte(fDownstream.Count); end; function TClump.GetUpCount: integer; begin Result := fUpstream.Count; end; procedure TClump.FinalizeClump; var i : integer; AL : TAsmLine; begin fDataSize := 0; // no code to start with ClumpCode.FixupFinalization; for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode[i]; AL.fStartAddress := fDataSize; inc(fDataSize, AL.InstructionSize div 2); end; // save code for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode[i]; AL.SaveToCode(fCode); end; end; procedure TClump.SaveToCode(var Store: CodeArray); var i, len, start : integer; begin if Length(fCode) = 0 then FinalizeClump; len := Length(fCode); start := Length(Store); // copy data from our local array to the passed in array SetLength(Store, start + len); for i := 0 to len - 1 do begin Store[start+i] := fCode[i]; end; end; procedure TClump.SaveDependencies(var Store: ClumpDepArray); var len, i : integer; begin len := Length(Store); SetLength(Store, len+DownstreamCount); for i := 0 to DownstreamCount - 1 do begin Store[len+i] := Byte(CodeSpace.IndexOf(DownstreamClumps[i])); end; end; procedure TClump.HandleNameToDSID(const aname: string; var aId: integer); begin CodeSpace.HandleNameToDSID(aname, aId); end; function TClump.GetFireCount: Word; var i, j : integer; cnt : Word; C : TClump; begin if Self.Index = 0 then Result := 0 else begin Result := 1; // how many times am I listed in other clumps downstream clumps list? cnt := 0; for i := 0 to CodeSpace.Count - 1 do begin C := CodeSpace[i]; if C.Index = Self.Index then Continue; for j := 0 to C.DownstreamCount - 1 do begin if C.DownstreamClumps[j] = Self.Name then begin inc(cnt); break; end; end; end; if cnt > 0 then Result := cnt; end; end; procedure TClump.AddDependant(const clumpName: string); begin if fDownstream.IndexOf(clumpName) = -1 then fDownstream.Add(clumpName); end; procedure TClump.AddAncestor(const clumpName: string); begin if fUpstream.IndexOf(clumpName) = -1 then fUpstream.Add(clumpName); end; procedure TClump.AddCaller(const clumpName: string); begin fCallers.Add(clumpName); // duplicates are ignored end; function TClump.GetCaseSensitive: boolean; begin Result := CodeSpace.CaseSensitive; end; procedure TClump.AddLabel(const lbl: string; Line : TAsmLine); begin fLabelMap.AddObject(lbl, Line); end; function TClump.IndexOfLabel(const lbl: string): integer; begin Result := fLabelMap.IndexOf(lbl); end; function TClump.AsmLineFromLabelIndex(const idx: integer): TAsmLine; begin Result := TAsmLine(fLabelMap.Objects[idx]); end; function TClump.GetInUse: boolean; begin Result := fRefCount > 0; end; procedure TClump.RemoveReferences; var i : integer; begin // remove references in code for i := 0 to ClumpCode.Count - 1 do begin ClumpCode.Items[i].RemoveVariableReferences; end; // remove downstream dependency references for i := 0 to DownstreamCount - 1 do begin CodeSpace.RemoveReferenceIfPresent(DownstreamClumps[i]); end; // if this clump is a subroutine remove // the return address variable as well if Self.IsSubroutine then CodeSpace.Dataspace.RemoveReferenceIfPresent(Format('__%s_return', [Name])); end; procedure TClump.DecRefCount; begin dec(fRefCount); end; procedure TClump.IncRefCount; begin inc(fRefCount); end; function IsStackOrReg(const str : string) : boolean; begin Result := (Pos('__D0', str) = 1) or (Pos('__signed_stack_', str) = 1) or (Pos('__unsigned_stack_', str) = 1) or (Pos('__float_stack_', str) = 1) or (Pos('__DU0', str) = 1) or (Pos('__DF0', str) = 1); end; procedure TClump.RemoveOrNOPLine(AL, ALNext : TAsmLine; const idx : integer); begin if AL.LineLabel = '' then begin ClumpCode.Delete(idx); end else if Assigned(ALNext) and (ALNext.LineLabel = '') then begin ALNext.LineLabel := AL.LineLabel; ClumpCode.Delete(idx); end else begin AL.Command := OPS_INVALID; AL.Args.Clear; end; end; function GetTypeHint(DSpace : TDataspace; const aLine: TASMLine; const idx : integer; bEnhanced : boolean): TDSType; var DE : TDataspaceEntry; begin Result := dsVoid; case aLine.Command of OP_ARRINIT : begin if (idx = 1) and not bEnhanced then begin // the first argument is always an array. We need the base type DE := DSpace.FindEntryByFullName(aLine.Args[0].Value); if Assigned(DE) then Result := DE.BaseDataType; end; end; else Result := dsVoid; end; end; function CreateConstantVar(DSpace : TDataspace; val : Extended; bIncCount : boolean; aTypeHint : TDSType) : string; var datatype : TDSType; DE : TDataspaceEntry; // iVal : Int64; sVal : Single; begin if aTypeHint <> dsVoid then datatype := aTypeHint else datatype := GetArgDataType(val); // iVal := Trunc(val*1000000); // scale by 6 decimal places // Result := GenerateTOCName(Byte(Ord(datatype)), Int64(abs(iVal)), '%1:d'); Result := Replace(NBCFloatToStr(abs(val)), '.', 'P'); if datatype = dsFloat then Result := 'f' + Result; // distinguish between float constants and integer constants if val < 0 then Result := '__constValNeg' + Result else Result := '__constVal' + Result; // is this temporary already in the dataspace? DE := DSpace.FindEntryByFullName(Result); if not Assigned(DE) then begin // we need to add it DE := DSpace.Add; DE.Identifier := Result; DE.DataType := datatype; // DE.DefaultValue := ValueAsCardinal(val, datatype); if datatype = dsFloat then begin sVal := val; DE.DefaultValue := SingleToCardinal(sVal); end else DE.DefaultValue := Cardinal(Trunc(val)); end; if Assigned(DE) and bIncCount then DE.IncRefCount; end; procedure ConvertToSetOrMov(DS : TDataspace; var AL : TAsmLine; iVal : Double; var arg1 : string); var tmp : string; DE : TDataspaceEntry; begin if (iVal < Low(SmallInt)) or (iVal > High(Word)) or (Trunc(iVal) <> iVal) then begin // we need to use mov AL.Command := OP_MOV; // the type of the output variable determines whether we should truncate this value or not tmp := AL.Args[0].Value; DE := DS.FindEntryByFullName(tmp); if Assigned(DE) then begin if DE.DataType <> dsFloat then iVal := Trunc(iVal); end; arg1 := CreateConstantVar(DS, iVal, True); end else begin // no need to use mov - we can use set instead AL.Command := OP_SET; arg1 := IntToStr(Trunc(iVal)); end; end; function GetArgValue(EP : TNBCExpParser; arg1 : string; var val : Double) : boolean; var bIsNeg : boolean; bIsFloat : boolean; begin if Pos('__constVal', arg1) = 1 then begin Result := True; // remove __constVal or __constValNeg bIsNeg := Pos('__constValNeg', arg1) = 1; if bIsNeg then System.Delete(arg1, 1, 13) else System.Delete(arg1, 1, 10); bIsFloat := (Pos('f', arg1) > 0) or (Pos('P', arg1) > 0); if bIsFloat then begin arg1 := Replace(Replace(arg1, 'f', ''), 'P', '.'); val := NBCStrToFloatDef(arg1, 0); end else val := StrToIntDef(arg1, 0); if bIsNeg then val := val * -1; end else begin EP.SilentExpression := arg1; Result := not EP.ParserError; if Result then val := EP.Value else val := 0; end; end; function CountArgUsage(AL : TAsmLine; const arg : string) : integer; var i : integer; begin Result := 0; for i := 0 to AL.Args.Count - 1 do begin if AL.Args[i].Value = arg then inc(Result); end; end; procedure TClump.Optimize(const level : Integer); var i, offset : integer; iVal : Double; AL, ALNext, tmpAL : TAsmLine; arg1, arg2, arg3, tmp : string; bDone, bArg1Numeric, bArg2Numeric, bCanOptimize : boolean; Arg1Val, Arg2Val : Double; DE : TDataspaceEntry; bEnhanced : boolean; function CheckReferenceCount : boolean; var cnt : integer; begin Result := True; arg1 := AL.Args[0].Value; // check the output (dest) argument cnt := CountArgUsage(AL, arg1); DE := CodeSpace.Dataspace.FindEntryByFullName(arg1); if Assigned(DE) then begin // simple case - refcount is less than this line's usage if DE.RefCount <= cnt then begin // setting a variable to a value and never referencing it again // set|mov X, whatever // nop (or delete line) // remove the references AL.RemoveVariableReferences; RemoveOrNOPLine(AL, nil, i); Result := False; end; end; end; begin bEnhanced := CodeSpace.RXEProgram.EnhancedFirmware; bDone := False; while not bDone do begin bDone := True; // assume we are done for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode.Items[i]; // any line of this form: op reg/stack, rest // followed by this line mov anything, reg/stack // where reg/stack1 == reg/stack2 // can be replaced by one line of this form: // op anything, rest // nop if AL.Optimizable then begin // first check reference count of output variable if not CheckReferenceCount then begin bDone := False; Break; end; arg1 := AL.Args[0].Value; if IsStackOrReg(arg1) then begin // maybe we can do an optimization // find the next line (which may not be i+1) that is not (NOP or labeled) offset := 1; while (i < ClumpCode.Count - offset) do begin tmpAL := ClumpCode.Items[i+offset]; if (tmpAL.Command <> OPS_INVALID) or (tmpAL.LineLabel <> '') then Break; inc(offset); end; // every line between Items[i] and Items[i+offset] are NOP lines without labels. if i < (ClumpCode.Count - offset) then begin ALNext := ClumpCode.Items[i+offset]; // now check other cases // bricxcc-Bugs-1669679 - make sure the next line // cannot be jumped to from elsewhere. If it does then the // "previous" line may actually be skipped so we cannot // do any optimization if (ALNext.LineLabel = '') and (ALNext.Command = OP_MOV) and (ALNext.Args[1].Value = arg1) then begin bCanOptimize := True; if not bEnhanced then begin if AL.Command in [OP_GETTICK, OP_NOT, OP_ARRSIZE, OP_GETOUT, OP_CMP, OP_WAIT] then begin DE := CodeSpace.Dataspace.FindEntryByFullName(ALNext.Args[0].Value); if Assigned(DE) then bCanOptimize := (DE.DataType <> dsFloat) else bCanOptimize := False; end else if AL.Command = OP_STRINGTONUM then begin DE := CodeSpace.Dataspace.FindEntryByFullName(ALNext.Args[1].Value); if Assigned(DE) then bCanOptimize := (DE.DataType <> dsFloat) else bCanOptimize := False; end; end else if AL.Command = OP_SET then begin // need to also check the type of the next line's output arg DE := CodeSpace.Dataspace.FindEntryByFullName(ALNext.Args[0].Value); if Assigned(DE) then bCanOptimize := DE.DataType <> dsFloat else bCanOptimize := False; end; if bCanOptimize then begin AL.RemoveVariableReference(arg1, 0); AL.Args[0].Value := ALNext.Args[0].Value; // switch output arg (no ref count changes) ALNext.RemoveVariableReference(arg1, 1); ALNext.Command := OPS_INVALID; // no-op next line ALNext.Args.Clear; bDone := False; Break; end; end; end; end; end; case AL.Command of OP_SET, OP_MOV : begin // this is a set or mov line // first check reference count of output variable if not CheckReferenceCount then begin bDone := False; Break; end; if AL.Args[0].Value = AL.Args[1].Value then begin // set|mov X, X <-- replace with nop or delete AL.RemoveVariableReferences; RemoveOrNOPLine(AL, nil, i); bDone := False; Break; end; arg1 := AL.Args[0].Value; // find the next line (which may not be i+1) that is not (NOP or labeled) offset := 1; while (i < ClumpCode.Count - offset) do begin tmpAL := ClumpCode.Items[i+offset]; if (tmpAL.Command <> OPS_INVALID) or (tmpAL.LineLabel <> '') then begin // is it safe to ignore this line? If it is a set or a mov for // different variables then yes (at higher optimization levels) ... // (this is not always safe AKA buggy) if not ((tmpAL.Command in [OP_SET, OP_MOV]) and (tmpAL.LineLabel = '') and (arg1 <> tmpAL.Args[0].Value) and (arg1 <> tmpAL.Args[1].Value) and (level >= 4)) then Break; end; inc(offset); end; // every line between Items[i] and Items[i+offset] are NOP lines without labels. // OR lines that have nothing whatsoever to do with the output variable in // Items[i] if i < (ClumpCode.Count - offset) then begin ALNext := ClumpCode.Items[i+offset]; // now check other cases // bricxcc-Bugs-1669679 - make sure the next line // cannot be jumped to from elsewhere. If it does then the // "previous" line may actually be skipped so we cannot // do any optimization if ALNext.LineLabel = '' then begin case ALNext.Command of OP_SET, OP_MOV : begin if ALNext.Args[0].Value = AL.Args[0].Value then begin // set|mov X, whatever // set|mov X, whatever <-- replace these two lines with // nop (or delete line) // set|mov X, whatever AL.RemoveVariableReferences; RemoveOrNOPLine(AL, ALNext, i); bDone := False; Break; end else begin arg1 := AL.Args[0].Value; arg2 := ALNext.Args[1].Value; if (arg1 = arg2) then begin // set|mov __D0,whatever (__D0 or __stack_nnn) // mov X,__D0 <-- replace these two lines with // nop (if arg1 and arg2 are stack or register variables) // mov X,whatever if AL.Command = OP_SET then tmp := CreateConstantVar(CodeSpace.Dataspace, StrToIntDef(AL.Args[1].Value, 0), True) else begin tmp := AL.Args[1].Value; CodeSpace.Dataspace.FindEntryAndAddReference(tmp); end; ALNext.Command := OP_MOV; ALNext.Args[1].Value := tmp; { ALNext.Command := AL.Command; ALNext.Args[1].Value := AL.Args[1].Value; } ALNext.RemoveVariableReference(arg2, 1); if IsStackOrReg(arg1) then begin // remove second reference to _D0 AL.RemoveVariableReferences; // AL.RemoveVariableReference(arg1, 0); RemoveOrNOPLine(AL, ALNext, i); end; bDone := False; Break; end; end; end; OPS_WAITV, OPS_WAITV_2 : begin // these two opcodes are only present if EnhancedFirmware is true arg1 := AL.Args[0].Value; arg2 := ALNext.Args[0].Value; if (arg1 = arg2) then begin // set|mov __D0,whatever (__D0 or __stack_nnn) // waitv __D0 <-- replace these two lines with // nop (if arg1 and arg2 are stack or register variables) // waitv|wait whatever ALNext.Args[0].Value := AL.Args[1].Value; ALNext.RemoveVariableReference(arg2, 0); if AL.Command = OP_SET then begin if CodeSpace.FirmwareVersion > MAX_FW_VER1X then ALNext.Command := OPS_WAITI_2 else ALNext.Command := OP_WAIT; end; CodeSpace.Dataspace.FindEntryAndAddReference(ALNext.Args[0].Value); if IsStackOrReg(arg1) then begin // remove second reference to _D0 AL.RemoveVariableReferences; // AL.RemoveVariableReference(arg1, 0); RemoveOrNOPLine(AL, ALNext, i); end; bDone := False; Break; end; end; OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_AND, OP_OR, OP_XOR, OP_LSL, OP_LSR, OP_ASL, OP_ASR : begin arg1 := AL.Args[0].Value; arg2 := ALNext.Args[2].Value; arg3 := ALNext.Args[1].Value; if (arg1 = arg2) or (arg1 = arg3) then begin // set|mov __D0,X // arithop A, B, __D0 <-- replace these two lines with // nop // arithop A, B, X if AL.Command = OP_SET then tmp := CreateConstantVar(CodeSpace.Dataspace, StrToIntDef(AL.Args[1].Value, 0), True) else begin // increment the reference count of this variable tmp := AL.Args[1].Value; CodeSpace.Dataspace.FindEntryAndAddReference(tmp); end; if (arg1 = arg2) then begin ALNext.Args[2].Value := tmp; ALNext.RemoveVariableReference(arg2, 2); end else begin // arg1=arg3 (aka ALNext.Args[1].Value) ALNext.Args[1].Value := tmp; ALNext.RemoveVariableReference(arg3, 1); end; if IsStackOrReg(arg1) then begin // remove second reference to _D0 AL.RemoveVariableReferences; // AL.RemoveVariableReference(arg1, 0); RemoveOrNOPLine(AL, ALNext, i); end; bDone := False; Break; end; end; OP_NEG, OP_NOT : begin arg1 := AL.Args[0].Value; arg2 := ALNext.Args[1].Value; if arg1 = arg2 then begin // set|mov __D0,X // neg|not A, __D0 <-- replace these two lines with // nop // neg|not A, X if AL.Command = OP_SET then tmp := CreateConstantVar(CodeSpace.Dataspace, StrToIntDef(AL.Args[1].Value, 0), True) else begin tmp := AL.Args[1].Value; CodeSpace.Dataspace.FindEntryAndAddReference(tmp); end; ALNext.Args[1].Value := tmp; ALNext.RemoveVariableReference(arg2, 1); if IsStackOrReg(arg1) then begin // remove second reference to _D0 AL.RemoveVariableReference(arg1, 0); RemoveOrNOPLine(AL, ALNext, i); end; bDone := False; Break; end; end; else // nothing end; end; end; end; OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_AND, OP_OR, OP_XOR, OP_ASL, OP_ASR : begin // first check reference count of output variable if not CheckReferenceCount then begin bDone := False; Break; end; if level >= 3 then begin // process argument 1 // is it a constant variable (i.e., aname == _constVal...) arg1 := AL.Args[1].Value; Arg1Val := 0; bArg1Numeric := GetArgValue(CodeSpace.Calc, arg1, Arg1Val); // now process argument 2 arg2 := AL.Args[2].Value; Arg2Val := 0; bArg2Numeric := GetArgValue(CodeSpace.Calc, arg2, Arg2Val); // ready to process if bArg1Numeric and bArg2Numeric then begin if (AL.Command in [OP_ADD, OP_SUB, OP_MUL, OP_DIV]) or ((Trunc(Arg1Val) = Arg1Val) and (Trunc(Arg2Val) = Arg2Val)) then begin // both arguments are numeric AL.RemoveVariableReference(arg1, 1); AL.RemoveVariableReference(arg2, 2); case AL.Command of OP_ADD : iVal := Arg1Val + Arg2Val; OP_SUB : iVal := Arg1Val - Arg2Val; OP_MUL : iVal := Arg1Val * Arg2Val; OP_DIV : iVal := Arg1Val / Arg2Val; OP_MOD : iVal := Trunc(Arg1Val) mod Trunc(Arg2Val); OP_AND : iVal := integer(Trunc(Arg1Val) and Trunc(Arg2Val)); OP_OR : iVal := integer(Trunc(Arg1Val) or Trunc(Arg2Val)); OP_XOR : iVal := integer(Trunc(Arg1Val) xor Trunc(Arg2Val)); OP_ASL : iVal := integer(Trunc(Arg1Val) shl Trunc(Arg2Val)); OP_ASR : iVal := integer(Trunc(Arg1Val) shr Trunc(Arg2Val)); else iVal := 0; end; // arithop X, N1, N2 <-- replace this line with // set|mov X, N (where N = N1 arithop N2) ConvertToSetOrMov(CodeSpace.Dataspace, AL, iVal, arg1); AL.Args.Delete(2); AL.Args[1].Value := arg1; bDone := False; Break; end; end; end; end; OP_NEG, OP_NOT : begin // first check reference count of output variable if not CheckReferenceCount then begin bDone := False; Break; end; if level >= 3 then begin // process argument 1 // is it a constant variable (i.e., aname == _constVal...) arg1 := AL.Args[1].Value; bArg1Numeric := GetArgValue(CodeSpace.Calc, arg1, Arg1Val); // ready to process if bArg1Numeric and ((AL.Command = OP_NEG) or (Trunc(Arg1Val) = Arg1Val)) then begin // the argument is numeric AL.RemoveVariableReference(arg1, 1); case AL.Command of OP_NEG : iVal := Arg1Val * -1; OP_NOT : iVal := integer(not boolean(Trunc(Arg1Val))); else iVal := 0; end; // neg|not X, N1 <-- replace this line with // set|mov X, N (where N = neg|not N1 ) ConvertToSetOrMov(CodeSpace.Dataspace, AL, iVal, arg1); AL.Args[1].Value := arg1; bDone := False; Break; end; end; end; OP_JMP, OP_BRCMP, OP_BRTST : begin // if this line is a some kind of jump statement and the destination is the very next line that // is not a no-op then it can be optimized. if AL.Command = OP_JMP then begin arg1 := AL.Args[0].Value; // first argument is label end else // if AL.Command in [OP_BRCMP, OP_BRTST] then begin arg1 := AL.Args[1].Value; // second argument is label end; // find the next line (which may not be i+1) that is not (NOP or labeled) offset := 1; while (i < ClumpCode.Count - offset) do begin tmpAL := ClumpCode.Items[i+offset]; if (tmpAL.Command <> OPS_INVALID) or (tmpAL.LineLabel <> '') then Break; inc(offset); end; // every line between Items[i] and Items[i+offset] are NOP lines without labels. if i < (ClumpCode.Count - offset) then begin ALNext := ClumpCode.Items[i+offset]; // if the next line has a label == to arg1 then we can delete the current line if ALNext.LineLabel = arg1 then begin AL.RemoveVariableReferences; RemoveOrNOPLine(AL, ALNext, i); RemoveUnusedLabels; bDone := False; Break; end; end; end; else // nothing end; end; end; end; procedure TClump.OptimizeMutexes; var i : integer; AL : TAsmLine; de : TDataspaceEntry; function AllCallersHaveZeroAncestors : boolean; var j, idx : integer; C : TClump; begin Result := True; for j := 0 to CallerCount - 1 do begin idx := CodeSpace.IndexOf(fCallers[j]); if idx <> -1 then begin C := CodeSpace[idx]; if C.UpstreamCount > 0 then begin Result := False; Break; end; end; end; end; begin if (UpstreamCount = 0) and ((CallerCount <= 1) or AllCallersHaveZeroAncestors) and (not IsMultithreaded) then for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode.Items[i]; if AL.Command in [OP_ACQUIRE, OP_RELEASE] then begin de := self.CodeSpace.Dataspace.FindEntryByName(Al.Args[0].Value); if Assigned(de) and (de.DataType = dsMutex) and (de.ThreadCount <= 1) then begin AL.RemoveVariableReferences; AL.Command := OPS_INVALID; // no-op AL.Args.Clear; end; end; end; end; function TClump.GetCallerCount: Byte; begin Result := Byte(fCallers.Count); end; function TClump.GetIsMultithreaded: boolean; begin Result := Codespace.fMultiThreadedClumps.IndexOf(Self.Name) <> -1; end; procedure TClump.RemoveUnusedLabels; var i : integer; AL : TAsmLine; SL : TStringList; begin // first gather a list of jump targets in this clump SL := TStringList.Create; try SL.Sorted := True; SL.Duplicates := dupIgnore; for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode.Items[i]; if AL.Command = OP_JMP then begin SL.Add(AL.Args[0].Value); // first argument is label end else if AL.Command in [OP_BRCMP, OP_BRTST] then begin SL.Add(AL.Args[1].Value); // second argument is label end; end; for i := 0 to ClumpCode.Count - 1 do begin AL := ClumpCode.Items[i]; if SL.IndexOf(AL.LineLabel) = -1 then AL.LineLabel := ''; end; finally SL.Free; end; end; { TClumpCode } function TClumpCode.Add: TAsmLine; begin Result := TAsmLine(inherited Add); end; constructor TClumpCode.Create(aClump : TClump); begin inherited Create(TAsmLine); fClump := aClump; end; destructor TClumpCode.Destroy; begin inherited; end; procedure TClumpCode.FixupFinalization; var i : integer; AL : TAsmLine; bDone : boolean; begin // if this clump does not contain exit, exitto or subret calls anywhere // or if the last line has an invalid opcode (empty line with label) // then add exit at the very end bDone := False; for i := 0 to Count - 1 do begin AL := Items[i]; if AL.Command in [OP_FINCLUMP, OP_FINCLUMPIMMED, OP_SUBRET] then begin bDone := True; Break; end; end; if not bDone or ((Count > 0) and (Items[Count - 1].Command = OPS_INVALID)) then begin // need to add fthread to end of clump code AL := Add; AL.LineNum := Clump.LastLine; if Clump.IsSubroutine then begin AL.Command := OP_SUBRET; AL.AddArgs(Format('__%s_return', [Clump.Name])); end else AL.Command := OP_FINCLUMP; end; end; function TClumpCode.GetItem(Index: Integer): TAsmLine; begin Result := TAsmLine(inherited GetItem(Index)); end; procedure TClumpCode.HandleNameToDSID(const aName: string; var aId: integer); begin aId := 0; if Assigned(fOnNameToDSID) then fOnNameToDSID(aName, aId); end; procedure TClumpCode.SetItem(Index: Integer; const Value: TAsmLine); begin inherited SetItem(Index, Value); end; { TAsmArgument } function TAsmArgument.Evaluate(Calc: TNBCExpParser): Extended; begin Calc.Expression := Value; Result := Calc.Value; end; function TAsmArgument.IsQuoted(delim : char): boolean; begin // the argument is a quoted if it starts and ends with // the specified delimiter. Result := (IsDelimiter(delim, Value, 1) and IsDelimiter(delim, Value, Length(Value))); end; procedure TAsmArgument.SetValue(const Value: string); begin fDSID := -1; fValue := Value; end; { TDSData } constructor TDSData.Create; begin fDSStaticSize := -1; end; function TDSData.DSCount: Word; begin Result := Word(Length(TOC)); end; function TDSData.DSStaticSize: Word; var i : integer; X : DSTocEntry; begin if fDSStaticSize = -1 then begin // the maximum address in toc + the size in bytes fDSStaticSize := 0; for i := 0 to Length(TOC) - 1 do begin X := TOC[i]; if X.DataDesc >= fDSStaticSize then begin fDSStaticSize := LongInt(X.DataDesc) + LongInt(BytesPerType[TDSType(X.TypeDesc)]); end; end; fDSStaticSize := Integer(RoundToByteSize(Word(fDSStaticSize), DWORD_LEN)); end; Result := Word(fDSStaticSize); end; function TDSData.DVArrayOffset: Word; begin Result := DopeVecs[0].offset; end; function TDSData.DynDSDefaultsOffset: Word; begin Result := Word(Length(StaticDefaults)); end; function TDSData.DynDSDefaultsSize: Word; begin Result := Word((DVArrayOffset - DSStaticSize) + (Length(DopeVecs)*SizeOf(DopeVector))); end; procedure TDSData.SaveToStream(aStream: TStream); var i, len, sBytes : integer; B : Byte; begin // dataspace table of contents for i := 0 to Length(TOC) - 1 do begin with TOC[i] do begin aStream.Write(TypeDesc, 1); aStream.Write(Flags, 1); WriteWordToStream(aStream, DataDesc); end; end; // static default data sBytes := DynDSDefaultsOffset; i := 0; len := Length(StaticDefaults); while i < sBytes do begin if i < len then B := StaticDefaults[i] else B := $FF; aStream.Write(B, SizeOf(Byte)); inc(i); end; // dynamic default data for i := 0 to Length(DynamicDefaults) - 1 do aStream.Write(DynamicDefaults[i], SizeOf(Byte)); // dope vectors for i := 0 to Length(DopeVecs) - 1 do begin with DopeVecs[i] do begin WriteWordToStream(aStream, offset); WriteWordToStream(aStream, elemsize); WriteWordToStream(aStream, count); WriteWordToStream(aStream, backptr); WriteWordToStream(aStream, link); end; end; // pad to even boundary at the end of the dataspace if needed if (sBytes mod 2) > 0 then begin B := $FF; aStream.Write(B, SizeOf(Byte)); end; end; procedure TDSData.SaveToSymbolTable(aStrings: TStrings); var i : integer; X : DSTOCEntry; begin aStrings.Add('#SYMBOLS'); aStrings.Add('Index'#9'Identifier'#9'Type'#9'Flag'#9'Data'#9'Size'#9'RefCount'); for i := 0 to DSCount - 1 do begin X := TOC[i]; aStrings.Add(Format('%d'#9'%s'#9'%d'#9'%d'#9'%d'#9'%d'#9'%d', [i, TOCNames[i], X.TypeDesc, X.Flags, X.DataDesc, X.Size, X.RefCount])); end; end; { TCodeSpaceAry } function TCodeSpaceAry.CodespaceCount: Word; begin Result := Word(Length(Code)); end; procedure TCodeSpaceAry.SaveToStream(aStream: TStream); var i : integer; begin // output code array for i := 0 to Length(Code) - 1 do begin WriteWordToStream(aStream, Code[i]); end; end; { TClumpData } procedure TClumpData.SaveToStream(aStream: TStream); var i : integer; B : byte; begin // clump records for i := 0 to Length(CRecs) - 1 do begin aStream.Write(CRecs[i].FireCount, 1); aStream.Write(CRecs[i].DependentCount, 1); WriteWordToStream(aStream, CRecs[i].CodeStart); end; // clump dependencies for i := 0 to Length(ClumpDeps) - 1 do begin aStream.Write(ClumpDeps[i], SizeOf(Byte)); end; if Length(ClumpDeps) mod 2 <> 0 then begin B := $FF; aStream.Write(B, 1); end; end; { TCardinalObject } constructor TCardinalObject.Create(aValue: Cardinal); begin fValue := aValue; end; { TIntegerObject } constructor TIntegerObject.Create(aValue: Integer); begin fValue := aValue; end; { EDuplicateDataspaceEntry } constructor EDuplicateDataspaceEntry.Create(DE : TDataspaceEntry); begin inherited Create(Format(sDuplicateDSEntry, [DE.FullPathIdentifier])); end; end. NXT/nbcdelphi.mak0000644000175000017500000000267111537752673013557 0ustar slavkoslavkoPROGRAMS = nbc.exe VER = 1.2.1.r4 DOBJECTS=uNXTClasses.dcu uPreprocess.dcu Parser10.dcu P10Build.dcu uNXCComp.dcu uRPGComp.dcu uRIC.dcu uRICComp.dcu uNBCCommon.dcu uNXTConstants.dcu uNBCInterface.dcu nbc.dpr DEFAULT_INCLUDE_DIR=. all:: $(DOBJECTS) $(PROGRAMS) clean:: rm -f *.o *.ppu *.rst *.compiled *.dcu ../*.dcu ../bricktools/*.dcu nbc_preproc.inc realclean:: clean rm -f $(PROGRAMS) mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas # Delphi #TOOLPREFIX=C:/win32apps/Borland/Delphi7/Bin/ DELPHI=$(TOOLPREFIX)dcc32.exe # how to link executable %.exe: %.dpr nbc_preproc.inc $(DELPHI) $< -U.. -U../bricktools -U../png -DCAN_DOWNLOAD -DFAST_MM # how to compile pas source %.dcu: %.pas mkdata.exe NBCCommonData.pas NXTDefsData.pas NXCDefsData.pas $(DELPHI) $< -U.. -U../bricktools -U../png -DCAN_DOWNLOAD -DFAST_MM # how to create the include file nbc_preproc.inc: echo '// '$@ > $@ echo 'const' >> $@ echo ' DEFAULT_INCLUDE_DIR = '\'$(DEFAULT_INCLUDE_DIR)\'';' >> $@ echo ' COMPILATION_TIMESTAMP = '\'`date`\'';' >> $@ # how to create the mkdata utility mkdata.exe: mkdata.dpr $(DELPHI) $< -U.. # how to create NBCCommonData.pas NBCCommonData.pas: NBCCommon.h ./mkdata.exe $< $@ nbc_common_data # how to create NXTDefsData.pas NXTDefsData.pas: NXTDefs.h ./mkdata.exe $< $@ nxt_defs_data # how to create NXCDefsData.pas NXCDefsData.pas: NXCDefs.h ./mkdata.exe $< $@ nxc_defs_data ParamUtils.pas0000644000175000017500000001251111537752674013245 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit ParamUtils; interface uses Classes; function ParamSwitch(S: String; bIgnoreCase : Boolean = true; const cmdLine : string = ''): Boolean; function ParamValue(S: String; bIgnoreCase : Boolean = true; const cmdLine : string = ''): String; function ParamIntValue(S: String; def : Integer = -1; bIgnoreCase : Boolean = true; const cmdLine : string = ''): Integer; function JCHParamStr(Index: Integer; const cmdLine : string = ''): string; function JCHParamCount(const cmdLine : string = ''): Integer; function getFilenameParam(const cmdLine : string = '') : string; procedure LoadParamDefinitions(aStrings : TStrings; const cmdLine : string = ''); implementation uses SysUtils; function CharNext(P : PChar) : PChar; begin Result := P; Inc(Result); end; function GetParamStr(P: PChar; var Param: string): PChar; var i, Len: Integer; Start, S, Q: PChar; begin while True do begin while (P[0] <> #0) and (P[0] <= ' ') do P := CharNext(P); if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break; end; Len := 0; Start := P; while P[0] > ' ' do begin if P[0] = '"' then begin P := CharNext(P); while (P[0] <> #0) and (P[0] <> '"') do begin Q := CharNext(P); Inc(Len, Q - P); P := Q; end; if P[0] <> #0 then P := CharNext(P); end else begin Q := CharNext(P); Inc(Len, Q - P); P := Q; end; end; SetLength(Param, Len); P := Start; S := Pointer(Param); i := 0; while P[0] > ' ' do begin if P[0] = '"' then begin P := CharNext(P); while (P[0] <> #0) and (P[0] <> '"') do begin Q := CharNext(P); while P < Q do begin S[i] := P^; Inc(P); Inc(i); end; end; if P[0] <> #0 then P := CharNext(P); end else begin Q := CharNext(P); while P < Q do begin S[i] := P^; Inc(P); Inc(i); end; end; end; Result := P; end; function JCHParamStr(Index: Integer; const cmdLine : string): string; var P: PChar; begin Result := ''; if (Index = 0) or (cmdLine = '') then Result := ParamStr(Index) else begin P := PChar(cmdLine); while True do begin P := GetParamStr(P, Result); if (Index = 0) or (Result = '') then Break; Dec(Index); end; end; end; function JCHParamCount(const cmdLine : string): Integer; var P: PChar; S: string; begin Result := 0; S := ''; if cmdLine = '' then Result := ParamCount else begin P := GetParamStr(PChar(cmdLine), S); while True do begin P := GetParamStr(P, S); if S = '' then Break; Inc(Result); end; end; end; function ParamSwitch(S: String; bIgnoreCase : Boolean; const cmdLine : string): Boolean; var I: Integer; P: String; begin Result := False ; if bIgnoreCase then S := UpperCase(S); for I := 0 to JCHParamCount(cmdLine) do begin P := JCHParamStr(I, cmdLine); if bIgnoreCase then P := UpperCase(P); if (P=S) or (Pos(S+'=',P)=1) then begin Result := True ; Break; end; end; end; function ParamValue(S: String; bIgnoreCase : Boolean; const cmdLine : string): String; var I : Integer; P, val: String; begin Result := '' ; if bIgnoreCase then S := UpperCase(S); for I := 0 to JCHParamCount(cmdLine) do begin val := JCHParamStr(I, cmdLine); if bIgnoreCase then P := UpperCase(val) else P := val; if (Pos(S+'=',P)<>0) then begin Result := Copy(val,Length(S)+2,MaxInt); Break; end; end; end; function ParamIntValue(S: String; def : integer; bIgnoreCase : Boolean; const cmdLine : string): Integer; begin Result := StrToIntDef(ParamValue(S, bIgnoreCase, cmdLine), def); end; function getFilenameParam(const cmdLine : string) : string; var i : Integer; tmp : string; begin Result := ''; for i := 1 to JCHParamCount(cmdLine) do begin tmp := JCHParamStr(i, cmdLine); if Pos('-', tmp) = 1 then Continue; // a switch // the first parameter that is not a switch is the filename Result := tmp; Break; end; end; procedure LoadParamDefinitions(aStrings : TStrings; const cmdLine : string); var I : Integer; P: String; begin for I := 0 to JCHParamCount(cmdLine) do begin P := JCHParamStr(I, cmdLine); if Pos('-D=', P) = 1 then begin // this is a #define System.Delete(P, 1, 3); if Pos('=', P) = 0 then P := P + '=1'; aStrings.Add(P); end; end; end; end. tests/0000755000175000017500000000000011676036336011613 5ustar slavkoslavkotests/struct.nxc0000644000175000017500000000174211537752640013654 0ustar slavkoslavkotypedef unsigned int myType ; struct person { string name; myType age; }; struct car { string car_type; int manu_year; }; myType fred = 23; person myPerson; task main() { typedef const unsigned long anotherType; person anotherPerson; car fooBar; myPerson.age = 40; anotherPerson = myPerson; fooBar.car_type = "honda"; fooBar.manu_year = anotherPerson.age; // fooBar = anotherPerson; fooBar.manu_year += 1; fooBar += 2; anotherPerson.age = myPerson.age + 1; anotherPerson.name = "testing"; anotherType j = 12; int i = 0; i = j + 10; NumOut(0, LCD_LINE1, fooBar.manu_year); NumOut(0, LCD_LINE2, myPerson.age); NumOut(0, LCD_LINE3, anotherPerson.age); NumOut(0, LCD_LINE4, j); NumOut(0, LCD_LINE5, i); TextOut(0, LCD_LINE6, anotherPerson.name); TextOut(0, LCD_LINE7, fooBar.car_type); fooBar -= 2; TextOut(0, LCD_LINE8, fooBar.car_type); Wait(10000); } tests/test.npg0000644000175000017500000000013511537752640013276 0ustar slavkoslavkoForward WaitTwoSeconds //BackwardFive //EmptyWait ForwardFive WaitFiveSeconds EndLoop tests/test.nxc0000644000175000017500000001131311537752640013302 0ustar slavkoslavko// requires b30 long a=-40, b = 23, __b=34; byte zz; byte buf[]; long data[]; byte foo[][]; string weird = "fred"; //#define Testing OnRev(OUT_BC, 50) void George(byte b); /* void George(byte b) { int g1 = 4, g2=-3; byte b1[], b2=33; b2 = g1+g2+b; // b1 = OUT_BC; OnFwd(OUT_BC, b2); Wait(1000); // byte b1[], b2=33; Testing; Wait(1000); } */ //void MyTestSub(int x, int y, short j); void MyTestSub(int x, int y, short j) //void MyTestSub(x, y, j) { byte g1=3, g2=5; int foo=-3; foo = GetOutput(OUT_A, TachoCount); SetSensor(IN_3, SENSOR_ROTATION); George(g2*10); foo = x + y * j; g1 = foo/4; NumOut(0, 0, true, g1); OnFwd(OUT_BC, g1); Wait(4000); } task Fred() { ArrayInit(data, 0, 4); data[0] = 23; weird[2] = "Wd" ; // data[0] = weird[0]; // NumOut(0, LCD_LINE4, data[0], true); weird += BrickDataName(); TextOut(50, LCD_LINE1, weird, true); GetBrickDataAddress(buf); b = ArrayLen(buf); NumOut(0, LCD_LINE1, b); for (a=0, b=2; a < b; a++) { NumOut(a*15, LCD_LINE2, buf[a]); } Wait(10000); OnFwd(OUT_BC, -75); Wait(5000); } char j=-40, k = 23, x=4; mutex myMutex; string msg="test" , blech; string FooBar(int a, string b) { string result ="r=" ; result += NumToStr(a); result += b; return (result); } int Multiply(int a, int b) { return (a * b); } task main (){ int xxxx = 23; Precedes(Fred); // Stop( xxxx == 23 ); // Fred; msg = FooBar(10, "_fred" ); TextOut(0, LCD_LINE1, msg, true); NumOut(0, LCD_LINE2, xxxx); xxxx = Multiply(2, 3) + 4; NumOut(0, LCD_LINE3, xxxx); xxxx = Multiply(2, 3); NumOut(0, LCD_LINE4, xxxx); NumOut(0, LCD_LINE5, Multiply(10, xxxx)); xxxx = ("fred" == "fred") + 2 + (5 >= (2*2)); NumOut(0, LCD_LINE6, xxxx); Wait(10000); Stop( "fred" == "fred" ); RotateMotorEx(OUT_BC, 75, 90, 0, true, true); RotateMotorEx(OUT_BC, 75, 90, 100, true, true); RotateMotorEx(OUT_BC, 75, 90, -100, true, true); RotateMotorEx(OUT_BC, -75, 90, 0, true, true); RotateMotorEx(OUT_BC, -75, 90, 100, true, true); RotateMotorEx(OUT_BC, -75, 90, -100, true, true); Stop(true); a = (j < 5) ? 23 : 48; if (j < 5 && ((k&0x7f) != 0)) { OnRev(OUT_B, 40); } else { OnFwd(OUT_B, 70); } Random(5000); if (true) OnRev(OUT_B, 40); else { OnFwd(OUT_C, 30); } { OnFwd(OUT_A, 20); a=Random(5000) * 2; NumOut(0, 20, true, a); Wait(a); Off(OUT_A); } do { // foobar; OnFwd(OUT_BC, 50+40); Wait(500); Off(OUT_BC); Wait(1000); a++; b++; } while (a < 10); repeat(10) { repeat(4) { OnFwd(OUT_BC, 50); Wait(1000); Off(OUT_BC); Wait(2000); } } Acquire(myMutex); asm { add a, a, 1 sub b, a, 2 OnRev(OUT_BC, 50) } Release(myMutex); SetSensorType(IN_1, IN_TYPE_SWITCH); PlayTone(TONE_A4, MS_500); while(!SoundState()) /* do nothing */ ; Wait(500); PlayFile( "test.rso" ); myLoop: LineOut(30, 50, 50, 30, false); LineOut(0, 0, 30, 50, false); PointOut(30, 40, false); CircleOut(30, 40, 10, false); RectOut(30, 50, 20, 10, false); // goto myLoop msg += ".r" + "s" + "o" ; PlayFile(msg); // Wait(1000); msg = NumToStr(10); TextOut(0, 50, msg); msg = StrCat("test" , " " , "please" ); TextOut(0, 35, msg); msg = SubStr("please" , 1, 3); TextOut(0, 0, msg); msg = Flatten(0x31); NumOut(50, 0, StrLen(msg)); TextOut(60, 0, msg); msg = StrReplace("please" , 2, "AA" ); TextOut(50, 8, msg); a = 100 - FreeMemory(); // a = FreeMemory(); NumOut(50, LCD_LINE2, a, true); NumOut(50, LCD_LINE3, FreeMemory()); NumOut(50, LCD_LINE4, BatteryLevel()); PlayTone(440, 2000); NumOut(10, LCD_LINE1, SoundState(), true); NumOut(10, LCD_LINE2, SoundFlags()); Wait(50); StopSound(); x--; if ((x%3)!=0) { TextOut(10, LCD_LINE1, "whoops"); } until(ButtonPressed(BTN2, true)); until(!ButtonPressed(BTN2, true)); SetSensorLowspeed(IN_1); // SetButtonState(BTN2, 0); ResetSensor(IN_1); while(BluetoothStatus(0) != 0); while(!BluetoothStatus(0)); while (!ButtonPressed(BTN2, true)) { NumOut(10, LCD_LINE5, SensorUS(IN_1), true); Wait(10); } while(!ButtonPressed(BTN4, true)) ; MyTestSub(12, 45, 10); } #define Testing OnRev(OUT_BC, 50) byte d, e, f; void George(byte b) { int g1 = 4, g2=-3; byte b1[], b2=33; b2 = g1+g2+b; // b1 = OUT_BC; OnFwd(OUT_BC, b2); Wait(1000); // byte b1[], b2=33; Testing; Wait(1000); } tests/bools.nbc0000644000175000017500000000517311537752640013422 0ustar slavkoslavko; -------------- variable declarations -------------- dseg segment ;------- definitions ------- ;------- declarations ------- myVar1 byte boolval2 byte 1 another_var byte 1 b2 byte bTrue byte 1 PleaseWork byte 1 dtArgs TDrawText MOT_AB byte[] OUT_A, OUT_B MOT_BC byte[] OUT_B, OUT_C MOT_ABC byte[] OUT_A, OUT_B, OUT_C buf byte[] 'test one, two' dseg ends ; -------------- program code -------------- /* dseg segment __main_wait_return byte __main_wait_ms word __main_wait_now dword __main_wait_then dword dseg ends */ #define TEXTOUT(x,y,cls,txt) mov dtArgs.Location.X,x \ mov dtArgs.Location.Y,y \ mov dtArgs.Options,cls \ mov dtArgs.Text,txt \ syscall DrawText,dtArgs #define FOO 75 #define BAR FOO*-1 #define FILEREAD(h,l,r,b) acquire frMutex \ mov frArgs.FileHandle,h \ mov frArgs.Length,l \ syscall FileRead,frArgs \ mov l, frArgs.Length \ mov b,frArgs.Buffer \ mov r,frArgs.Result \ release frMutex #define testing \ __##__THREADNAME__##_##__I__##: \ set b2, 100 \ jmp __##__THREADNAME__##_##__I__ \ __IncI__ // also __J__, __IncJ__, __DecI__, __DecJ__, __ResetI__, and __ResetJ__ thread main dseg segment fredfred byte 23 dseg ends #pragma debugbreak testing testing testing mov another_var, PleaseWork mov boolval2, bTrue mov myVar1, b2 set myVar1, 4<<5 mov myVar1, fredfred OnFwd( MOT_AB, FOO ) waitv 4000 Off(MOT_AB) waitv 1500 OnRev(MOT_AB, fredfred) mov dtArgs.Text, buf mov dtArgs.Text, 'please work, wont you?' TEXTOUT(10,60,1,'HELLO; // , / . WORLD!') // mov 10, myVar1 waitv 4000 Coast(MOT_AB) waitv 4000 call MySub waitv 1500 abs myVar1, -50 jmp BadLabelLocation // set __main_wait_ms, 65534 // subcall __main_wait, __main_wait_return // exit BadLabelLocation: abs myVar1, -60 endt thread Testing dseg segment fredfred2 byte 10 dseg ends mov boolval2, fredfred2 endt subroutine MySub mov boolval2, fredfred OnFwd( MOT_AB, FOO ) wait 3000 Off(MOT_AB) return ends /* thread __main_wait gettick __main_wait_now add __main_wait_then, __main_wait_now, __main_wait_ms __main_waiting: gettick __main_wait_now brcmp LT, __main_waiting, __main_wait_now, __main_wait_then subret __main_wait_return endt */ uCmdLineUtils.pas0000644000175000017500000000440711537752674013712 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uCmdLineUtils; interface uses Classes; function progName : string; procedure PrintVersion(const ts : string = ''); procedure PrintUsageError(const ts : string = ''); function redirectErrorsToFile : boolean; procedure setErrorOutputFile(var F : TextFile); function getIncludePath : string; implementation uses SysUtils, ParamUtils, uVersionInfo, uLocalizedStrings; function progName : string; begin Result := ExtractFileName(ParamStr(0)); Result := ChangeFileExt(Result, ''); end; procedure PrintVersion(const ts : string); var V : TVersionInfo; app, tmp : string; begin app := ParamStr(0); V := GetVersionInfo(app); tmp := V.ProductName + VersionString + V.ProductVersion + ' (' + V.FileVersion; if ts <> '' then tmp := tmp + ',' + BuiltString + ts; tmp := tmp + ')'; Writeln(tmp); Writeln(' ' + V.LegalCopyright); end; procedure PrintUsageError(const ts : string); begin PrintVersion(ts); Writeln(Format(UsageErrorMessage, [progName])); end; function redirectErrorsToFile : boolean; begin Result := ParamSwitch('-E', false); end; procedure setErrorOutputFile(var F : TextFile); var val, dir : string; begin val := ''; if ParamSwitch('-E', false) then begin val := ParamValue('-E', false); dir := ExtractFilePath(val); if dir <> '' then ForceDirectories(dir); end; AssignFile(F, val); Rewrite(F); end; function getIncludePath : string; begin Result := ExtractFilePath(ParamStr(0)); if ParamSwitch('-I', false) then begin Result := ParamValue('-I', false); end; end; end. uCommonUtils.pas0000644000175000017500000002264011537752674013626 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uCommonUtils; interface uses Classes; const DEFAULT_CHARSET = 1; SW_SHOWMINNOACTIVE = 7; HKEY_CLASSES_ROOT = LongWord($80000000); HKEY_CURRENT_USER = LongWord($80000001); HKEY_LOCAL_MACHINE = LongWord($80000002); type HWND = type LongWord; type TWaveFormatEx = packed record wFormatTag: Word; { format type } nChannels: Word; { number of channels (i.e. mono, stereo, etc.) } nSamplesPerSec: Cardinal; { sample rate } nAvgBytesPerSec: Cardinal; { for buffer estimation } nBlockAlign: Word; { block size of data } wBitsPerSample: Word; { number of bits per sample of mono data } cbSize: Word; { the count in bytes of the size of } end; type _mthd = record id : array[0..3] of Char; len : Cardinal; fmt : Word; track : Word; div_ : Word; end; MTHD = _mthd; type _mtrk = record id : array[0..3] of Char; len : Cardinal; end; MTRK = _mtrk; procedure WriteSmallIntToStream(aStream : TStream; value : SmallInt; bLittleEndian : Boolean = True); procedure ReadSmallIntFromStream(aStream : TStream; var value : SmallInt; bLittleEndian : Boolean = True); procedure WriteWordToStream(aStream : TStream; value : Word; bLittleEndian : Boolean = True); procedure ReadWordFromStream(aStream : TStream; var value : Word; bLittleEndian : Boolean = True); procedure WriteCardinalToStream(aStream : TStream; value : Cardinal; bLittleEndian : Boolean = True); procedure ReadCardinalFromStream(aStream : TStream; var value : Cardinal; bLittleEndian : Boolean = True); procedure WriteWaveFormatToStream(aStream : TStream; fmt : TWaveFormatEx); function ReadMIDIMTHDFromStream(aStream : TStream; var head : MTHD) : boolean; function ReadMIDIMTRKFromStream(aStream : TStream; var head : MTRK) : boolean; function HiWord(L: Cardinal): Word; function HiByte(W: Word): Byte; function GetByte(val : Cardinal; idx : integer) : Byte; function BytesToCardinal(b1 : byte; b2 : byte = 0; b3 : byte = 0; b4 : Byte = 0) : Cardinal; {overload;} //function BytesToCardinal(b : array of byte) : Cardinal; overload; procedure GetFileList(const Directory : string; const Pattern : string; List : TStringlist); procedure GetSubDirectories(const Directory : string; List : TStringlist); procedure OSSleep(const ms : Cardinal); procedure PostWindowMessage(aHwnd : HWND; aMsg : Cardinal; wParam, lParam : Integer); function MulDiv(const x, num, den : integer) : integer; function CardinalToSingle(const cVal : Cardinal) : Single; function SingleToCardinal(const sVal : Single) : Cardinal; function StripTrailingZeros(const aNum : string) : string; implementation uses {$IFNDEF FPC} Windows, {$ENDIF} SysUtils; procedure WriteWordToStream(aStream : TStream; value : Word; bLittleEndian : Boolean); var B1, B2 : byte; begin if bLittleEndian then begin B1 := Lo(value); B2 := Hi(value); end else begin B1 := Hi(value); B2 := Lo(value); end; aStream.Write(B1, 1); aStream.Write(B2, 1); end; procedure WriteSmallIntToStream(aStream : TStream; value : SmallInt; bLittleEndian : Boolean); begin WriteWordToStream(aStream, Word(value), bLittleEndian); end; procedure ReadWordFromStream(aStream : TStream; var value : Word; bLittleEndian : Boolean); var B1, B2 : byte; begin B1 := 0; B2 := 0; aStream.Read(B1, 1); aStream.Read(B2, 1); if bLittleEndian then begin value := Word(Word(B1) + (Word(B2) shl 8)); end else begin value := Word(Word(B2) + (Word(B1) shl 8)); end; end; procedure ReadSmallIntFromStream(aStream : TStream; var value : SmallInt; bLittleEndian : Boolean); var w : word; begin w := 0; ReadWordFromStream(aStream, w, bLittleEndian); value := SmallInt(w); end; procedure WriteCardinalToStream(aStream : TStream; value : Cardinal; bLittleEndian : Boolean); var b1, b2, b3, b4 : byte; begin if bLittleEndian then begin b1 := GetByte(value, 0); b2 := GetByte(value, 1); b3 := GetByte(value, 2); b4 := GetByte(value, 3); end else begin b1 := GetByte(value, 3); b2 := GetByte(value, 2); b3 := GetByte(value, 1); b4 := GetByte(value, 0); end; aStream.Write(b1, 1); aStream.Write(b2, 1); aStream.Write(b3, 1); aStream.Write(b4, 1); end; procedure ReadCardinalFromStream(aStream : TStream; var value : Cardinal; bLittleEndian : Boolean); var b1, b2, b3, b4 : byte; begin b1 := 0; b2 := 0; b3 := 0; b4 := 0; aStream.Read(b1, 1); aStream.Read(b2, 1); aStream.Read(b3, 1); aStream.Read(b4, 1); if bLittleEndian then begin value := BytesToCardinal(b1, b2, b3, b4); end else begin value := BytesToCardinal(b4, b3, b2, b1); end; end; procedure WriteWaveFormatToStream(aStream : TStream; fmt : TWaveFormatEx); begin WriteWordToStream(aStream, fmt.wFormatTag); WriteWordToStream(aStream, fmt.nChannels); WriteCardinalToStream(aStream, fmt.nSamplesPerSec); WriteCardinalToStream(aStream, fmt.nAvgBytesPerSec); WriteWordToStream(aStream, fmt.nBlockAlign); WriteWordToStream(aStream, fmt.wBitsPerSample); WriteWordToStream(aStream, fmt.cbSize); end; function ReadMIDIMTHDFromStream(aStream : TStream; var head : MTHD) : boolean; begin try aStream.Read(head.id, 4); ReadCardinalFromStream(aStream, head.len, False); ReadWordFromStream(aStream, head.fmt, False); ReadWordFromStream(aStream, head.track, False); ReadWordFromStream(aStream, head.div_, False); Result := True; except Result := False; end; end; function ReadMIDIMTRKFromStream(aStream : TStream; var head : MTRK) : boolean; begin try aStream.Read(head.id, 4); ReadCardinalFromStream(aStream, head.len, False); Result := True; except Result := False; end; end; function HiWord(L: Cardinal): Word; begin Result := Word(L shr 16); end; function HiByte(W: Word): Byte; begin Result := Byte(W shr 8); end; function GetByte(val : Cardinal; idx : integer) : Byte; begin case idx of 0 : Result := Lo(Word(val)); 1 : Result := Hi(Word(val)); 2 : Result := Lo(HiWord(val)); 3 : Result := Hi(HiWord(val)); else Result := 0; end; end; procedure OSSleep(const ms : Cardinal); begin {$IFDEF FPC} // not sure what to do here yet {$ELSE} Windows.Sleep(ms); {$ENDIF} end; procedure PostWindowMessage(aHwnd : HWND; aMsg : Cardinal; wParam, lParam : Integer); begin {$IFDEF FPC} // ; {$ELSE} PostMessage(aHwnd, aMsg, wParam, lParam); {$ENDIF} end; function MulDiv(const x, num, den : integer) : integer; begin Result := (x * num) div den; end; function BytesToCardinal(b1 : byte; b2 : byte = 0; b3 : byte = 0; b4 : Byte = 0) : Cardinal; begin Result := Cardinal(b1) + (Cardinal(b2) shl 8) + (Cardinal(b3) shl 16) + (Cardinal(b4) shl 24); end; { function BytesToCardinal(b : array of byte) : Cardinal; var i : integer; begin Result := 0; for i := Low(b) to High(b) do Result := (Result shl 8) + b[i]; end; } {$ifdef FPC} function CardinalToSingle(const cVal : Cardinal) : Single; begin Result := Single(cVal); end; function SingleToCardinal(const sVal : Single) : Cardinal; begin Result := Cardinal(sVal); end; {$else} function CardinalToSingle(const cVal : Cardinal) : Single; begin Result := Single(Pointer(cVal)); end; function SingleToCardinal(const sVal : Single) : Cardinal; begin Result := Cardinal(Pointer(sVal)); end; {$endif} function StripTrailingZeros(const aNum : string) : string; begin Result := aNum; while Result[Length(Result)] = '0' do System.Delete(Result, Length(Result), 1); if Result[Length(Result)] in ['.', ','] then System.Delete(Result, Length(Result), 1); end; procedure GetFileList(const Directory : string; const Pattern : string; List : TStringlist); var SearchRec : TSearchRec; iRes : Integer; begin iRes := FindFirst(IncludeTrailingPathDelimiter(Directory) + Pattern, faAnyFile, SearchRec); try while iRes = 0 do begin if (SearchRec.Attr and faDirectory) <> faDirectory then List.Add(SearchRec.Name); iRes := FindNext(SearchRec); end; finally FindClose(SearchRec); end; end; procedure GetSubDirectories(const Directory : string; List : TStringlist); var SearchRec : TSearchRec; iRes : Integer; begin iRes := FindFirst(IncludeTrailingPathDelimiter(Directory) + '*.*', faDirectory, SearchRec); try while iRes = 0 do begin if (SearchRec.Attr and faDirectory) = faDirectory then if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then List.Add(SearchRec.Name); iRes := FindNext(SearchRec); end; finally FindClose(SearchRec); end; end; end. uDebugLogging.pas0000644000175000017500000000234411537752674013711 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uDebugLogging; interface procedure DebugLog(const aMsg : string); procedure DebugFmt(const aFormat: string; const Args: array of const); implementation uses {$IFNDEF FPC} Windows, {$ENDIF} SysUtils; procedure WriteToLog(const aMsg : string); begin {$IFNDEF FPC} OutputDebugString(PChar(aMsg)); {$ENDIF} end; procedure DebugLog(const aMsg : string); begin WriteToLog(aMsg); end; procedure DebugFmt(const aFormat: string; const Args: array of const); var msg : string; begin msg := Format(aFormat, Args); WriteToLog(msg); end; end.uGenLexer.pas0000644000175000017500000000215111537752674013061 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uGenLexer; interface uses mwGenericLex; type TGenLexer = class(TmwGenLex) protected procedure InitForLanguage(Lex: TGenLexer); virtual; abstract; public constructor CreateLexer; virtual; end; TGenLexerClass = class of TGenLexer; implementation { TGenLexer } constructor TGenLexer.CreateLexer; begin inherited Create; Sensitive := True; Clear; InitMainSelector; InitForLanguage(Self); end; end.uGlobals.pas0000644000175000017500000001006011537752674012731 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uGlobals; {$IFDEF FPC} {$MODE Delphi} {$ENDIF} interface const // remote commands kRemoteKeysReleased = $0000; kRemotePBMessage1 = $0100; kRemotePBMessage2 = $0200; kRemotePBMessage3 = $0400; kRemoteOutAForward = $0800; kRemoteOutBForward = $1000; kRemoteOutCForward = $2000; kRemoteOutABackward = $4000; kRemoteOutBBackward = $8000; kRemoteOutCBackward = $0001; kRemoteSelProgram1 = $0002; kRemoteSelProgram2 = $0004; kRemoteSelProgram3 = $0008; kRemoteSelProgram4 = $0010; kRemoteSelProgram5 = $0020; kRemoteStopOutOff = $0040; kRemotePlayASound = $0080; {$IFDEF FPC} const MB_ICONASTERISK = $00000040; {$ENDIF} const K_RCX = 'RCX'; K_CYBER = 'CyberMaster'; K_SCOUT = 'Scout'; K_RCX2 = 'RCX2'; K_SPY = 'Spybot'; K_SWAN = 'Swan'; K_NXT = 'NXT'; const rtRCX = 0; rtCybermaster = 1; rtScout = 2; rtRCX2 = 3; rtSpy = 4; rtSwan = 5; rtNXT = 6; const SU_RCX = rtRCX; SU_CYBERMASTER = rtCybermaster; SU_SCOUT = rtScout; SU_RCX2 = rtRCX2; SU_SPYBOTIC = rtSpy; SU_SWAN = rtSwan; SU_NXT = rtNXT; var UserDataLocalPath : string; SymFileLibraryPath : string; var LocalBrickType : integer; LocalStandardFirmware : Boolean; var GlobalAbort : boolean; function IsNXT : boolean; function IsSwan : boolean; function IsRCX2 : boolean; function IsRCX : boolean; function IsScout : boolean; function IsSpybotic : boolean; function GetJoystickButtonScript(const i : byte; bPress : boolean) : string; {$IFNDEF FPC} function GetSpecialFolderPath(folder : integer) : string; {$ENDIF} implementation uses {$IFNDEF FPC} SHFolder, Windows, {$ENDIF} SysUtils; function IsNXT : boolean; begin result := (LocalBrickType = SU_NXT); end; function IsSwan : boolean; begin result := (LocalBrickType = SU_SWAN); end; function IsRCX2 : boolean; begin result := (LocalBrickType = SU_RCX2) or (LocalBrickType = SU_SWAN); end; function IsRCX : boolean; begin result := (LocalBrickType = SU_RCX) or (LocalBrickType = SU_RCX2) or (LocalBrickType = SU_SWAN); end; function IsScout : boolean; begin result := (LocalBrickType = SU_SCOUT); end; function IsSpybotic : boolean; begin result := (LocalBrickType = SU_SPYBOTIC); end; function GetJoystickButtonScript(const i : byte; bPress : boolean) : string; const name_postfix : array[boolean] of string = ('r', 'p'); begin Result := UserDataLocalPath+Format('joybtn%2.2d%s.rops', [i, name_postfix[bPress]]); end; {$IFNDEF FPC} function GetSpecialFolderPath(folder : integer) : string; const SHGFP_TYPE_CURRENT = 0; var path: array [0..MAX_PATH] of char; begin if SUCCEEDED(SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,@path[0])) then Result := path else Result := ''; end; {$ENDIF} initialization {$IFNDEF FPC} UserDataLocalPath := GetSpecialFolderPath(CSIDL_APPDATA{CSIDL_LOCAL_APPDATA})+'\JoCar Consulting\BricxCC\3.3\'; SymFileLibraryPath := GetSpecialFolderPath(CSIDL_APPDATA{CSIDL_LOCAL_APPDATA})+'\JoCar Consulting\BricxCC\3.3\sym\'; {$ELSE} UserDataLocalPath := IncludeTrailingPathDelimiter(ExpandFilename('~')); SymFileLibraryPath := IncludeTrailingPathDelimiter(ExpandFilename('~')) + IncludeTrailingPathDelimiter('sym'); {$ENDIF} end. uLocalizedStrings.pas0000644000175000017500000007574111537752674014647 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uLocalizedStrings; interface // BricxCC unit resourcestring S_RESET = 'reload defaults from Default directory'; S_COM = 'use the named port for this instance (COM1..COMnnn, usb)'; S_RCX = 'use brick type N for this instance'; S_AUTO = 'auto connect using default or specified port and type'; S_NONE = 'do not connect to brick at startup'; S_POS = 'position windows using values in INI file'; S_HELP = 'display this message before starting up'; S_NT = 'use compiler timeout specified for this instance (in seconds)'; S_DEBUG = 'display debug message when launching compiler'; S_USERPATH = 'set the path for user configuration files'; // MainUnit unit resourcestring sNoRCX = 'No connection to the programmable brick. Certain options will be unavailable.'; sNoPort = 'no port'; sNoRobot = 'no robot'; sHideCodeError = 'Hide Code/Error|Warning Listing'; sShowCodeError = 'Show Code/Error|Warning Listing'; sFirmDwnldFailed = 'Firmware download failed. Put the RCX closer and try again.'; sWrongNum = 'wrong download number'; sWarnCancelFD = 'Firmware download cancelled.'; sBrickCommError = 'Unable to communicate with your brick'; sRecording = 'Recording'; sEnterData = 'Enter data'; sEnterRunParams = 'Enter run parameters'; SFilterAllFiles = 'All files|*.*|'; sProgramLocked = 'Program is locked.'; sClearMemConfirm = 'Are you sure you want to clear the brick''s memory?'; sBreakAll = 'Break all'; sContinue = 'Continue'; sFileMenu = '&File'; sEditMenu = '&Edit'; sCopySpecialMenu = 'Copy &Special'; sSearchMenu = '&Search'; sViewMenu = '&View'; sProjectManager = '&Project Manager'; sCodeExplorer = 'Code E&xplorer'; sStatusBar = '&Status bar'; sTemplates = 'T&emplates'; sHideErrors = '&Hide Errors'; sToolWindows = '&Tool Windows'; sMacroManager = '&Macro Manager'; spbForthConsole = 'pbForth Console'; sWindowList = '&Window List'; sToolbarsMenu = 'Tool&bars'; sCompileMenu = '&Compile'; sProgramNumberMenu = '&Program Number'; sProgram = 'Program'; sToolsMenu = '&Tools'; sbrickOSMenu = '&brickOS'; sSetLNPAddress = '&Set LNP Address...'; sLNPAddress = 'LNP &Address'; sAddress = 'Address'; sLNPPort = 'LNP &Port'; sPort = 'Port'; sWindowMenu = '&Window'; sTileHorizontal = 'Tile &Horizontal'; sTileVertical = 'Tile &Vertical'; sCascade = '&Cascade'; sArrangeIcons = '&Arrange Icons'; sPositionsMenu = '&Positions'; sSave = 'Save'; sLoad = 'Load'; sHelpMenu = '&Help'; sIndex = '&Index'; sNQCGuide = '&NQC Guide'; sHowToUseHelp = '&How to Use Help'; sWebPage = '&Web page'; sNextWindow = '&Next window'; sGuidePDFs = 'Guide PDFs'; sTutorialPDFs = 'Tutorial PDFs'; // Editor unit resourcestring S_Overwrite = 'Overwrite'; S_Insert = 'Insert'; S_ReadOnly = 'ReadOnly'; S_FileChanged = 'File %s has been modified. Save changes?'; S_Modified = 'Modified'; sErrors = 'Errors'; sFullErrors = 'Full errors in'; sCodeListing = 'Code listing of'; sCompileSuccess = 'Program compiled successfully.'; sCompileErrors = 'Errors found on program compile.'; sCompileDownloadSuccess = 'Program compiled and downloaded successfully.'; sCompileDownloadErrors = 'Errors found on program compile and download.'; sUntitled = 'Untitled'; sFindDeclaration = 'Find Dec&laration'; sClosePage = '&Close Page'; sOpenFileAtCursor = 'Open &File at Cursor'; sTopicSearch = 'Topic &Search'; sUndo = 'U&ndo'; sRedo = '&Redo'; sCut = 'C&ut'; sCopy = 'Co&py'; sPaste = 'P&aste'; sDelete = 'D&elete'; sSelectAll = 'Selec&t All'; sToggleBookmarksMenu = '&Toggle Bookmarks'; sBookmark = 'Bookmark'; sGotoBookmarksMenu = '&Goto Bookmarks'; sViewExplorer = 'View E&xplorer'; sToggleBreakpoint = 'Toggle Breakpoint'; // CodeUnit unit resourcestring sFind = '&Find'; sFindNext = 'Find &Next'; sFindPrevious = 'Find &Previous'; sGotoLine = '&Goto Line'; sStayOnTop = 'Stay on &top'; // GotoLine unit resourcestring sGotoError = 'Line must be between 1 and %d.'; // GX_ProcedureList resourcestring SAllString = ''; SNoneString = ''; SInvalidIndex = 'Invalid index number'; SParseStatistics = 'Procedures processed in %g seconds'; // SearchRCX unit resourcestring S_CANNOT_FIND_RCX = 'Cannot find brick. Switch it on or move it closer and press OK.'; S_SEARCHING_NXT = 'Searching for NXTs'; S_SEARCHING_BRICK = 'Searching for a brick'; // Translate unit resourcestring S_TRANSLATE = 'Translating an old NQC program into NQC 2.0. ' + 'This might not be completely correct. ' + 'Please check afterwards. Do you want to continue?'; // uCodeExplorer unit resourcestring sUnableToParseFile = 'Unable to parse current file'; // uParseCommon unit + others resourcestring SImplementationNotFound = 'Implementation section not found (parser error?)'; sUnknown = 'Unknown'; sFunction = 'Function'; sProcedure = 'Procedure'; sConstructor = 'Constructor'; sDestructor = 'Destructor'; sClassFunc = 'Class Func'; sClassProc = 'Class Proc'; sTask = 'Task'; sSubroutine = 'Subroutine'; sMacros = 'Macros'; sFunctions = 'Functions'; sSubroutines = 'Subroutines'; sTasks = 'Tasks'; sProcedures = 'Procedures'; sConstructors = 'Constructors'; sDestructors = 'Destructors'; sExploring = 'Exploring'; // uMacroForm unit resourcestring sConfirmDeleteMM = 'Delete selected macro?'; // About unit resourcestring sVersion = 'Version'; sBuild = 'Build'; // dlgConfirmReplace resourcestring SAskReplaceText = 'Replace this occurence of "%s"?'; // DTestPrintPreview resourcestring sPageLabel = ' Page: '; sPrintCmdHint = 'Print (%0:s)|Print the document on %0:s'; sWholePage = 'Whole page'; sPageWidth = 'Page width'; // Construct unit resourcestring sExpandAll = 'Expand All'; sCollapseAll = 'Collapse All'; sDoubleClickToInsert = 'Double Click to Insert'; // ExecProgram unit resourcestring sTimeout = 'Program execution timed out. Try increasing the timeout value.'; sAborted = 'Program execution aborted.'; sUnableToExecute = 'Unable to create process:' + #10 + '%s' + #10#10 + 'Make sure %s is in a directory on the system path ' + #10 + 'or in the same directory as the controlling program' + #10 + '(%s).'; // Preferences unit resourcestring S_ChangeMacroCaption = 'Changing a Macro'; S_ChangeMacroPrompt = 'Change Macro %s:'; S_ChangeTemplateCaption = 'Changing a Template'; S_ChangeTemplatePrompt = 'Change the Template:'; S_InsertTemplateCaption = 'Inserting a Template'; S_InsertTemplatePrompt = 'Type the template you want to insert:'; S_KeystrokeCaption = 'Keystroke Editor'; S_CodeTemplatesCaption = 'Code Templates'; S_ConfirmAPIDelete = 'Are you sure you want to delete this item?'; // Controller unit resourcestring sRaw = 'Raw'; sBoolean = 'Boolean'; sTransCount = 'Trans Count'; sPeriodCount = 'Period Count'; sPercent = 'Percent'; sCelsius = 'Celsius'; sFahrenheit = 'Fahrenheit'; sAngle = 'Angle'; sNone = 'None'; sSwitch = 'Switch'; sTemperature = 'Temperature'; sLight = 'Reflection'; sLightActiv = 'Light Active'; sLightInact = 'Light Inactive'; sSoundDB = 'Sound DB'; sSoundDBA = 'Sound DBA'; sCustom = 'Custom'; sLowspeed = 'Lowspeed'; sLowspeed9v = 'Lowspeed 9V'; sHighspeed = 'Highspeed'; sColorFull = 'Color Full'; sColorRed = 'Color Red'; sColorGreen = 'Color Green'; sColorBlue = 'Color Blue'; sColorNone = 'Color None'; sScoutSourceError = 'Scout only supports variable and constant sources'; sNonSpybotSrcError = 'Only Spybots support sources past Indirect'; // Diagnose unit resourcestring sRCXDead = 'Brick is NOT alive'; sRCXAlive = 'Brick is alive'; sVariable = 'Variable '; sWatch = 'Watch'; sInput1 = 'Input 1'; sInput2 = 'Input 2'; sInput3 = 'Input 3'; sOutputA = 'Output A'; sOutputB = 'Output B'; sOutputC = 'Output C'; sUserSelect = 'User Select'; sExceptions = 'Exceptions'; // EditCodeTemplate unit resourcestring sNewTemplate = 'New Code Template'; sEditTemplate = 'Edit Code Template'; // JoystickUnit unit resourcestring sDriveMotor = 'Drive Motor'; sSteerMotor = 'Steer Motor'; sLeftMotor = 'Left Motor'; sRightMotor = 'Right Motor'; // MemoryUnit unit resourcestring sDownloadMemMapFailed = 'Memory map download failed!'; sSubroutinePointers = 'Subroutine Pointers'; sTaskPointers = 'Task Pointers'; sSoundPointers = 'Sound Pointers'; sAnimationPointers = 'Animation Pointers'; sDataPointer = 'Data Pointer: '; sTopOfMemory = 'Top of Memory: '; sFreeMemLeft = 'Free Memory Left: '; sTotalUsed = 'Total Memory Used: '; sDatalogStart = 'Datalog Start Pointer: '; sDatalogCurrent = 'Datalog Current Pointer: '; // Transdlg unit resourcestring sColMacro = 'Cursor column in active editor'; sRowMacro = 'Cursor row in active editor'; sCurTokenMacro = 'Word at cursor in active editor'; sPathMacro = 'Directory portion of parameter'; sNameMacro = 'File name of parameter'; sNameOnlyMacro = 'File name of parameter without extension'; sExtMacro = 'File extension of parameter'; sEdNameMacro = 'Expanded file name of active editor'; sPromptMacro = 'Prompt for information'; sSaveMacro = 'Save file in active editor'; sSaveAllMacro = 'Save all modified files'; sPortMacro = 'Current port'; sTargetMacro = 'Current target'; // Transfer unit resourcestring sConfirm = 'Delete the item entitled %s?'; // uCmdLineUtils unit resourcestring UsageErrorMessage = 'Use "%s -help" for more information.'; VersionString = ' version '; BuiltString = ' built '; // uEEPROM unit resourcestring sEEPROMLoadError = 'Error loading EEPROM data'; sConfirmEEPROMWrite = 'Are you sure you want to write data to the brick?'; // uExplorerOptions unit resourcestring sHidden = 'Hidden'; sVisible = 'Visible'; sCollapsed = 'Collapsed'; sExpanded = 'Expanded'; // uMacroLib unit resourcestring sMacroLibFormatError = 'Invalid macro library format'; // uNewWatch unit resourcestring sWatchError = 'Cannot find the brick anymore'; // uNXTExplorer unit resourcestring sConfirmDel = 'Delete all the selected files?'; sConfirmDefrag = 'Defragment the NXT filesystem.'#13#10 + 'This operation attempts to a) upload all files from the NXT ' + 'to your computer, b) erase the NXT flash memory, and c) download ' + 'all the files back to the NXT. It is possible that the defragment ' + 'operation may not complete successfully and files may be lost.'#13#10 + 'Do you want to go ahead with the defragmentation operation?'; sConfirmErase = 'Erase all files on the NXT?'; sLowBattery = 'Battery level is too low to complete this operation'; sDefragError = 'Defragmentation failed!'; sDefragSuccess = 'Defragmentation complete!'; sTooBig = 'File size (%d) of "%s" is too large.'; sDownloadFailed = 'Download failed'; sExit = 'E&xit'; sNXTViewStyleMenu = 'NXT View Style'; sPCViewStyleMenu = 'PC View Style'; sAbout = '&About'; // uNXTImage unit resourcestring sBTResetConfirm = 'Are you sure you want to reset Bluetooth to factory defaults?'; sBootSAMBAConfirm = 'Are you sure you want to boot the NXT in SAMBA mode?'; sUtilitiesMenu = 'Utilities'; sSetNXTName = 'Set NXT Name'; sBootSAMBA = 'Boot NXT into SAMBA mode'; sResetBluetooth = 'Reset Bluetooth to factory defaults'; sRefreshRate = '&Refresh Rate'; sScale = 'Sca&le'; sDisplay = '&Display'; sNormal = '&Normal'; sPopup = '&Popup'; sPlayClicks = 'Play Clicks'; // uProjectManager unit resourcestring sRemoveConfirm = 'Remove the selected file(s) from the project?'; // uSetLNPAddress unit resourcestring sFailedToSetLNPAddr = 'Failed to set LNP address.'#13#10 + 'Check the current address setting.'; sSuccessfulSetLNPAddr = 'LNP Address successfully set to %d.'; // uWav2RsoCvt resourcestring sErrRiffWaveFmt = 'Error processing %s: wave file is not RIFF/WAVE format'; sErrPCMFmt = 'Error processing %s: wave files must be in PCM, MS ADPCM, or IMA ADPCM format'; sErr64kLimit = 'Error processing %s: wave file exceeds 64k maximum size'; sSuccess = 'Success: %s'; // common to multiple compilers resourcestring sException = 'Exception'; sProgramError = '%d errors during compilation'; sInvalidConstExpr = 'Invalid constant expression'; sUnmatchedCloseParen = 'Unmatched close parenthesis'; sParserError = 'parser error'; // uRPGComp resourcestring sNothingAfterEnd = 'Commands are not allowed after EndLoop or EndStop'; sUnknownCommand = 'Unknown RPG command'; sTooManyCommands = 'Too many RPG commands in program'; // uRICComp resourcestring sInvalidArgument = 'invalid argument: %d'; sInvalidVarMapIndex = 'invalid varmap index: %d'; sInvalidCommandArgument = 'Invalid command argument'; sSpriteLengthError = 'sprite command must have rows with a length > 0'; sInvalidMapSyntax = 'Invalid map element function syntax'; sInvalidPolygonSyntax = 'Invalid polygon point syntax'; sVarMapCountError = 'varmap command must have at least two map elements'; sPolygonCountError = 'polygon command must have at least three points'; sStringNotBinary = 'String is not a valid binary number: %s'; sInvalidHexLength = 'Invalid length of hex string: %d'; sUnableToFindImage = 'Unable to find image file "%s"'; sEllipseRequires127 = 'The ellipse command requires the enhanced NBC/NXC firmware, v1.27 or greater'; sPolygonRequires127 = 'The polygon command requires the enhanced NBC/NXC firmware, v1.27 or greater'; // uPreprocess unit resourcestring sInvalidPreprocDirective = 'Invalid preprocessor directive'; sImportRICNotFound = 'Unable to find RIC import file: "%s"'; sImportRICMissingQuotes = '#importric directive requires a filename (e.g., #importric "foo.ric")'; sImportRICInvalid = '#importric directive filename must end in ".ric"'; sDownloadNotFound = 'Unable to find download file: "%s"'; sDownloadMissingQuotes = '#download directive requires a filename (e.g., #download "foo.ric")'; sIncludeNotFound = 'Unable to find include file: "%s"'; sIncludeMissingQuotes = '#include directive requires a filename (e.g., #include "foo.h")'; sMacroMismatch = 'Preprocessor macro function does not match instance (%s)'; sUnmatchedDirective = 'Unmatched preprocessor directive'; sInvalidPreprocExpression = 'Invalid preprocessor expression : %s'; sInvalidCharConstant = 'Invalid char constant'; sMaxRecursionDepthError = 'Max recursion depth (%d) exceeded'; sIncludePath = 'Include path'; sSearchingForFile = 'Searching for file'; sFoundFile = 'Found file'; sProcessingDownload = 'Processing download'; sProcessingImport = 'Processing import'; sProcessingInclude = 'Processing include'; // uNXTClasses resourcestring sInvalidStatement = 'Unknown or invalid statement'; sInvalidLine = 'Line type "%s" is not valid while in the "%s" state'; sInvalidNumArgs = 'Invalid number of arguments: %d expected, %d found'; sInvalidNumArgsVar = 'Invalid number of arguments: at least %d expected, %d found'; sInvalidNumArgsOdd = 'Invalid number of arguments: argument count must be odd'; sInvalidCompareCode = 'Invalid comparison code: %s'; sBadConstExpression = 'Invalid constant expression: %s'; sConstOutOfRange = '%d is outside the valid range [%d,%d]'; sInvalidOpcode = 'Invalid opcode: %s'; sDuplicateLabel = 'Duplicate label (%s)'; sDuplicateDSEntry = 'Duplicate variable declaration (%s)'; sDuplicateType = 'Duplicate type declaration (%s)'; sInvalidVarDecl = 'Invalid variable declaration (%s)'; sInvalidVarArg = 'Invalid variable argument: %s'; sInvalidMutexArg = 'Invalid mutex argument: %s'; sInvalidClusterArg = 'Invalid struct argument: %s'; sInvalidArrayArg = 'Invalid array argument: %s'; sInvalidScalarArg = 'Invalid scalar argument: %s'; sInvalidStringArg = 'Invalid string argument: %s'; sInvalidLabelArg = 'Invalid label argument: %s'; sInvalidClumpArg = 'Invalid thread argument: %s'; sReturnNotInSub = 'The return opcode can only be used within a subroutine'; sNoReturnAtEndOfSub = 'The last operation in a subroutine must be a return'; sCompCheckFailed = 'compchk failed. %d is not %s %d.'; sCompCheckTypFailed = 'compchktype failed. %s is not %s.'; sInvalidCompCheck = 'invalid compchk operation'; sInvalidCompCheckTyp = 'invalid compchktype operation'; sUnsafeDivision = 'Dividing a signed number by an unsigned number is unsafe'; sUnusedVar = 'Unused variable: %s. Enable optimization with -Z1 to remove.'; sInvalidSetStatement = 'The set opcode cannot be used with float variables'; sMainUndefined = 'The main thread is not explicitly named'; sNoNegShifts = 'Negative shifts are not supported'; sNBCFinalizeDepends = 'Finalizing dependencies'; sNBCOptimizeLevel = 'Optimizing at level %d'; sNBCBuildRefs = 'Build codespace references'; sNBCOptMutexes = 'Optimize mutexes'; sNBCCompactCode = 'Compact the codespace'; sNBCRemoveLabels = 'Remove unused labels'; sNBCRunCodeOpts = 'Run codespace optimizations'; sNBCCompactAfterOpt = 'Compact the codespace after optimizations'; sNBCCompactData = 'Compact the dataspace'; sNBCSortDataspace = 'Sort the dataspace'; sNBCGenerateRawDS = 'Generate raw dataspace data'; sNBCFillCodeArrays = 'Fill clump and codespace arrays'; sNBCUpdateHeader = 'Update executable file header'; sNBCWriteHeader = 'Write file header to executable'; sNBCWriteDataspace = 'Write dataspace to executable'; sNBCWriteClumpData = 'Write clump data to executable'; sNBCWriteCodespace = 'Write code to executable'; sNBCWriteOptSource = 'Write optimized source to compiler output'; sNBCFinished = 'Finished'; sNBCCompFinished = 'Finished compiling NBC source code'; sNBCLoadSystemFiles = 'Loading NBC system files'; sNBCPreprocess = 'Running NBC Preprocessor'; sNBCCompilingSource = 'Compiling NBC source code'; sNBCOptClump = 'Optimizing clump: %s'; sNBCCompBegin = 'NBC compilation begins'; // uNXCComp unit resourcestring sTaskName = 'Task name'; sVariableName = 'Variable name'; sStringReturnValue = 'String return value'; sInvalidAssignment = 'Invalid assignment'; sDatatypesNotCompatible = 'Datatypes are not compatible'; sInlineInvalid = 'The inline keyword may only be used with functions'; sSafeCallInvalid = 'The safecall keyword may only be used with functions'; sBadPrototype = 'Prototypes without parameter names are not supported'; sMainMustBeTask = 'main must be a task'; sUDTNotEqual = 'User-defined types do not match'; sInvalidArrayDeclaration = 'Invalid array declaration'; sInvalidArrayInit = 'Invalid array or struct initialization'; sUnknownUDT = 'Unknown user-defined type'; sReturnInvalid = 'return is invalid outside a subroutine'; sInvalidBreakContinue = '%s is invalid outside of a loop'; sProtoAlreadyDefined = 'Prototype already defined - "begin"'; sNotValidForPrototype = 'Not valid for a prototype'; sMissingDataType = 'Missing Data Type'; sDataTypesAlreadyDefined = 'Data types already defined in prototype'; sParameterList = 'Parameter List'; sUnexpectedChar = 'Unexpected character encountered'; sValidProgBlock = 'Valid Program Block Statement'; sConstInitialization = 'constant initialization'; sInitNotAllowed = 'Initialization is not allowed for mutex variables'; sInvalidStringInit = 'Invalid string initialization'; sConstLocArrNotSupported = 'Constant local arrays are not supported'; sUnknownAPICommand = 'Unknown API command'; sDefaultInvalid = 'default is invalid outside a switch statement'; sCaseInvalid = 'case is invalid outside a switch statement'; sCaseDuplicateNotAllowed = 'duplicate case labels are not allowed'; sInvalidUseOfTaskName = 'Invalid use of task name'; sInvalidArrayExpr = 'Invalid array expression'; sRecursiveInlineError = 'Calling an inline function from an inline function is not supported'; sNestedCallsError = 'Nested calls to the same function are not supported.'; sRecursiveNotAllowed = 'Recursive function calls are not supported'; sExpNotSupported = 'Expressions are not supported for struct, array, or reference parameters'; sEnhancedFirmwareReqd = 'Enhanced firmware is required for this operation'; sSymbolTableFull = 'Symbol Table Full'; sInvalidArrayDim = 'Invalid array dimensions - must be from 1 to 4'; sAssignTaskError = 'Can not assign to a task or subroutine'; sArgMustBeTask = 'Argument must be a task'; sInvalidReturnType = 'Invalid return type'; sInvalidStringAssign = 'Invalid string assignment'; sInvalidArrayIndex = 'Invalid array index'; sFloatNotSupported = 'float types are not supported at the specified firmware version'; sNoUnsignedFloat = 'float types cannot be declared as unsigned'; sMainTaskNotFound = 'No task named "main" exists'; sNXCGenerateTrailer = 'NXC generate trailer'; sNXCProcessGlobals = 'NXC processing global declarations'; sNXCProcedure = 'NXC processing procedure block: %s'; sNXCFunction = 'NXC processing function block: %s'; sNXCCompBegin = 'NXC compilation begins'; sNXCPreprocess = 'Running NXC preprocessor'; sNXCInitProgram = 'NXC init program'; sNXCParseProg = 'NXC parse program code'; sNXCCodeGenComplete = 'NXC code generation finished'; sConstNotInline = 'Only inline functions can correctly use non-reference constant parameters'; sInvalidFuncDecl = 'Declaration syntax error'; sDefaultParamError = 'Invalid parameter syntax with default values'; sInvalidFunctionCall = 'Invalid function call'; sInvalidEnumDecl = 'Invalid enum declaration'; sUnknownDatatype = 'Unknown datatype'; sCompileTargets = 'Compiling for firmware version %d, NBC/NXC enhanced = %s'; sCurrentFile = 'Current file = "%s"'; sConstOrConstExpr = 'constant or constant expression'; sNotAnAPIFunc = '%s is not an API function'; sNotAnAPIStrFunc = '%s is not an API string function'; // uNBCCommon unit resourcestring sExpectedString = '%s expected'; sDataType = 'Data type'; sIdentifier = 'Identifier'; sDirective = 'Preprocessor directive'; sNumber = 'Number'; sHexNumber = 'Hex number'; sCharLiteral = 'Character literal'; sStringLiteral = 'String literal'; sStringType = 'string constant or variable of type string'; sByteArrayType = 'byte array type'; sStringVarType = 'string type'; sStructType = 'struct type'; sMutexType = 'mutex type'; sIntegerType = 'integer type'; sNumericType = 'numeric type'; sMathFactor = 'Math Factor'; sArrayOfString = 'array of string'; sArrayDatatype = 'array data type'; sUndefinedIdentifier = 'Undefined Identifier %s'; sDuplicateIdentifier = 'Duplicate Identifier %s'; sTooManyArgs = 'Too many arguments'; sTooFewArgs = 'Too few arguments'; sTooFewParams = 'Too few parameters'; sMaxParamCountExceeded = 'Max param count exceeded'; sConstNotAllowed = 'Constant not allowed on LHS of assignment'; sConstRequired = 'A constant is required in this context'; sFuncParamDeclMismatch = 'Function parameter declaration mismatch'; // nbc.dpr resourcestring UsageSyntax = 'Syntax: %s [options] filename [options]'; UsagePort = ' -S=: specify port name (usb), brick resource name, or alias'; UsageDownload = ' -d: download program'; UsageRunProg = ' -r: download and run program'; UsageBinary = ' -b: treat input file as a binary file (don''t compile it)'; UsageQuiet = ' -q: quiet'; UsageNoSystem = ' -n: prevent the system file from being included'; UsageDefine = ' -D=[=]: define macro '; UsageDecompile = ' -x: decompile program'; UsageOptimize = ' -Z[1|2]: turn on compiler optimizations'; UsageMaxErrors = ' -ER=n: set maximum errors before aborting (0 == no limit)'; UsageMaxDepth = ' -PD=n: set max preprocessor recursion depth (default == 10)'; UsageOutput = ' -O= : specify output file'; UsageErrors = ' -E= : write compiler messages to '; UsageIncludes = ' -I=: search for include files'; UsageNBCOutput = ' -nbc= : save NXC intermediate NBC code to '; UsageListing = ' -L= : generate code listing to '; UsageSymbols = ' -Y= : generate symbol table to '; UsageWarnings = ' -w[-|+] : warnings off or on (default is on)'; UsageStatusMsg = ' -sm[-|+] : status messages off or on (default is on)'; UsageEnhanced = ' -EF : enhanced firmware'; UsageSafecall = ' -safecall: NXC will wrap all function calls in Acquire/Release'; UsageAPI = ' -api: dump the API to stdout'; UsageFirmVer = ' -v=n: set the targeted firmware version (default == 128, NXT 1.1 == 105)'; UsageHelp = ' -help : display command line options'; // uEditorExperts.pas resourcestring SNoTokens = 'No tokens found to align on.'; sEECommentName = 'Comment Code'; sEEUncommentName = 'Uncomment Code'; sEEAlignName = 'Align Lines'; sEEPrevIdentName = 'Previous Identifier'; sEENextIdentName = 'Next Identifier'; sEEReverseName = 'Reverse Statement'; sEEGrepSearchName = 'Grep Search'; sEEGrepResultsName = 'Grep Results'; sEECommentHelp = ' This expert comments out a selected block of code. To ' + 'use it, select a block in the Delphi editor and activate this expert. ' + #13#10#13#10 + ' You can configure this expert to use different comment styles.'; sEEUncommentHelp = ' This expert uncomments a selected block of code. To ' + 'use it, select a block in the IDE code editor and activate this expert.' + #13#10 + ' Uncommenting is performed using the comment style that you selected for ' + 'the Comment Code editor expert.'; sEEAlignHelp = ' This expert aligns the text of the selected lines at ' + 'the first occurrence of a chosen token in each line. To use it, select a ' + 'block of code in the code editor and activate this expert. You may find ' + 'this feature useful to align the right hand side of variable, field, or ' + 'constant declarations and other similar lists. ' + #13#10 + ' There are two alignment modes. In the "Align at rightmost token" mode, ' + 'the rightmost token found in the selected text becomes the column position ' + 'the other lines are aligned to. In the "Align at first token" mode, the ' + 'first located token is used to determine the alignment column. In this ' + 'second mode, any line whose token prefix is longer than the position of ' + 'the first token will not be modified. ' + #13#10 + ' You can configure the list of tokens to align on as well as the minimum ' + 'number of space characters that must precede a token that is being aligned.'; sEEPrevIdentHelp = ' This expert detects the identifier under the cursor ' + 'and allows you to quickly jump to the previous occurrence of that ' + 'identifier in the same file.'; sEENextIdentHelp = ' This expert detects the identifier under the ' + 'cursor and allows you to quickly jump to the next occurrence of that ' + 'identifier in the same file.'; sEEReverseHelp = ' This expert reverses all assignment statements in ' + 'a selected block of code. It expects all reversible statements to be ' + 'contained on a single line.'; sEEGrepSearchHelp = 'Start a new grep search.'; sEEGrepResultsHelp = 'Show previous grep search results.'; // nextscreen.dpr resourcestring sUnableToConnect = 'Unable to connect to the selected NXT brick.'; // piano.pas resourcestring sPianoFilter = 'NQC Files (*.nqc,*.nqh)|*.nqc;*.nqh|' + 'MindScript files (*.rcx2;*.lsc)|*.rcx2;*.lsc|' + 'LASM Files (*.lasm)|*.lasm|' + 'C++ Files (*.c,*.cpp,*.h,*.hpp)|*.c;*.cpp;*.h;*.hpp|' + 'Pascal Files (*.pas,*.dpr,*.dpk,*.inc)|*.pas;*.dpr;*.dpk;*.inc|' + 'Forth Files (*.4th, *.f, *.fr, *.fth)|*.4th;*.f;*.fr;*.fth|' + 'Java Files (*.java)|*.java|' + 'Next Byte Code Files (*.nbc)|*.nbc|' + 'NXC Files (*.nxc)|*.nxc|' + 'NXT Melody Files (*.rmd)|*.rmd|'; // uportsedit.pas resourcestring sSaveNXTDatChanges = 'Save changes to nxt.dat file?'; // uNBCInterface.pas resourcestring sCannotFindFile = 'Unable to find the specified input file'#13#10'File "%s" ; line 1'; sNXCCompilationFailed = 'NXC compilation failed.'; sNBCCompilationFailed = 'NBC compilation failed.'; sVersionCheckFailed = 'Firmware version check failed.'; // uNXTWatchList resourcestring sConfirmDeleteAllWatches = 'Delete all watches?'; sWatchName = 'Watch Name'; sWatchValue = 'Value'; sNotYetImplemented = 'Not yet implemented'; implementation end. uNBCLexer.pas0000644000175000017500000005564411537752674012771 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNBCLexer; interface uses Classes, uGenLexer; type TNBCSimpleLexer = class(TGenLexer) protected procedure InitForLanguage(Lex: TGenLexer); override; end; TNBCLexer = class(TGenLexer) protected procedure InitForLanguage(Lex: TGenLexer); override; end; implementation uses SysUtils, mwGenericLex; { TNBCSimpleLexer } procedure TNBCSimpleLexer.InitForLanguage(Lex: TGenLexer); var Pat, OptPat: TAny; begin { Space} Pat := TAny.Create(nil); Pat.CharClass := [#1..#9, #11, #12, #14..#32]; Pat.Id := piSpace; Lex.Add(Pat); { LineEnd} Pat := TAny.Create(nil); Pat.Kind := pkLineEnd; Pat.Id := piLineEnd; Pat.Max := 1; Lex.Add(Pat); { Identifier} Pat := TIdentifier.Create(nil); Pat.CharClass := [#33..#126]; Lex.Add(Pat); { Symbol, Comment } Pat := TAny.Create(nil); Pat.Key := '//'; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '/'; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); OptPat := TTillLineEnd.Create(Pat); OptPat.Id := piComment; { Symbol, Comment } Pat := TAny.Create(nil); Pat.Key := ';'; Pat.Min := 1; Pat.Id := piComment; Lex.Add(Pat); OptPat := TTillLineEnd.Create(Pat); OptPat.Id := piComment; { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'subroutine'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'thread'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); end; { TNBCLexer } procedure TNBCLexer.InitForLanguage(Lex: TGenLexer); var Pat, OptPat, Temp: TAny; begin { Space} Pat := TAny.Create(nil); Pat.CharClass := [#1..#9, #11, #12, #14..#32]; Pat.Id := piSpace; Lex.Add(Pat); { LineEnd} Pat := TAny.Create(nil); Pat.Kind := pkLineEnd; Pat.Id := piLineEnd; Pat.Max := 1; Lex.Add(Pat); { Identifier} Pat := TIdentifier.Create(nil); Lex.Add(Pat); { String } Pat := TAny.Create(nil); Pat.Key := '"'; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.Key := '"'; Pat.Min := 1; Pat.Max := 1; Pat.Id := piString; Pat.Kind := pkTillKey; Temp:= Pat; Pat := TAny.Create(Pat); Pat.Key := '"'; Pat.Id := piBadString; Pat.Min := 1; Pat.Max := 1; Pat.Regress := True; Pat.ToRegress := Temp; { String } Pat := TAny.Create(nil); Pat.Key := ''''; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.Key := ''''; Pat.Min := 1; Pat.Max := 1; Pat.Id := piString; Pat.Kind := pkTillKey; Temp:= Pat; Pat := TAny.Create(Pat); Pat.Key := ''''; Pat.Id := piBadString; Pat.Min := 1; Pat.Max := 1; Pat.Regress := True; Pat.ToRegress := Temp; { Symbol, Comment } Pat := TAny.Create(nil); Pat.Key := '/*'; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '//'; OptPat.Id := piComment; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TTillLineEnd.Create(OptPat); OptPat.Id := piComment; OptPat := TAny.Create(nil); OptPat.Key := '/'; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); Pat := TAny.Create(Pat); Pat.Key := '*/'; Pat.Id := piComment; Pat.Kind := pkTillKey; Pat.MultiLine := True; { Symbol, Comment } Pat := TAny.Create(nil); Pat.Key := ';'; Pat.Min := 1; Pat.Id := piComment; Lex.Add(Pat); OptPat := TTillLineEnd.Create(Pat); OptPat.Id := piComment; { Number } Pat := TAny.Create(nil); Pat.CharClass := ['1'..'9']; Pat.Min := 1; Pat.Id := piNumber; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.CharClass := ['0'..'9']; Pat.Id := piNumber; { Number } Pat := TAny.Create(nil); Pat.Key := '0x'; Pat.Id := piNumber; Pat.Min := 1; Pat.Max := 2; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '0'; OptPat.Min := 1; OptPat.Id := piNumber; Pat.AddOption(OptPat); Pat := TAny.Create(Pat); Pat.CharClass := ['0'..'9', 'A'..'F', 'a'..'f']; Pat.Id := piNumber; { Symbol (VA_ARGS), Symbol (period)} Pat := TAny.Create(nil); Pat.Key:= '...'; Pat.Id:= piSymbol; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '.'; OptPat.Id:= piSymbol; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { Directive, Identifier} Pat := TAny.Create(nil); Pat.Key:= '#download'; Pat.Id:= piDirective; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '#include'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#define'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#ifndef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#import'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#pragma'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#endif'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#error'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#ifdef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#reset'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#undef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#elif'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#else'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#line'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#if'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); { OptPat := TAny.Create(nil); OptPat.Key := '##'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); } OptPat := TAny.Create(nil); OptPat.Key := '#'; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'arrsubset'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'arrbuild'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'arrtostr'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'acquire'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'arrinit'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'arrsize'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'abs'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'add'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'and'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'asl'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'asr'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'brcmp'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'brtst'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'byte'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'cmpset'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'call'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'cmnt'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'cmp'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'dword'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'div'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'db'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'dd'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'dw'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'exitto'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'ends'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'endt'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'exit'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'flatten'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'follows'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'fmtnum'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'gettick'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'getout'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'getin'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'index'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'jmp'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'long'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'lsl'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'lsr'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'mutex'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'mod'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'mov'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'mul'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'numtostr'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'neg'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'not'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'or'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'precedes'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'priority'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'release'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'replace'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'return'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'rotl'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'rotr'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'stopthread'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'subroutine'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'strsubset'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'strtoarr'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'strtonum'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'segment'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'subcall'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'syscall'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sdword'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'setout'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'strcat'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'struct'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'subret'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sbyte'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'setin'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'slong'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'start'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sword'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sign'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'stop'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'set'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sub'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'typedef'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'thread'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'tstset'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'tst'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'unflatten'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'udword'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'ubyte'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'ulong'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'uword'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'void'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'waitv'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'wait'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'word'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'xor'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); end; end. uNXCLexer.pas0000644000175000017500000004072611537752674013012 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uNXCLexer; interface uses Classes, uGenLexer; type TNXCLexer = class(TGenLexer) protected procedure InitForLanguage(Lex: TGenLexer); override; end; implementation uses SysUtils, mwGenericLex; { TNXCLexer } procedure TNXCLexer.InitForLanguage(Lex: TGenLexer); var Pat, OptPat, Temp: TAny; begin { Space} Pat := TAny.Create(nil); Pat.CharClass := [#1..#9, #11, #12, #14..#32]; Pat.Id := piSpace; Lex.Add(Pat); { LineEnd} Pat := TAny.Create(nil); Pat.Kind := pkLineEnd; Pat.Id := piLineEnd; Pat.Max := 1; Lex.Add(Pat); { Identifier} Pat := TIdentifier.Create(nil); Lex.Add(Pat); // TODO: need to try to add support for \" { String } Pat := TAny.Create(nil); Pat.Key := '"'; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.Key := '"'; Pat.Min := 1; Pat.Max := 1; Pat.Id := piString; Pat.Kind := pkTillKey; Temp:= Pat; Pat := TAny.Create(Pat); Pat.Key := '"'; Pat.Id := piBadString; Pat.Min := 1; Pat.Max := 1; Pat.Regress := True; Pat.ToRegress := Temp; // TODO: need to try to add support for \' { String } Pat := TAny.Create(nil); Pat.Key := ''''; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.Key := ''''; Pat.Min := 1; Pat.Max := 1; Pat.Id := piChar; Pat.Kind := pkTillKey; Temp:= Pat; Pat := TAny.Create(Pat); Pat.Key := ''''; Pat.Id := piBadString; Pat.Min := 1; Pat.Max := 1; Pat.Regress := True; Pat.ToRegress := Temp; { Symbol, Comment } Pat := TAny.Create(nil); Pat.Key := '/*'; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '//'; OptPat.Id := piComment; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TTillLineEnd.Create(OptPat); OptPat.Id := piComment; OptPat := TAny.Create(nil); // divided-by-equals symbol OptPat.Key := '/='; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '/'; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); Pat := TAny.Create(Pat); Pat.Key := '*/'; Pat.Id := piComment; Pat.Kind := pkTillKey; Pat.MultiLine := True; { Number } Pat := TAny.Create(nil); Pat.CharClass := ['1'..'9']; Pat.Min := 1; Pat.Id := piNumber; Lex.Add(Pat); Pat := TAny.Create(Pat); Pat.CharClass := ['0'..'9']; Pat.Id := piNumber; { Number } Pat := TAny.Create(nil); Pat.Key := '0x'; Pat.Id := piNumber; Pat.Min := 1; Pat.Max := 2; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '0'; OptPat.Min := 1; OptPat.Id := piNumber; Pat.AddOption(OptPat); Pat := TAny.Create(Pat); Pat.CharClass := ['0'..'9', 'A'..'F', 'a'..'f']; Pat.Id := piNumber; { Symbol } Pat := TAny.Create(nil); Pat.Key := '||='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '||'; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '|='; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '|'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '&&'; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '&='; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '&'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '!='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '!'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '*='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '*'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '<='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '<<'; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '<'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '>='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '>>'; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '>'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '=='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '='; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '+-='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '+='; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '++'; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '+'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol } Pat := TAny.Create(nil); Pat.Key := '-='; Pat.Min := 1; Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '--'; OptPat.Min := 1; Pat.AddOption(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '-'; OptPat.Min := 1; Pat.AddOption(OptPat); { Symbol (VA_ARGS), Symbol (period)} Pat := TAny.Create(nil); Pat.Key:= '...'; Pat.Id:= piSymbol; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '.'; OptPat.Id:= piSymbol; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { Directive, Identifier} Pat := TAny.Create(nil); Pat.Key:= '#download'; Pat.Id:= piDirective; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '#include'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#define'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#ifndef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#import'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#pragma'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#endif'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#error'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#ifdef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#reset'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#undef'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#elif'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#else'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#line'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#if'; OptPat.Id:= piDirective; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '#'; OptPat.Min := 1; OptPat.Id := piSymbol; Pat.AddOption(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= '__TMPBYTE__'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := '__TMPLONG__'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '__TMPWORD__'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '__RETURN__'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := '__RETVAL__'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'abs'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'asm'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'break'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'bool'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'byte'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'continue'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'const'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'case'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'char'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'default'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'do'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'else'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'false'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'for'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'goto'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'inline'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'int'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'if'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'long'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'mutex'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'priority'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'repeat'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'return'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'safecall'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'string'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'struct'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'switch'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'short'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'start'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sign'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'stop'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'sub'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'typedef'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); OptPat := TAny.Create(nil); OptPat.Key := 'task'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); OptPat := TAny.Create(nil); OptPat.Key := 'true'; OptPat.Id:= piKeyWord; OptPat.Min:= 1; Pat.AddOption(OptPat); TAlphaNumeric.Create(OptPat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'unsigned'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'void'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); { KeyWord, Identifier} Pat := TAny.Create(nil); Pat.Key:= 'while'; Pat.Id:= piKeyWord; Pat.Min:= 1; TAlphaNumeric.Create(Pat); Lex.Add(Pat); Pat.AddOption(TIdentifier.Create(nil)); end; end. uVersionInfo.pas0000644000175000017500000001447111537752674013621 0ustar slavkoslavko(* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is John Hansen. * Portions created by John Hansen are Copyright (C) 2009 John Hansen. * All Rights Reserved. * *) unit uVersionInfo; interface type TVersionAttributes = record PrivateBuild : Boolean; SpecialBuild : Boolean; PreRelease : Boolean; Debug : Boolean; InfoInferred : Boolean; Patched : Boolean; end; TVersionInfo = record CompanyName : String; FileDescription : String; FileVersion : String; InternalName : String; LegalCopyright : String; OriginalFileName : String; ProductName : String; ProductVersion : String; Comments : String; FileFlags : TVersionAttributes; end; function GetVersionInfo(const FileName: String): TVersionInfo; function GetProductVersion : string; var VerCompanyName : string = ''; VerFileDescription : string = ''; VerFileVersion : string = ''; VerInternalName : string = ''; VerLegalCopyright : string = ''; VerOriginalFileName : string = ''; VerProductName : string = ''; VerProductVersion : string = ''; VerComments : string = ''; implementation uses {$IFNDEF FPC} Windows, {$ENDIF} SysUtils; {$IFNDEF FPC} function GetProductVersion : string; var VI : TVersionInfo; begin VI := GetVersionInfo(ParamStr(0)); Result := VI.ProductVersion; end; function GetVersionInfo(const FileName: String): TVersionInfo; var PBlock : Pointer; BlockSize : Cardinal; Dummy : DWORD; Name : Array[0..1024] of Char; V : TVersionInfo; pTransTable: PLongint; sFileInfo: string; function VerValue(P: Pointer;Value: String): String; var Dummy : UINT; Buffer : Pointer; S : String; B : Array[0..1024] of Char; T : Array[0..1024] of Char; begin S := sFileInfo + Value ; StrPCopy(B,S); Buffer := @T[1] ; VerQueryValue(P,B,Buffer,Dummy); Result := StrPas(Buffer); end; function AnalyzeFlags(const AFileFlags : Integer) : TVersionAttributes; var sflag,dflag, pflag, rflag, vflag, iflag : integer; temp : TVersionAttributes; begin temp.SpecialBuild := False; temp.PrivateBuild := False; temp.PreRelease := False; temp.Debug := False; temp.InfoInferred := False; temp.Patched := False; // and returns type according to operand types sflag := AFileFlags and VS_FF_SPECIALBUILD; dflag := AFileFlags and VS_FF_DEBUG; rflag := AFileFlags and VS_FF_PRERELEASE; pflag := AFileFlags and VS_FF_PATCHED; vflag := AFileFlags and VS_FF_PRIVATEBUILD; iflag := AFileFlags and VS_FF_INFOINFERRED; if (sflag = VS_FF_SPECIALBUILD) then temp.SpecialBuild := True; if (dflag = VS_FF_DEBUG) then temp.Debug := True; if (rflag = VS_FF_PRERELEASE) then temp.PreRelease := True; if (pflag = VS_FF_PATCHED) then temp.Patched := True; if (vflag = VS_FF_PRIVATEBUILD) then temp.PrivateBuild := True; if (iflag = VS_FF_INFOINFERRED) then temp.InfoInferred := True; Result := temp; end; // get the fixed file attribute -FileFlags function VerFixedValue(P: Pointer): TVersionAttributes; var Dummy : UINT; Buffer : Pointer; sts : Boolean; S : String; B : Array[0..1024] of Char; T : Array[0..1024] of Char; Fl : DWord; V : PVSFixedFileInfo; begin S := '\'; StrPCopy(B,S); Buffer := @T[1] ; sts := VerQueryValue(P,B,Buffer,Dummy); if sts then begin V := Buffer; Fl := V.dwFileFlags; Result := AnalyzeFlags(Fl); end; end; begin StrPCopy(Name, FileName); BlockSize := GetFileVersionInfoSize(Name,Dummy); if BlockSize > 0 then begin GetMem(PBlock,2*BlockSize); try if GetFileVersionInfo(Name,Dummy,BlockSize,PBlock) then begin if VerQueryValue(PBlock, '\VarFileInfo\Translation', Pointer(pTransTable), BlockSize) then sFileInfo := Format('\StringFileInfo\%.4x%.4x\', [LoWord(pTransTable^), HiWord(pTransTable^)]) else sFileInfo := '\StringFileInfo\040904e4\'; V.CompanyName := VerValue(PBlock,'CompanyName'); V.FileDescription := VerValue(PBlock,'FileDescription'); V.FileVersion := VerValue(PBlock,'FileVersion'); V.InternalName := VerValue(PBlock,'InternalName'); V.LegalCopyright := VerValue(PBlock,'LegalCopyright'); V.OriginalFileName := VerValue(PBlock,'OriginalFileName'); V.ProductName := VerValue(PBlock,'ProductName'); V.ProductVersion := VerValue(PBlock,'ProductVersion'); V.Comments := VerValue(PBlock,'Comments'); V.FileFlags := VerFixedValue(PBlock); end; finally FreeMem(PBlock); end; end; Result := V ; end; {$ELSE} function VerFixedValue: TVersionAttributes; begin Result.PrivateBuild := False; Result.SpecialBuild := False; Result.PreRelease := False; Result.Debug := False; Result.InfoInferred := False; Result.Patched := False; end; function GetProductVersion : string; begin Result := VerProductVersion; end; function GetVersionInfo(const FileName: String): TVersionInfo; begin Result.CompanyName := VerCompanyName; Result.FileDescription := VerFileDescription; Result.FileVersion := VerFileVersion; Result.InternalName := VerInternalName; Result.LegalCopyright := VerLegalCopyright; Result.OriginalFileName := VerOriginalFileName; Result.ProductName := VerProductName; Result.ProductVersion := VerProductVersion; Result.Comments := VerComments; Result.FileFlags := VerFixedValue; if FileName = 'xyzzy' then Result.Comments := FileName; end; {$ENDIF} end.