unit uSpirit;

interface

uses
  rcx_constants, Classes;

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;

const
  MAX_COMPORT   = 8;
  MAX_USBPORT   = MAX_COMPORT+4;

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;

type
//  TBrickType = rtRCX..rtNXT;
  TDownloadStatusEvent = procedure(Sender : TObject; cur, total : Integer; var Abort : boolean) 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;

  EEPROMBlock = record
    Data : array[0..15] of Byte;
  end;

  TBrickComm = class
  public
    function  Open : boolean; 
    function  Close : boolean; 

    // PBrick sound commands
    function PlayTone(aFreq, aTime : word) : boolean; 
    function PlaySystemSound(aSnd : byte) : boolean; 

    // PBrick output control commands
    function MotorsOn(aMotorList : Byte) : boolean; 
    function MotorsOff(aMotorList : Byte) : boolean; 
    function MotorsFloat(aMotorList : Byte) : boolean; 
    function SetFwd(aMotorList : Byte) : boolean; 
    function SetRwd(aMotorList : Byte) : boolean; 
    function SwitchDirection(aMotorList : Byte) : boolean; 
    function SetMotorPower(aMotorList : Byte; aSrc, aNum : integer) : boolean; 

    // PBrick input control commands
    function SetSensorType(aNum, aType : integer) : boolean; 
    function SetSensorMode(aNum, aMode, aSlope : integer) : boolean; 
    function ClearSensorValue(aNum : integer) : boolean; 

    // general
    function TowerExists : boolean; 
    function Ping : boolean; 
    function PrepareBrick : boolean; 
    function UnlockFirmware : boolean; 
    function UnlockBrick : string; 
    function DownloadMemoryMap : TStrings; 
    function MonitorIR(aSeconds: integer): TStrings; 
    function PowerDownTime(aTime : integer) : boolean; 
    function BatteryLevel : integer; 
    function BrickAlive : boolean; 
    function Shutdown : boolean; 
    function Sleep(aVal : integer) : boolean; 
    function Version(var rom : Cardinal; var ram : Cardinal) : boolean; 
    function TransmitPower(aLevel : TTransmitLevel) : boolean; 

    function Poll(aSrc, aNum : integer) : integer; 
    function StartTask(aTask : integer) : boolean; 
    function StopTask(aTask : integer) : boolean; 
    function StopAllTasks : boolean; 
    function DeleteTask(aTask : integer) : boolean; 
    function DeleteAllTasks : boolean; 
    function DeleteSub(aSub : integer) : boolean; 
    function DeleteAllSubs : boolean; 
    function ClearTimer(aNum : integer) : boolean; 
    function ClearMemory : boolean; 

    function GetOutputStatus(aOut : integer) : integer; 
    function GetVariableValue(aVar: integer): integer; 
    function GetInputValue(aIn: integer): integer; 
    function GetMessageValue(aNum : integer) : integer; 
    function GetTimerValue(aNum : integer) : integer; 
    function GetCounterValue(aNum : integer) : integer; 

    // PBrick arithmetic/logical commands
    function SetVar(aVar, aSrc, aNum : integer) : boolean; 
    function SumVar(aVar, aSrc, aNum : integer) : boolean; 
    function SubVar(aVar, aSrc, aNum : integer) : boolean; 
    function DivVar(aVar, aSrc, aNum : integer) : boolean; 
    function MulVar(aVar, aSrc, aNum : integer) : boolean; 
    function SgnVar(aVar, aSrc, aNum : integer) : boolean; 
    function AbsVar(aVar, aSrc, aNum : integer) : boolean; 
    function AndVar(aVar, aSrc, aNum : integer) : boolean; 
    function OrVar(aVar, aSrc, aNum : integer) : boolean; 

    // communication to brick
    function SendRawCommand(aCmd : string; bRetry : boolean) : string; 
    function SendRemoteStr(aEvent : string; aRepeat : integer = 1) : boolean; 
    function SendRemote(aEvent : Word; aRepeat : integer = 1) : boolean; 
    function SendMessage(aMsg : integer) : boolean; 

    // RCX/2 only
    function SelectProgram(aProg : integer) : boolean; 
    function SelectDisplay(aSrc, aNumber : integer) : boolean; 
    function SetWatchHHMM(aHrs, aMins : integer) : boolean; 
    function SetWatch(aTime : string) : boolean; 
    function DownloadFirmware(aFile : string; bFast, bComp, bUnlock : boolean) : boolean; 
    function SetDatalog(aSize : integer) : boolean; 
    function DatalogNext(aSrc, aNum : integer) : boolean; 
    function UploadPartialDatalog(aFrom, aSize : integer) : TStrings; 
    function UploadDatalog(bVerbose : boolean) : TStrings; 

    // CM only methods
    function Drive(aLeft, aRight : integer) : boolean; 
    function ClearTachoCounter(aMotorList : Byte) : boolean; 
    function OnWait(aMotorList : Byte; aNum : integer; aTime : Byte) : boolean; 
    function OnWaitDifferent(aMotorList : Byte; aNum0, aNum1, aNum2 : integer; aTime : Byte) : boolean; 

    // Scout only methods
    function ScoutNum(aVal : integer) : boolean; 
    function Scout(bPower : boolean = true) : boolean; 
    function CalibrateLightSensor : boolean; 
    function SetFeedback(src, val : integer) : boolean; 
    function SetLightSensorUpperThreshold(src : TLSSource; val : TThresholdValue) : boolean; 
    function SetLightSensorLowerThreshold(src : TLSSource; val : TThresholdValue) : boolean; 
    function SetLightSensorHysteresis(src : TLSSource; val : TThresholdValue) : boolean; 
    function SetLightSensorBlinkTime(src : TLSSource; val : TBlinkTimeValue) : boolean; 
    function SetTimerLimit(num : TTimerNumber; src : TTCSource; val : integer) : boolean; 
    function SetCounterLimit(num : TCounterNumber; src : TTCSource; val : integer) : boolean; 
    function ScoutRules(motion : TScoutMotion; touch : TScoutTouch; 
      light : TScoutLight; time : TScoutScale; fx : TScoutEffects) : boolean; 
    function ScoutSound(bSoundEnable : boolean; bSoundOff : boolean; aNum : TSoundSetNumber) : boolean; 

    // Scout & Spybot only methods
    function SendVLL(aSrc, aNum : integer) : boolean; 
    function SetLight(bOn : boolean) : boolean; 

    // RCX2, Scout, & Spybot methods
    function PollMemory(address : Integer; size : Integer = 128) : TStrings; 
    function SetGlobalOutput(motors : TMotorsNum; action : TGlobalOutAction) : boolean; 
    function SetGlobalDirection(motors : TMotorsNum; action : TGlobalDirAction) : boolean; 
    function SetMaxPower(motors : TMotorsNum; src, num : integer) : boolean; 
    function IncCounter(num : TCounterNumber) : boolean; 
    function DecCounter(num : TCounterNumber) : boolean; 
    function ClearCounter(num : TCounterNumber) : boolean; 

    // RCX2 & spybot only methods
    function ClearSound : boolean; 
    function UnmuteSound : boolean; 
    function SendUARTData(start, size : integer) : boolean; 
    function SetEvent(enum, snum, etype : integer) : boolean; 
    function CalibrateEvent(enum, upper, lower, hysteresis : integer) : boolean; 
    function ClearAllEvents : boolean; 
    function SetSourceValue(aDestSrc, aDestVal, aOrigSrc: Byte; aOrigVal: Smallint): boolean; 

    // RCX2, Spy, & NXT
    function MuteSound : boolean; 

    // RCX2 only methods
    function ViewSourceValue(prec, src, value : integer) : boolean; 

    // Spybot only methods
    function PollEEPROM(block : Integer = -1) : TStrings; 

    // NXT only methods
    // NXT direct commands
    function StartProgram(const filename : string) : boolean; 
    function StopProgram : boolean; 
    function PlaySoundFile(const filename : string; bLoop : boolean) : boolean; 
    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; 
    function SetNXTOutputState(const port : byte; const power : integer;
      const mode, regmode : byte; const turnratio : integer;
      const runstate : byte; const tacholimit : cardinal) : boolean; 
    function GetNXTInputValues(const port : byte; var valid, calibrated : boolean;
      var stype, smode : byte; var raw, normalized : word;
      var scaled, calvalue : smallint) : boolean; 
    function SetNXTInputMode(const port, stype, smode : byte) : boolean; 
    function ResetInputScaledValue(const port : byte) : boolean; 
    function ResetOutputPosition(const port : byte; const Relative : boolean) : boolean; 
    function MessageWrite(const inbox : byte; const msg : string) : boolean; 
    function KeepAlive(var time : cardinal; const chkResponse : boolean = true) : boolean; 
    function LSGetStatus(port : byte; var bytesReady : byte) : boolean; 
    function GetCurrentProgramName(var name : string) : boolean; 
    function GetButtonState(const idx : byte; const reset : boolean;
      var pressed : boolean; var count : byte) : boolean; 
    function MessageRead(const remote, local : byte; const remove : boolean; var Msg : NXTMessage) : boolean; 
    // NXT system commands
    function NXTOpenRead(const filename : string; var handle : cardinal;
      var size : cardinal) : boolean; 
    function NXTOpenWrite(const filename : string; const size : cardinal;
      var handle : cardinal) : boolean; 
    function NXTRead(var handle : cardinal; var count : word;
      var buffer : NXTDataBuffer) : boolean; 
    function NXTWrite(var handle : cardinal; const buffer : NXTDataBuffer;
      var count : word; const chkResponse : boolean = false) : boolean; 
    function NXTCloseFile(var handle : cardinal; const chkResponse: boolean = false) : boolean; 
    function NXTDeleteFile(var filename : string; const chkResponse: boolean = false) : boolean; 
    function NXTFindFirstFile(var filename : string; var handle : cardinal; var filesize : cardinal) : boolean; 
    function NXTFindNextFile(var handle : cardinal; var filename : string; var filesize : cardinal) : boolean; 
    function NXTGetVersions(var protmin, protmaj, firmmin, firmmaj : byte) : boolean; 
    function NXTOpenWriteLinear(const filename : string; const size : cardinal;
      var handle : cardinal) : boolean; 
    function NXTOpenReadLinear(const filename : string; var handle : cardinal;
      var size : cardinal) : boolean; 
    function NXTOpenWriteData(const filename : string; const size : cardinal;
      var handle : cardinal) : boolean; 
    function NXTOpenAppendData(const filename : string; var size : cardinal;
      var handle : cardinal) : boolean; 
    function NXTCloseModuleHandle(var handle : cardinal; const chkResponse: boolean = false) : boolean; 
    function NXTBootCommand(const chkResponse: boolean = false) : boolean; 
    function NXTSetBrickName(const name : string; const chkResponse: boolean = false) : boolean; 
    function NXTGetBrickName : string;
    function NXTGetDeviceInfo(var name : string; BTAddress : PByte;
      var BTSignal : Cardinal; var memFree : Cardinal) : boolean; 
    function NXTFreeMemory : integer; 
    function NXTDeleteUserFlash(const chkResponse: boolean = false) : boolean; 
    function NXTBTFactoryReset(const chkResponse: boolean = false) : boolean; 
    function NXTPollCommandLen(const bufNum : byte; var count : byte) : boolean; 
    function NXTPollCommand(const bufNum : byte; var count : byte;
      var buffer : NXTDataBuffer) : boolean; 
    function NXTWriteIOMap(var ModID : Cardinal; const Offset : Word;
      var count : Word; const buffer : NXTDataBuffer; chkResponse : Boolean = False) : boolean; 
    function NXTReadIOMap(var ModID : Cardinal; const Offset : Word;
      var count : Word; var buffer : NXTDataBuffer) : boolean; 
    function NXTFindFirstModule(var ModName : string; var Handle : cardinal;
      var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; 
    function NXTFindNextModule(var Handle : cardinal; var ModName : string;
      var ModID, ModSize : Cardinal; var IOMapSize : Word) : boolean; 
    function NXTRenameFile(const old, new : string; const chkResponse: boolean = false) : boolean; 

    // wrapper functions
    function NXTDownloadFile(const filename : string; const filetype : TNXTFileType) : boolean; 
    function NXTDownloadStream(aStream : TStream; const dest : string; const filetype : TNXTFileType) : boolean; 
    function NXTUploadFile(const filename : string; const dir : string = '') : boolean; 
    function NXTListFiles(const searchPattern : string; Files : TStrings) : boolean; 
    function NXTListModules(const searchPattern : string; Modules : TStrings) : boolean; 
    function NXTListBricks(Bricks : TStrings) : boolean; 
    procedure NXTInitializeResourceNames; 
    function NXTDefragmentFlash : Boolean; virtual;

    // properties
    property  EEPROM[addr : Byte] : Byte;
    property  EEPROMBlock[idx : Integer] : EEPROMBlock;
    property  NXTLowSpeed[port : byte] : NXTLSBlock;
    property  IsOpen : boolean;
    property  FastMode : boolean;
    property  UseBluetooth : boolean;
    property  BluetoothName : string;
    property  BluetoothSearchTimeout : Cardinal;
    property  Quiet : Boolean;
    property  BrickType : byte;
    property  Port : string;
    property  PortName : string;
    property  NicePortName : string;
    property  FullPortName : string;
    property  BrickTypeName : string;
    property  RxTimeout : Word;
    property  VerboseMode : boolean;
    property  AutoClose : boolean;
    property  DataLog : TStrings;
    property  MemoryMap : TStrings;
    property  MemoryData : TStrings;
    property  TowerExistsSleep : Word;
    property  LinkLog : String;
    property  RCXFirmwareChunkSize : Integer;
    property  DownloadWaitTime : Integer;
    property  OmitHeader : Boolean;
    property  OnDownloadStart : TNotifyEvent;
    property  OnDownloadDone : TNotifyEvent;
    property  OnDownloadStatus : TDownloadStatusEvent;
    property  OnOpenStateChanged : TNotifyEvent;
  end;

function NameToNXTFileType(name : string) : TNXTFileType;
function MakeValidNXTFilename(const filename : string) : string;
function GetInitFilename: string;
function GetJoystickButtonScript(const i : byte; bPress : boolean) : string;
function FantomAPIAvailable : boolean;
procedure LoadNXTPorts(aStrings : TStrings);

implementation

end.