using System;
using System.Text;
namespace NKH.MindSqualls
{
///
/// Abstract class representing the NXT communication protocol.
///
///
/// The communication protocol for the NXT brick is specified in the documents:
///
/// Lego Mindstorms NXT,
/// Bluetooth Developer Kit,
/// Appendix 1: LEGO MINDSTORMS NXT Communication protocol
/// - and:
/// Appendix 2: LEGO MINDSTORMS NXT Direct commands
///
/// - which can be downloaded at:
/// http://mindstorms.lego.com/overview/NXTreme.aspx
///
/// A special thanks goes to Bram Fokke for his NXT# project:
/// http://nxtsharp.fokke.net/
///
/// Without his work, I doubt very much if my own work would have gotten off the ground. I have even st... ehem... borrowed a bit of his code here and there. However the major part of the code is my own.
///
public abstract class NxtCommunicationProtocol
{
///
/// Constructor.
///
public NxtCommunicationProtocol()
: base()
{ }
#region Communication.
///
/// Flag indicating if a reply should always be recieved.
///
public bool ReplyRequired = false;
///
/// Connect to the NXT brick.
///
public abstract void Connect();
///
/// Disconnect from the NXT brick.
///
public abstract void Disconnect();
///
/// Returns a boolean indicating if the NXT brick is connected.
///
public abstract bool IsConnected
{
get;
}
///
/// Send a request to the NXT brick, and return a reply.
///
/// The request to the NXT brick
/// The reply from the NXT brick, or null
protected abstract byte[] Send(byte[] request);
#endregion
#region Protocol.
///
/// STARTPROGRAM
///
///
/// Reference: BDK, Appendix 2, p. 5.
///
/// File name
public void StartProgram(string fileName)
{
ValidateFilename(fileName);
byte[] fileNameByteArr = Encoding.ASCII.GetBytes(fileName);
byte[] request = new byte[22];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.StartProgram;
fileNameByteArr.CopyTo(request, 2);
Send(request);
}
///
/// STOPPROGRAM
///
///
/// Reference: BDK, Appendix 2, p. 5.
///
public void StopProgram()
{
byte[] request = new byte[] {
(byte) (ReplyRequired ? 0x00 : 0x80),
(byte) NxtCommand.StopProgram
};
Send(request);
}
///
/// PLAYSOUNDFILE
///
///
/// Reference: BDK, Appendix 2, p. 5.
///
/// Loop sound file indefinately?
/// File name
public void PlaySoundfile(bool loop, string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[23];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.PlaySoundfile;
request[2] = (byte) (loop ? 0xFF : 0x00);
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 3);
Send(request);
}
///
/// PLAYTONE
///
///
/// Reference: BDK, Appendix 2, p. 6.
///
/// Frequency for the tone, Hz
/// Duration of the tone, ms
public void PlayTone(UInt16 frequency, UInt16 duration)
{
if (frequency < 200) frequency = 200;
if (frequency > 14000) frequency = 14000;
byte[] request = new byte[6];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.PlayTone;
Util.SetUInt16(frequency, request, 2);
Util.SetUInt16(duration, request, 4);
Send(request);
}
///
/// SETOUTPUTSTATE
///
///
/// Reference: BDK, Appendix 2, p. 6.
///
/// Motor port
/// Power set point
/// Mode
/// Regulation mode
/// Turn ratio
/// Run state
/// Tacho limit, 0: run forever
public void SetOutputState(NxtMotorPort motorPort, sbyte power, NxtMotorMode mode, NxtMotorRegulationMode regulationMode, sbyte turnRatio, NxtMotorRunState runState, UInt32 tachoLimit)
{
TraceUtil.MethodEnter();
if (power < -100) power = -100;
if (power > 100) power = 100;
if (turnRatio < -100) turnRatio = -100;
if (turnRatio > 100) turnRatio = 100;
byte[] request = new byte[12];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.SetOutputState;
request[2] = (byte) motorPort;
request[3] = (byte) power;
request[4] = (byte) mode;
request[5] = (byte) regulationMode;
request[6] = (byte) turnRatio;
request[7] = (byte) runState;
Util.SetUInt32(tachoLimit, request, 8);
Send(request);
TraceUtil.MethodExit(null);
}
///
/// SETINPUTMODE
///
///
/// Reference: BDK, Appendix 2, p. 7.
///
/// Input Port
/// Sensor Type
/// Sensor Mode
public void SetInputMode(NxtSensorPort sensorPort, NxtSensorType sensorType, NxtSensorMode sensorMode)
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
(byte) (ReplyRequired ? 0x00 : 0x80),
(byte) NxtCommand.SetInputMode,
(byte) sensorPort,
(byte) sensorType,
(byte) sensorMode
};
Send(request);
TraceUtil.MethodExit(null);
}
///
/// GETOUTPUTSTATE
///
///
/// Reference: BDK, Appendix 2, p. 8.
///
/// Ourput Port
/// Returns a parsed NxtGetOutputStateReply with the reply
public NxtGetOutputStateReply? GetOutputState(NxtMotorPort motorPort)
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.GetOutputState,
(byte) motorPort
};
byte[] reply = Send(request);
if (reply == null)
{
TraceUtil.MethodExit("return null");
return null;
}
byte motorPortOut = reply[3];
if (motorPortOut != (byte) motorPort)
{
TraceUtil.MethodExit("throw new NxtException");
throw new NxtException(string.Format("Output motor port, {0}, was different from input motor port, {1}.", motorPortOut, motorPort));
}
NxtGetOutputStateReply result;
result.power = (sbyte) reply[4];
result.mode = (NxtMotorMode) reply[5];
result.regulationMode = (NxtMotorRegulationMode) reply[6];
result.turnRatio = (sbyte) reply[7];
result.runState = (NxtMotorRunState) reply[8];
result.tachoLimit = Util.GetUInt32(reply, 9);
result.tachoCount = Util.GetInt32(reply, 13);
result.blockTachoCount = Util.GetInt32(reply, 17);
result.rotationCount = Util.GetInt32(reply, 21);
TraceUtil.MethodExit("return result");
return result;
}
///
/// GETINPUTVALUES
///
///
/// Reference: BDK, Appendix 2, p. 8.
/// Used with passive sensors like the Touch, Light and Sound sensors.
///
/// Input Port
/// Returns a NxtGetInputValues with the parsed reply
public NxtGetInputValuesReply? GetInputValues(NxtSensorPort sensorPort)
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.GetInputValues,
(byte) sensorPort
};
byte[] reply = Send(request);
if (reply == null)
{
TraceUtil.MethodExit("return null");
return null;
}
byte sensorPortOut = reply[3];
if (sensorPortOut != (byte) sensorPort)
{
TraceUtil.MethodExit("throw new NxtException");
throw new NxtException(string.Format("Output sensor port, {0}, was different from input sensor port, {1}.", sensorPortOut, sensorPort));
}
NxtGetInputValuesReply result;
result.valid = (reply[4] != 0x00);
result.calibrated = (reply[5] != 0x00);
result.sensorType = (NxtSensorType) reply[6];
result.sensorMode = (NxtSensorMode) reply[7];
result.rawAdValue = Util.GetUInt16(reply, 8);
result.normalizedAdValue = Util.GetUInt16(reply, 10);
result.scaledValue = Util.GetInt16(reply, 12);
result.calibratedValue = Util.GetInt16(reply, 14);
TraceUtil.MethodExit("return result");
return result;
}
///
/// RESETINPUTSCALEDVALUE
///
///
/// Reference: BDK, Appendix 2, p. 8.
///
/// Input Port
public void ResetInputScaledValue(NxtSensorPort sensorPort)
{
byte[] request = new byte[] {
(byte) (ReplyRequired ? 0x00 : 0x80),
(byte) NxtCommand.ResetInputScaledValue,
(byte) sensorPort
};
Send(request);
}
///
/// MESSAGEWRITE
///
///
/// Reference: BDK, Appendix 2, p. 9.
///
/// Inbox number
/// Message data
public void MessageWrite(NxtMailbox inBox, string messageData)
{
if (!messageData.EndsWith("\0"))
messageData += '\0';
byte messageSize = (byte) messageData.Length;
if (messageSize > 59)
throw new ArgumentException("Message may not exceed 59 characters.");
byte[] request = new byte[4 + messageSize];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.MessageWrite;
request[2] = (byte) inBox;
request[3] = messageSize;
Encoding.ASCII.GetBytes(messageData).CopyTo(request, 4);
Send(request);
}
///
/// RESETMOTORPOSITION
///
///
/// Reference: BDK, Appendix 2, p. 9.
///
/// Output port
/// Relative? True: position relative to last movement, False: absolute position
public void ResetMotorPosition(NxtMotorPort motorPort, bool relative)
{
byte[] request = new byte[] {
(byte) (ReplyRequired ? 0x00 : 0x80),
(byte) NxtCommand.ResetMotorPosition,
(byte) motorPort,
(byte) (relative ? 0xFF : 0x00)
};
Send(request);
}
///
/// GETBATTERYLEVEL
///
///
/// Reference: BDK, Appendix 2, p. 9.
///
/// Voltage in millivolts
public UInt16? GetBatteryLevel()
{
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.GetBatteryLevel
};
byte[] reply = Send(request);
if (reply == null) return null;
UInt16 voltage = Util.GetUInt16(reply, 3);
return voltage;
}
///
/// STOPSOUNDPLAYBACK
///
///
/// Reference: BDK, Appendix 2, p. 9.
///
public void StopSoundPlayback()
{
byte[] request = new byte[] {
(byte) (ReplyRequired ? 0x00 : 0x80),
(byte) NxtCommand.StopSoundPlayback
};
Send(request);
}
///
/// KEEPALIVE
///
///
/// Reference: BDK, Appendix 2, p. 10.
///
/// Current sleep time limit, ms
public UInt32? KeepAlive()
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.KeepAlive
};
byte[] reply = Send(request);
if (reply == null)
{
TraceUtil.MethodExit("return null");
return null;
}
UInt32 currentSleepLimit = Util.GetUInt32(reply, 3);
TraceUtil.MethodExit("return currentSleepLimit");
return currentSleepLimit;
}
///
/// LSGETSTATUS
///
///
/// Reference: BDK, Appendix 2, p. 10.
/// Returns the number of bytes ready in the LowSpeed port. Used with digital sensors like the Ultrasonic sensor.
///
/// Sensor port
/// Bytes Ready (count of available bytes to read)
///
///
public byte? LsGetStatus(NxtSensorPort sensorPort)
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.LsGetStatus,
(byte) sensorPort
};
byte[] reply = Send(request);
if (reply == null)
{
TraceUtil.MethodExit("return null");
return null;
}
byte bytesReady = reply[3];
TraceUtil.MethodExit("return bytesReady");
return bytesReady;
}
///
/// LSWRITE
///
///
/// Reference: BDK, Appendix 2, p. 10.
/// Writes data to the LowSpeed port. Used with digital sensors like the Ultrasonic sensor.
///
/// Sensor port
/// Rx Data Length
/// Tx Data
///
///
public void LsWrite(NxtSensorPort sensorPort, byte rxDataLength, byte[] txData)
{
TraceUtil.MethodEnter();
byte txDataLength = (byte) txData.Length;
if (txDataLength == 0)
{
TraceUtil.MethodExit("throw new ArgumentException - 1");
throw new ArgumentException("No data to send.");
}
if (txDataLength > 16)
{
TraceUtil.MethodExit("throw new ArgumentException - 2");
throw new ArgumentException("Tx data may not exceed 16 bytes.");
}
if (rxDataLength < 0 || 16 < rxDataLength)
{
TraceUtil.MethodExit("throw new ArgumentException - 3");
throw new ArgumentException("Rx data length should be in the interval 0-16.");
}
byte[] request = new byte[5 + txDataLength];
request[0] = (byte) (ReplyRequired ? 0x00 : 0x80);
request[1] = (byte) NxtCommand.LsWrite;
request[2] = (byte) sensorPort;
request[3] = txDataLength;
request[4] = rxDataLength;
txData.CopyTo(request, 5);
Send(request);
TraceUtil.MethodExit(null);
}
///
/// LSREAD
///
///
/// Reference: BDK, Appendix 2, p. 10.
/// Reads data from the LowSpeed port. Used with digital sensors like the Ultrasonic sensor.
///
/// The sensor port
/// The data read from the port
///
///
public byte[] LsRead(NxtSensorPort sensorPort)
{
TraceUtil.MethodEnter();
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.LsRead,
(byte) sensorPort
};
byte[] reply = Send(request);
if (reply == null)
{
TraceUtil.MethodExit("return null");
return null;
}
byte bytesRead = reply[3];
byte[] rxData = new byte[bytesRead];
Array.Copy(reply, 4, rxData, 0, bytesRead);
TraceUtil.MethodExit("return rxData");
return rxData;
}
///
/// GETCURRENTPROGRAMNAME
///
///
/// Reference: BDK, Appendix 2, p. 11.
///
/// File name of the running program
public string GetCurrentProgramName()
{
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.GetCurrentProgramName
};
byte[] reply = Send(request);
if (reply == null) return null;
string fileName = Encoding.ASCII.GetString(reply, 3, 20).TrimEnd('\0');
return fileName;
}
///
/// MESSAGEREAD
///
///
/// Reference: BDK, Appendix 2, p. 11.
///
/// Remote Inbox number
/// Local Inbox number
/// Remove? True: clears message from Remote Inbox
/// Message data
public string MessageRead(NxtMailbox2 remoteInboxNo, NxtMailbox localInboxNo, bool remove)
{
byte[] request = new byte[] {
0x00,
(byte) NxtCommand.MessageRead,
(byte) remoteInboxNo,
(byte) localInboxNo,
(byte) (remove ? 0xFF : 0x00)
};
byte[] reply = Send(request);
if (reply == null) return null;
byte localInboxNoOut = reply[3]; // TODO: Validate on this?
byte messageSize = reply[4];
string message = Encoding.ASCII.GetString(reply, 5, messageSize).TrimEnd('\0');
return message;
}
///
/// OPEN READ COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 7.
/// Close the handle after use. The handle is automatically closed if an error occurs.
///
/// The name of the file
/// A NxtOpenReadReply with the result of the request
public NxtOpenReadReply? OpenRead(string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenRead;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
byte[] reply = Send(request);
if (reply == null) return null;
NxtOpenReadReply result;
result.handle = reply[3];
result.fileSize = Util.GetUInt32(reply, 4);
return result;
}
///
/// OPEN WRITE COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 7.
/// Close the handle after use. The handle is automatically closed if an error occurs.
///
/// The file name
/// The file size
/// A handle to the file
public byte? OpenWrite(string fileName, UInt32 fileSize)
{
ValidateFilename(fileName);
byte[] request = new byte[26];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenWrite;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
Util.SetUInt32(fileSize, request, 22);
byte[] reply = Send(request);
if (reply == null) return null;
return reply[3];
}
///
/// READ COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 8.
///
/// A handle to the file
/// Number of data bytes to be read
/// A byte array with the read data
public byte[] Read(byte handle, UInt16 bytesToRead)
{
byte[] request = new byte[5];
request[0] = 0x01;
request[1] = (byte) NxtCommand.Read;
request[2] = handle;
Util.SetUInt16(bytesToRead, request, 3);
byte[] reply = Send(request);
if (reply == null) return null;
byte handleOut = reply[3];
if (handleOut != handle)
throw new NxtException(string.Format("Output handle, {0}, was different from input handle, {1}.", handleOut, handle));
UInt16 bytesRead = Util.GetUInt16(reply, 4);
byte[] respons = new byte[bytesRead];
Array.Copy(reply, 6, respons, 0, bytesRead);
return respons;
}
///
/// WRITE COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 8.
///
/// File handle to write to
/// Data to write
/// Number of bytes written
public UInt16? Write(byte handle, byte[] data)
{
byte[] request = new byte[3 + data.Length];
request[0] = 0x01;
request[1] = (byte) NxtCommand.Write;
request[2] = handle;
data.CopyTo(request, 3);
byte[] reply = Send(request);
if (reply == null) return null;
byte handleOut = reply[3];
if (handleOut != handle)
throw new NxtException(string.Format("Output handle, {0}, was different from input handle, {1}.", handleOut, handle));
UInt16 bytesWritten = Util.GetUInt16(reply, 4);
return bytesWritten;
}
///
/// CLOSE COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 8.
///
/// File handle to close
public void Close(byte handle)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.Close,
handle
};
byte[] reply = Send(request);
if (reply == null) return;
byte handleOut = reply[3];
if (handleOut != handle)
throw new NxtException(string.Format("Output handle, {0}, was different from input handle, {1}.", handleOut, handle));
}
///
/// DELETE COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 9.
///
/// The file name
public void Delete(string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.Delete;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
byte[] reply = Send(request);
if (reply == null) return;
string fileNameOut = Encoding.ASCII.GetString(reply, 3, 20);
if (fileNameOut != fileName)
throw new NxtException(string.Format("The file reported as deleted, '{0}', was different from the file requested, '{1}'.", fileNameOut, fileName));
}
///
/// FIND FIRST
///
///
/// Reference: BDK, Appendix 1, p. 9.
/// Close the handle after use. The handle is automatically closed if an error occurs.
///
/// Filename or -mask to search
/// A NxtFindFileReply containing the result for the search
///
public NxtFindFileReply? FindFirst(string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.FindFirst;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
return SendAndParseNxtFindFileReply(request);
}
///
/// FIND NEXT
///
///
/// Reference: BDK, Appendix 1, p. 10.
/// Close the handle after use. The handle is automatically closed if an error occurs.
///
/// Handle from the previous found file or from the FindFirst command
/// A NxtFindFileReply containing the result for the search
///
public NxtFindFileReply? FindNext(byte handle)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.FindNext,
handle
};
return SendAndParseNxtFindFileReply(request);
}
///
/// Sends a FindFirst- or FindNext-request and parses the result as a NxtFindFileReply.
///
/// The request
/// A NxtFindFileReply containing the parsed result
///
///
private NxtFindFileReply? SendAndParseNxtFindFileReply(byte[] request)
{
byte[] reply;
NxtFindFileReply result;
try
{
reply = Send(request);
if (reply == null) return null;
}
catch (NxtCommunicationProtocolException ex)
{
if (ex.errorMessage == NxtErrorMessage.FileNotFound)
{
result.FileFound = false;
result.handle = 0;
result.fileName = "";
result.fileSize = 0;
return result;
}
// Rethrow if not a FileNotFound error.
throw;
}
result.FileFound = true;
result.handle = reply[3];
result.fileName = Encoding.ASCII.GetString(reply, 4, 20).TrimEnd('\0');
result.fileSize = Util.GetUInt32(reply, 24);
return result;
}
///
/// GET FIRMWARE VERSION
///
///
/// Reference: BDK, Appendix 1, p. 11.
///
/// A NxtGetFirmwareVersionReply with the protocol-, and the firmware versions.
public NxtGetFirmwareVersionReply? GetFirmwareVersion()
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.GetFirmwareVersion
};
byte[] reply = Send(request);
if (reply == null) return null;
NxtGetFirmwareVersionReply result;
result.protocolVersion = new Version(reply[4], reply[3]);
result.firmwareVersion = new Version(reply[6], reply[5]);
return result;
}
///
/// OPEN WRITE LINEAR COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 11.
///
/// The file name
/// The file size
/// A handle to the file
public byte? OpenWriteLinear(string fileName, UInt32 fileSize)
{
ValidateFilename(fileName);
byte[] request = new byte[26];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenWriteLinear;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2); // NOTE: I'm not sure if the documentation is 100%
Util.SetUInt32(fileSize, request, 22); // ... correct here, since it do not allow space for the null terminator.
byte[] reply = Send(request);
if (reply == null) return null;
byte handle = reply[3];
return handle;
}
///
/// OPEN READ LINEAR COMMAND (INTERNAL COMMAND)
///
///
/// Reference: BDK, Appendix 1, p. 12.
///
/// The file name
/// Pointer to linear memory segment
public UInt32? OpenReadLinear(string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenReadLinear;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
byte[] reply = Send(request);
if (reply == null) return null;
UInt32 pointer = Util.GetUInt32(reply, 3);
return pointer;
}
///
/// OPEN WRITE DATA COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 12.
///
/// The file name
/// The file size
/// A handle to the file
public byte? OpenWriteData(string fileName, UInt32 fileSize)
{
ValidateFilename(fileName);
byte[] request = new byte[26];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenWriteData;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2); // NOTE: I'm not sure if the documentation is 100%
Util.SetUInt32(fileSize, request, 22); // ... correct here, since it do not allow space for the null terminator.
byte[] reply = Send(request);
if (reply == null) return null;
byte handle = reply[3];
return handle;
}
///
/// OPEN APPEND DATA COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 13.
///
/// The file name
/// A NxtOpenAppendDataReply withe the parsed reply
public NxtOpenAppendDataReply? OpenAppendData(string fileName)
{
ValidateFilename(fileName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.OpenAppendData;
Encoding.ASCII.GetBytes(fileName).CopyTo(request, 2);
byte[] reply = Send(request);
if (reply == null) return null;
NxtOpenAppendDataReply result;
result.handle = reply[3];
result.availableFilesize = Util.GetUInt32(reply, 4);
return result;
}
///
/// REQUEST FIRST MODULE
///
///
/// Reference: BDK, Appendix 1, p. 19.
///
/// Modulename or -mask to search
/// A NxtRequestModuleReply containing the result for the search
///
///
public NxtRequestModuleReply? RequestFirstModule(string resourceName)
{
ValidateFilename(resourceName);
byte[] request = new byte[22];
request[0] = 0x01;
request[1] = (byte) NxtCommand.RequestFirstModule;
Encoding.ASCII.GetBytes(resourceName).CopyTo(request, 2);
return SendAndParseNxtRequestModuleReply(request);
}
///
/// REQUEST NEXT MODULE
///
///
/// Reference: BDK, Appendix 1, p. 19.
///
/// Handle number from the previous Request Next Module command or from the very first Request First Module command
/// A NxtRequestModuleReply containing the result for the search
///
///
public NxtRequestModuleReply? RequestNextModule(byte handle)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.RequestNextModule,
handle
};
return SendAndParseNxtRequestModuleReply(request);
}
///
/// Sends a RequestFirstModule- or RequestNextModule-request and parses the result as a NxtRequestModule.
///
/// The request
/// A NxtRequestModuleReply containing the parsed result
///
///
private NxtRequestModuleReply? SendAndParseNxtRequestModuleReply(byte[] request)
{
byte[] reply;
NxtRequestModuleReply result;
try
{
reply = Send(request);
if (reply == null) return null;
}
catch (NxtCommunicationProtocolException ex)
{
if (ex.errorMessage == NxtErrorMessage.NoMoreHandles || ex.errorMessage == NxtErrorMessage.ModuleNotFound)
{
result.ModuleFound = false;
result.handle = 0;
result.moduleName = "";
result.moduleId = 0;
result.moduleIdCC = 0;
result.moduleIdFF = 0;
result.moduleIdPP = 0;
result.moduleIdTT = 0;
result.moduleSize = 0;
result.moduleIoMapSize = 0;
return result;
}
// Rethrow if not a NoMoreHandles- or a ModuleNotFound error.
throw;
}
result.ModuleFound = true;
result.handle = reply[3];
result.moduleName = Encoding.ASCII.GetString(reply, 4, 20).TrimEnd('\0');
result.moduleId = Util.GetUInt32(reply, 24);
// NOTE: There seems to be some inconsistency in the documentation about PP TT CC FF, Appendix 1, p. 18.
result.moduleIdFF = 0; // reply[24];
result.moduleIdCC = 0; // reply[25];
result.moduleIdTT = reply[26]; // reply[26];
result.moduleIdPP = reply[24]; // reply[27]
result.moduleSize = Util.GetUInt32(reply, 28);
result.moduleIoMapSize = Util.GetUInt16(reply, 32);
return result;
}
///
/// CLOSE MODULE HANDLE COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 20.
///
/// Handle number
///
///
public void CloseModuleHandle(byte handle)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.CloseModuleHandle,
handle
};
Send(request);
}
///
/// READ IO MAP COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 20.
///
/// The module ID
/// The offset to read from
/// Number of bytes to be read
/// IO-map content
public byte[] ReadIoMap(UInt32 moduleId, UInt16 offset, UInt16 bytesToRead)
{
byte[] request = new byte[10];
request[0] = 0x01;
request[1] = (byte) NxtCommand.ReadIoMap;
Util.SetUInt32(moduleId, request, 2);
Util.SetUInt16(offset, request, 6);
Util.SetUInt16(bytesToRead, request, 8);
byte[] reply = Send(request);
if (reply == null) return null;
UInt32 moduleIdOut = Util.GetUInt32(reply, 3);
if (moduleIdOut != moduleId)
throw new NxtException(string.Format("Output module Id, {0}, was different from input module Id, {1}.", moduleIdOut, moduleId));
UInt16 bytesRead = Util.GetUInt16(reply, 7);
byte[] ioMapContent = new byte[bytesRead];
Array.Copy(reply, 9, ioMapContent, 0, bytesRead);
return ioMapContent;
}
///
/// WRITE IO MAP COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 21.
///
/// The module ID
/// The offset to write to
/// IO-map content to be stored in IO-map[index]...IO-map[index+N]
/// The number of data that have been written
public UInt16? WriteIoMap(UInt32 moduleId, UInt16 offset, byte[] ioMapContent)
{
UInt16 bytesToWrite = (UInt16) ioMapContent.Length;
byte[] request = new byte[10 + ioMapContent.Length];
request[0] = 0x01;
request[1] = (byte) NxtCommand.WriteIoMap;
Util.SetUInt32(moduleId, request, 2);
Util.SetUInt16(offset, request, 6);
Util.SetUInt16(bytesToWrite, request, 8);
ioMapContent.CopyTo(request, 10);
byte[] reply = Send(request);
if (reply == null) return null;
UInt32 moduleIdOut = Util.GetUInt32(reply, 3);
if (moduleIdOut != moduleId)
throw new NxtException(string.Format("Output module Id, {0}, was different from input module Id, {1}.", moduleIdOut, moduleId));
UInt16 bytesWritten = Util.GetUInt16(reply, 7);
return bytesWritten;
}
///
/// BOOT COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 13.
/// This command can only be accepted by USB.
///
public void Boot()
{
byte[] request = new byte[21];
request[0] = 0x01;
request[1] = (byte) NxtCommand.Boot;
Encoding.ASCII.GetBytes("Let's dance: SAMBA").CopyTo(request, 2);
byte[] reply = Send(request);
if (reply == null) return;
string result = Encoding.ASCII.GetString(reply, 3, 4).TrimEnd('\0');
if (result != "Yes")
throw new NxtException("The reply, '{0}', was not the expected, 'Yes'.");
}
///
/// SET BRICK NAME COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 13.
/// For some reason only the first 8 characters is remembered when the NXT is turned off. This is with version 1.4 of the firmware, and it may be fixed with newer versions.
///
/// The new name of the NXT brick
public void SetBrickName(string brickName)
{
if (brickName.Length > 15)
brickName = brickName.Substring(0, 15);
byte[] request = new byte[18];
request[0] = 0x01;
request[1] = (byte) NxtCommand.SetBrickName;
Encoding.ASCII.GetBytes(brickName).CopyTo(request, 2);
Send(request);
}
///
/// GET DEVICE INFO
///
///
/// Reference: BDK, Appendix 1, p. 14.
/// For some reason only the first 8 characters of the BXT name is remembered when the NXT is turned off. This is with version 1.4 of the firmware, and it may be fixed with newer versions.
///
/// A NxtGetDeviceInfoReply containing the parsed result
public NxtGetDeviceInfoReply? GetDeviceInfo()
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.GetDeviceInfo
};
byte[] reply = Send(request);
if (reply == null) return null;
NxtGetDeviceInfoReply result;
result.nxtName = Encoding.ASCII.GetString(reply, 3, 15).TrimEnd('\0');
result.btAdress = new byte[7];
Array.Copy(reply, 18, result.btAdress, 0, 7);
result.bluetoothSignalStrength = Util.GetUInt32(reply, 25);
result.freeUserFlash = Util.GetUInt32(reply, 29);
return result;
}
///
/// DELETE USER FLASH
///
///
/// Reference: BDK, Appendix 1, p. 14.
///
public void DeleteUserFlash()
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.DeleteUserFlash
};
Send(request);
}
///
/// POLL COMMAND LENGTH
///
///
/// Reference: BDK, Appendix 1, p. 15.
///
/// Buffer Number: 0x00 = Poll Buffer, 0x01 = High Speed buffer
/// Number of bytes for the command ready in the buffer
public byte? PollCommandLength(byte bufferNo)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.PollCommandLength,
bufferNo
};
byte[] reply = Send(request);
if (reply == null) return null;
// NOTE: My guess is that the documentation has switched meaning between bytes 2 and 3.
byte bufferNoOut = reply[3];
if (bufferNoOut != bufferNo)
throw new NxtException(string.Format("Output buffer no-, {0}, was different from input buffer no., {1}.", bufferNoOut, bufferNo));
byte bytesReady = reply[4];
return bytesReady;
}
///
/// POLL COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 15.
///
/// Buffer Number: 0x00 = Poll Buffer, 0x01 = High Speed buffer
/// Command length
public void PollCommand(byte bufferNo, byte commandLength)
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.PollCommand,
bufferNo,
commandLength
};
byte[] reply = Send(request);
if (reply == null) return;
// NOTE: My guess is that the documentathion has switched meaning between bytes 2 and 3.
byte bufferNoOut = reply[3];
if (bufferNoOut != bufferNo)
throw new NxtException(string.Format("Output buffer no-, {0}, was different from input buffer no., {1}.", bufferNoOut, bufferNo));
// TODO: Parse the reply, and return the result.
}
///
/// BLUETOOTH FACTORY RESET COMMAND
///
///
/// Reference: BDK, Appendix 1, p. 15.
/// This command cannot be transmitted via Bluetooth because all Bluetooth functionality is reset by this command!
///
public void BluetoothFactoryReset()
{
byte[] request = new byte[] {
0x01,
(byte) NxtCommand.BluetoothFactoryReset
};
Send(request);
}
#endregion
#region Utilities.
///
/// This function validates that the filename is correct for the NXT brick.
///
/// The file name
private void ValidateFilename(string fileName)
{
if (fileName.Length > 19)
throw new ArgumentException("File name is to long. Maximum length is 19 characters (15.3).");
}
#endregion
}
#region Reply types.
///
/// Reply type for the FindFirst() and FindNext() functions.
///
///
///
public struct NxtFindFileReply
{
///
/// Boolean indicating if a file was found or not.
///
public bool FileFound;
///
/// The file handle.
///
public byte handle;
///
/// The file name.
///
public string fileName;
///
/// The filesize.
///
public UInt32 fileSize;
}
///
/// Reply type for the FindFirst() and FindNext() functions.
///
///
///
public struct CopyOfNxtFindFileReply
{
///
/// Boolean indicating if a file was found or not.
///
public bool FileFound;
///
/// The file handle.
///
public byte handle;
///
/// The file name.
///
public string fileName;
///
/// The filesize.
///
public UInt32 fileSize;
}
///
/// Reply type for the GetDeviceInfo() function.
///
///
public struct NxtGetDeviceInfoReply
{
///
/// The name of the NXT brick.
///
public string nxtName;
///
/// The bluetooth address.
///
public byte[] btAdress;
///
/// The bluetooth signal strength.
///
public UInt32 bluetoothSignalStrength;
///
/// The size of the free user flash.
///
public UInt32 freeUserFlash;
}
///
/// Reply type for the GetFirmwareVersion() function.
///
///
public struct NxtGetFirmwareVersionReply
{
///
/// The protocol version.
///
public Version protocolVersion;
///
/// The firmware version.
///
public Version firmwareVersion;
}
///
/// Reply type for the GetInputValues() function.
///
///
public struct NxtGetInputValuesReply
{
///
/// A boolean indicating if the returned result is valid or not.
///
public bool valid;
///
/// A boolean indicating if the returned result is calibrated or not.
///
public bool calibrated;
///
/// The sensor type.
///
public NxtSensorType sensorType;
///
/// The sensor mode.
///
public NxtSensorMode sensorMode;
///
/// The raw A/D value.
///
public UInt16 rawAdValue;
///
/// The normalized A/D value.
///
public UInt16 normalizedAdValue;
///
/// The scaled value.
///
public Int16 scaledValue;
///
/// The calibrated value.
///
public Int16 calibratedValue;
}
///
/// Reply type for the GetOutputState() function.
///
///
public struct CopyOfNxtGetOutputStateReply
{
///
/// The motor power.
///
public sbyte power;
///
/// The motor mode.
///
public NxtMotorMode mode;
///
/// The regulation mode.
///
public NxtMotorRegulationMode regulationMode;
///
/// The turn ratio.
///
public sbyte turnRatio;
///
/// The run state.
///
public NxtMotorRunState runState;
///
/// The tacho limit in degrees, 0 means unlimited.
///
public UInt32 tachoLimit;
///
/// The tacho count.
///
public Int32 tachoCount;
///
/// The block tacho count.
///
public Int32 blockTachoCount;
///
/// The rotation count.
///
public Int32 rotationCount;
///
/// ToString()-override.
///
/// ... TBD ...
public override string ToString()
{
return string.Format("[P:{0,4}|M:{1,25}|RM:{2,27}|TR:{3,4}|RS:{4,24}|TL:{5,3}|TC:{6,4}|BTC:{7,4}|RC:{8,4}]",
power,
mode,
regulationMode,
turnRatio,
runState,
tachoLimit,
tachoCount,
blockTachoCount,
rotationCount);
}
}
///
/// Reply type for the GetOutputState() function.
///
///
public struct NxtGetOutputStateReply
{
///
/// The motor power.
///
public sbyte power;
///
/// The motor mode.
///
public NxtMotorMode mode;
///
/// The regulation mode.
///
public NxtMotorRegulationMode regulationMode;
///
/// The turn ratio.
///
public sbyte turnRatio;
///
/// The run state.
///
public NxtMotorRunState runState;
///
/// The tacho limit in degrees, 0 means unlimited.
///
public UInt32 tachoLimit;
///
/// The tacho count.
///
public Int32 tachoCount;
///
/// The block tacho count.
///
public Int32 blockTachoCount;
///
/// The rotation count.
///
public Int32 rotationCount;
///
/// ToString()-override.
///
/// ... TBD ...
public override string ToString()
{
return string.Format("[P:{0,4}|M:{1,25}|RM:{2,27}|TR:{3,4}|RS:{4,24}|TL:{5,3}|TC:{6,4}|BTC:{7,4}|RC:{8,4}]",
power,
mode,
regulationMode,
turnRatio,
runState,
tachoLimit,
tachoCount,
blockTachoCount,
rotationCount);
}
}
///
/// Reply type for the OpenAppendData() function.
///
///
public struct NxtOpenAppendDataReply
{
///
/// File handle.
///
public byte handle;
///
/// Available file size.
///
public UInt32 availableFilesize;
}
///
/// Reply type for the OpenRead() function.
///
///
public struct NxtOpenReadReply
{
///
/// File handle.
///
public byte handle;
///
/// File size.
///
public UInt32 fileSize;
}
///
/// Reply type for the RequestFirstModule() and RequestNextModule() functions.
///
///
///
public struct NxtRequestModuleReply
{
///
/// Boolean indicating if a module was found, or not.
///
public bool ModuleFound;
///
/// Module handle.
///
public byte handle;
///
/// Module name.
///
public string moduleName;
///
/// Module ID.
///
public UInt32 moduleId;
///
/// Module ID, PP-value.
///
public byte moduleIdPP;
///
/// Module ID, TT-value.
///
public byte moduleIdTT;
///
/// Module ID, CC-value.
///
public byte moduleIdCC;
///
/// Module ID, FF-value.
///
public byte moduleIdFF;
///
/// Module size.
///
public UInt32 moduleSize;
///
/// Module IO-map size.
///
public UInt16 moduleIoMapSize;
}
#endregion
#region Enumerations.
///
/// Commands to the NXT brick.
///
///
/// Reference: BDK, Appendix 1 & 2.
///
public enum NxtCommand: byte
{
///
/// BDK, Appendix 2, p. 5.
///
StartProgram = 0x00,
///
/// BDK, Appendix 2, p. 5.
///
StopProgram = 0x01,
///
/// BDK, Appendix 2, p. 5.
///
PlaySoundfile = 0x02,
///
/// BDK, Appendix 2, p. 6.
///
PlayTone = 0x03,
///
/// BDK, Appendix 2, p. 6.
///
SetOutputState = 0x04,
///
/// BDK, Appendix 2, p. 7.
///
SetInputMode = 0x05,
///
/// BDK, Appendix 2, p. 8.
///
GetOutputState = 0x06,
///
/// BDK, Appendix 2, p. 8.
///
GetInputValues = 0x07,
///
/// BDK, Appendix 2, p. 8.
///
ResetInputScaledValue = 0x08,
///
/// BDK, Appendix 2, p. 9.
///
MessageWrite = 0x09,
///
/// BDK, Appendix 2, p. 9.
///
ResetMotorPosition = 0x0A,
///
/// BDK, Appendix 2, p. 9.
///
GetBatteryLevel = 0x0B,
///
/// BDK, Appendix 2, p. 9.
///
StopSoundPlayback = 0x0C,
///
/// BDK, Appendix 2, p. 10.
///
KeepAlive = 0x0D,
///
/// BDK, Appendix 2, p. 10.
///
LsGetStatus = 0x0E,
///
/// BDK, Appendix 2, p. 10.
///
LsWrite = 0x0F,
///
/// BDK, Appendix 2, p. 10.
///
LsRead = 0x10,
///
/// BDK, Appendix 2, p. 11.
///
GetCurrentProgramName = 0x11,
///
/// BDK, Appendix 2, p. 11.
///
MessageRead = 0x13,
///
/// BDK, Appendix 1, p. 7.
///
OpenRead = 0x80,
///
/// BDK, Appendix 1, p. 7.
///
OpenWrite = 0x81,
///
/// BDK, Appendix 1, p. 8.
///
Read = 0x82,
///
/// BDK, Appendix 1, p. 8.
///
Write = 0x83,
///
/// BDK, Appendix 1, p. 8.
///
Close = 0x84,
///
/// BDK, Appendix 1, p. 9.
///
Delete = 0x85,
///
/// BDK, Appendix 1, p. 9.
///
FindFirst = 0x86,
///
/// BDK, Appendix 1, p. 10.
///
FindNext = 0x87,
///
/// BDK, Appendix 1, p. 11.
///
GetFirmwareVersion = 0x88,
///
/// BDK, Appendix 1, p. 11.
///
OpenWriteLinear = 0x89,
///
/// BDK, Appendix 1, p. 12.
///
OpenReadLinear = 0x8A,
///
/// BDK, Appendix 1, p. 12.
///
OpenWriteData = 0x8B,
///
/// BDK, Appendix 1, p. 13.
///
OpenAppendData = 0x8C,
///
/// BDK, Appendix 1, p. 19.
///
RequestFirstModule = 0x90,
///
/// BDK, Appendix 1, p. 19.
///
RequestNextModule = 0x91,
///
/// BDK, Appendix 1, p. 20.
///
CloseModuleHandle = 0x92,
///
/// BDK, Appendix 1, p. 20.
///
ReadIoMap = 0x94,
///
/// BDK, Appendix 1, p. 21.
///
WriteIoMap = 0x95,
///
/// BDK, Appendix 1, p. 13.
///
Boot = 0x97,
///
/// BDK, Appendix 1, p. 13.
///
SetBrickName = 0x98,
///
/// BDK, Appendix 1, p. 14.
///
GetDeviceInfo = 0x9B,
///
/// BDK, Appendix 1, p. 14.
///
DeleteUserFlash = 0xA0,
///
/// BDK, Appendix 1, p. 15.
///
PollCommandLength = 0xA1,
///
/// BDK, Appendix 1, p. 15.
///
PollCommand = 0xA2,
///
/// BDK, Appendix 1, p. 15.
///
BluetoothFactoryReset = 0xA4
}
///
/// ERROR MESSAGE BACK TO THE HOST
///
///
/// Reference: BDK, Appendix 1, p. 16.
/// Reference: BDK, Appendix 2, p. 12.
///
public enum NxtErrorMessage: byte
{
///
/// BDK, Appendix 2, p. 12.
///
Succes = 0x00,
///
/// BDK, Appendix 2, p. 12.
///
PendingCommunicationTransactionInProgress = 0x20,
///
/// BDK, Appendix 2, p. 12.
///
SpecifiedMailboxQueueIsEmpty = 0x40,
///
/// BDK, Appendix 1, p. 16.
///
NoMoreHandles = 0x81,
///
/// BDK, Appendix 1, p. 16.
///
NoSpace = 0x82,
///
/// BDK, Appendix 1, p. 16.
///
NoMoreFiles = 0x83,
///
/// BDK, Appendix 1, p. 16.
///
EndOfFileExpected = 0x84,
///
/// BDK, Appendix 1, p. 16.
///
EndOfFile = 0x85,
///
/// BDK, Appendix 1, p. 16.
///
NotALinearFile = 0x86,
///
/// BDK, Appendix 1, p. 16.
///
FileNotFound = 0x87,
///
/// BDK, Appendix 1, p. 16.
///
HandleAllReadyClosed = 0x88,
///
/// BDK, Appendix 1, p. 16.
///
NoLinearSpace = 0x89,
///
/// BDK, Appendix 1, p. 16.
///
UndefinedError = 0x8A,
///
/// BDK, Appendix 1, p. 16.
///
FileIsBusy = 0x8B,
///
/// BDK, Appendix 1, p. 16.
///
NoWriteBuffers = 0x8C,
///
/// BDK, Appendix 1, p. 16.
///
AppendNotPossible = 0x8D,
///
/// BDK, Appendix 1, p. 16.
///
FileIsFull = 0x8E,
///
/// BDK, Appendix 1, p. 16.
///
FileExists = 0x8F,
///
/// BDK, Appendix 1, p. 16.
///
ModuleNotFound = 0x90,
///
/// BDK, Appendix 1, p. 16.
///
OutIfBoundary = 0x91,
///
/// BDK, Appendix 1, p. 16.
///
IllegalFileName = 0x92,
///
/// BDK, Appendix 1, p. 16.
///
IllegalHandle = 0x93,
///
/// BDK, Appendix 2, p. 12.
///
RequestFailed = 0xBD, // i.e. specified file not found
///
/// BDK, Appendix 2, p. 12.
///
UnknownCommandOpcode = 0xBE,
///
/// BDK, Appendix 2, p. 12.
///
InsanePacket = 0xBF,
///
/// BDK, Appendix 2, p. 12.
///
DataContainsOutOfRangeValues = 0xC0,
///
/// BDK, Appendix 2, p. 12.
///
CommunicationBusError = 0xDD,
///
/// BDK, Appendix 2, p. 12.
///
NoFreeMemoryInCommunicationBuffer = 0xDE,
///
/// BDK, Appendix 2, p. 12.
///
SpecifiedChannelOrConnectionIsNotValid = 0xDF,
///
/// BDK, Appendix 2, p. 12.
///
SpecifiedChannelOrConnectionNotConfiguredOrBusy = 0xE0,
///
/// BDK, Appendix 2, p. 12.
///
NoActiveProgram = 0xEC,
///
/// BDK, Appendix 2, p. 12.
///
IllegalSizeSpecified = 0xED,
///
/// BDK, Appendix 2, p. 12.
///
IllegalMailboxQueueIdSpecified = 0xEE,
///
/// BDK, Appendix 2, p. 12.
///
AttemptedToAccessInvalidFieldOfAStructure = 0xEF,
///
/// BDK, Appendix 2, p. 12.
///
BadInputOrOutputSpecified = 0xF0,
///
/// BDK, Appendix 2, p. 12.
///
InsufficientMemoryAvailable = 0xFB,
///
/// BDK, Appendix 2, p. 12.
///
BadArguments = 0xFF
}
///
/// Reference: BDK, Appendix 2, p. 6.
///
[Flags]
public enum NxtMotorMode: byte
{
///
/// Turn on the specified motor.
///
MOTORON = 0x01,
///
/// Use run/break instead of run/float in PWM.
///
BRAKE = 0x02,
///
/// Turns on the regulation.
///
REGULATED = 0x04
}
///
/// Reference: BDK, Appendix 2, p. 6.
///
public enum NxtMotorPort: byte
{
///
/// Motor port A.
///
PortA,
///
/// Motor port B.
///
PortB,
///
/// Motor port C.
///
PortC,
///
/// All motor ports.
///
All = 0xFF
}
///
/// Reference: BDK, Appendix 2, p. 6.
///
public enum NxtMotorRegulationMode: byte
{
///
/// No regulation will be enabled.
///
REGULATION_MODE_IDLE = 0x00,
///
/// Power control will be enabled on specified output.
///
REGULATION_MODE_MOTOR_SPEED = 0x01,
///
/// Syncronization will be enabled (Needs enabled on two output).
///
REGULATION_MODE_MOTOR_SYNC = 0x02
}
///
/// Reference: BDK, Appendix 2, p. 6.
///
[Flags]
public enum NxtMotorRunState: byte
{
///
/// Output will be idle.
///
MOTOR_RUN_STATE_IDLE = 0x00,
///
/// Output will ramp-up.
///
MOTOR_RUN_STATE_RAMPUP = 0x10,
///
/// Output will be running.
///
MOTOR_RUN_STATE_RUNNING = 0x20,
///
/// Output will ramp-down.
///
MOTOR_RUN_STATE_RAMPDOWN = 0x40
}
///
/// Reference: BDK, Appendix 2, p. 7.
///
public enum NxtSensorMode: byte
{
///
/// ... TBD ...
///
RAWMODE = 0x00,
///
/// ... TBD ...
///
BOOLEANMODE = 0x20,
///
/// ... TBD ...
///
TRANSITIONCNTMODE = 0x40,
///
/// ... TBD ...
///
PERIODCOUNTERMODE = 0x60,
///
/// ... TBD ...
///
PCTFULLSCALEMODE = 0x80,
///
/// ... TBD ...
///
CELSIUSMODE = 0xA0,
///
/// ... TBD ...
///
FAHRENHEITMODE = 0xC0,
///
/// ... TBD ...
///
ANGLESTEPMODE = 0xE0
// SLOPEMASK = 0x1F (?)
// MODEMASK = 0xE0 (?)
}
///
/// Reference: BDK, Appendix 2, p. 7.
///
public enum NxtSensorPort: byte
{
///
/// Sensor port 1.
///
Port1,
///
/// Sensor port 2.
///
Port2,
///
/// Sensor port 3.
///
Port3,
///
/// Sensor port 4.
///
Port4
}
///
/// Reference: BDK, Appendix 2, p. 7.
///
///
/// Explantion of the values is found on p. 46 of the Executable File Specification document.
///
public enum NxtSensorType: byte
{
///
/// No sensor configured.
///
NO_SENSOR = 0x00,
///
/// NXT or RCX touch sensor.
///
SWITCH = 0x01,
///
/// RCX temperature sensor.
///
TEMPERATURE = 0x02,
///
/// RCX light sensor.
///
REFLECTION = 0x03,
///
/// RCX rotation sensor.
///
ANGLE = 0x04,
///
/// NXT light sensor with floodlight enabled.
///
LIGHT_ACTIVE = 0x05,
///
/// NXT light sensor with floodlight disabled.
///
LIGHT_INACTIVE = 0x06,
///
/// NXT sound sensor; dB scaling.
///
SOUND_DB = 0x07,
///
/// NXT sound sensor; dBA scaling.
///
SOUND_DBA = 0x08,
///
/// Unused in NXT programs.
///
CUSTOM = 0x09,
///
/// I2C digital sensor.
///
LOWSPEED = 0x0A,
///
/// I2C digital sensor; 9V power.
///
LOWSPEED_9V = 0x0B,
///
/// "HIGHSPEED". Unused in NXT programs.
///
NO_OF_SENSOR_TYPES = 0x0C,
///
/// Nxt Colour Sensor
///
COLOR_DETECTOR = 0x0D,
COLOR_RED = 0x0E,
COLOR_GREEN = 0x0F,
COLOR_BLUE = 0x10,
COLOR_NONE = 0x11,
}
///
/// Reference: BDK, Appendix 2, p. 9.
///
public enum NxtMailbox: byte
{
///
/// ... TBD ...
///
Box0,
///
/// ... TBD ...
///
Box1,
///
/// ... TBD ...
///
Box2,
///
/// ... TBD ...
///
Box3,
///
/// ... TBD ...
///
Box4,
///
/// ... TBD ...
///
Box5,
///
/// ... TBD ...
///
Box6,
///
/// ... TBD ...
///
Box7,
///
/// ... TBD ...
///
Box8,
///
/// ... TBD ...
///
Box9
}
///
/// Reference: BDK, Appendix 2, p. 9.
/// Reference: BDK, Appendix 2, p. 11. (see MessageRead() function).
///
public enum NxtMailbox2: byte
{
///
/// ... TBD ...
///
Box0,
///
/// ... TBD ...
///
Box1,
///
/// ... TBD ...
///
Box2,
///
/// ... TBD ...
///
Box3,
///
/// ... TBD ...
///
Box4,
///
/// ... TBD ...
///
Box5,
///
/// ... TBD ...
///
Box6,
///
/// ... TBD ...
///
Box7,
///
/// ... TBD ...
///
Box8,
///
/// ... TBD ...
///
Box9,
///
/// ... TBD ...
///
Box10,
///
/// ... TBD ...
///
Box11,
///
/// ... TBD ...
///
Box12,
///
/// ... TBD ...
///
Box13,
///
/// ... TBD ...
///
Box14,
///
/// ... TBD ...
///
Box15,
///
/// ... TBD ...
///
Box16,
///
/// ... TBD ...
///
Box17,
///
/// ... TBD ...
///
Box18,
///
/// ... TBD ...
///
Box19
}
#endregion
}