/// <summary> /// Connect to Lego RCX brick. /// </summary> /// /// <param name="towerType">Type of IR tower to use for communication with RCX brick.</param> /// /// <returns>Returns <b>true</b> on successful connection or <b>false</b> /// otherwise.</returns> /// /// <remarks>If connection to RCX brick was established before the call, existing connection will be reused. /// If it is required to force reconnection, then <see cref="Disconnect"/> method should be called before. /// </remarks> /// public bool Connect(IRTowerType towerType) { lock ( sync ) { // check if we are already connected if (stack != IntPtr.Zero) { return(true); } uint status; // create stack status = GhostAPI.GhCreateStack( (towerType == IRTowerType.USB) ? "LEGO.Pbk.CommStack.Port.USB" : "LEGO.Pbk.CommStack.Port.RS232", "LEGO.Pbk.CommStack.Protocol.IR", "LEGO.Pbk.CommStack.Session", out stack); if (!GhostAPI.PBK_SUCCEEDED(status)) { return(false); } // select first available device StringBuilder sb = new StringBuilder(200); status = GhostAPI.GhSelectFirstDevice(stack, sb, sb.Length); if (!GhostAPI.PBK_SUCCEEDED(status)) { Disconnect( ); return(false); } // open stack, set interleave, set wait mode and check if the brick is alive if ( !GhostAPI.PBK_SUCCEEDED(GhostAPI.GhOpen(stack)) || !GhostAPI.PBK_SUCCEEDED(GhostAPI.GhSetWaitMode(stack, IntPtr.Zero)) || !GhostAPI.PBK_SUCCEEDED(GhostAPI.GhSetInterleave(stack, 1, 0)) || !IsAlive( ) ) { Disconnect( ); return(false); } } return(true); }
/// <summary> /// Send command to Lego RCX brick and read reply. /// </summary> /// /// <param name="command">Command to send.</param> /// <param name="reply">Buffer to receive reply into.</param> /// <param name="expectedReplyLen">Expected reply length.</param> /// /// <returns>Returns <b>true</b> if the command was sent successfully and reply was /// received, otherwise <b>false</b>.</returns> /// /// <exception cref="NullReferenceException">Communication can not be performed, because connection with /// RCX brick was not established yet.</exception> /// <exception cref="ArgumentException">Reply buffer size is smaller than the reply data size.</exception> /// <exception cref="ApplicationException">Reply does not correspond to command (first byte of reply /// should be complement (bitwise NOT) to the first byte of command orred with 0x08).</exception> /// protected bool SendCommand(byte[] command, byte[] reply, int expectedReplyLen) { bool result = false; uint status; IntPtr queue; lock ( sync ) { // check if GhostAPI stack was created (if device is connected) if (stack == IntPtr.Zero) { throw new NullReferenceException("Not connected to RCX brick"); } // create command queue status = GhostAPI.GhCreateCommandQueue(out queue); if (!GhostAPI.PBK_SUCCEEDED(status)) { return(false); } // append command to the queue status = GhostAPI.GhAppendCommand(queue, command, command.Length, expectedReplyLen); if (GhostAPI.PBK_SUCCEEDED(status)) { // execute command status = GhostAPI.GhExecute(stack, queue); if (GhostAPI.PBK_SUCCEEDED(status)) { IntPtr commandHandle; uint replyLen; // get first command and its reply data lenght if ( (GhostAPI.PBK_SUCCEEDED(GhostAPI.GhGetFirstCommand(queue, out commandHandle))) && (GhostAPI.PBK_SUCCEEDED(GhostAPI.GhGetCommandReplyLen(commandHandle, out replyLen))) ) { // check provided reply buffer size if (reply.Length < replyLen) { throw new ArgumentException("Reply buffer is too small"); } // get reply data status = GhostAPI.GhGetCommandReply(commandHandle, reply, replyLen); if (GhostAPI.PBK_SUCCEEDED(status)) { // check that reply corresponds to command if ((command[0] | 0x08) != (byte)~reply[0]) { throw new ApplicationException("Reply does not correspond to command"); } result = true; } } } } // destroy command queue GhostAPI.GhDestroyCommandQueue(queue); } return(result); }