//------------------------------------------------------------------------------------------------------------------------------------------- private void SendResponse(byte command_byte, byte[] buffer) { byte[] response = new byte[] { (byte)(command_byte + 0x10), buffer[1], buffer[2] }; Debug.Print("Sending response: "); NumberConversions.PrintByteArray(response); _port.Write(response, 0, response.Length); }
//------------------------------------------------------------------------------------------------------------------------------------------- private void SendResponse(byte command_byte, byte[] buffer, ushort value) { char[] value_array = NumberConversions.ShortToCharArray(value); byte[] response = new byte[] { (byte)(command_byte + 0x10), buffer[1], buffer[2], (byte)value_array[0], (byte)value_array[1], (byte)value_array[2], (byte)value_array[3] }; Debug.Print("Sending response: "); NumberConversions.PrintByteArray(response); _port.Write(response, 0, response.Length); }
//------------------------------------------------------------------------------------------------------------------------------------------- private byte GetVariableIndexFromBuffer(byte command_byte, byte[] buffer) { byte index_high_nibble = buffer[1]; byte index_low_nibble = buffer[2]; byte index = NumberConversions.HexStringToByte(new String(new char[] { (char)index_high_nibble, (char)index_low_nibble })); Debug.Print("Command 0x" + NumberConversions.ByteToHexString(command_byte) + ": variable index = " + index.ToString()); return(index); }
//------------------------------------------------------------------------------------------------------------------------------------------- private byte GetByteValueFromBuffer(byte command_byte, byte[] buffer) { byte value_high_nibble = buffer[3]; byte value_low_nibble = buffer[4]; byte value = NumberConversions.HexStringToByte(new String(new char[] { (char)value_high_nibble, (char)value_low_nibble })); Debug.Print("Command 0x" + NumberConversions.ByteToHexString(command_byte) + ": setting with byte value = " + value.ToString()); return(value); }
//------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Sets the specified byte in the Amulet touchscreen /// </summary> /// <param name="index"></param> /// <returns></returns> public byte GetByte(byte index) { char[] nibbles = NumberConversions.ByteToCharArray(index); _port.Write(new byte[] { 0xD0, (byte)nibbles[0], (byte)nibbles[1] }, 0, 3); // set timer to check response time long start = Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks; // wait for response from Amulet byte result = ParseResponseForByte(); long end = Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks; long ms = (end - start) / System.TimeSpan.TicksPerMillisecond; return(result); }
//------------------------------------------------------------------------------------------------------------------------------------------- private ushort GetShortValueFromBuffer(byte command_byte, byte[] buffer) { byte msb_value_high_nibble = buffer[3]; byte msb_value_low_nibble = buffer[4]; byte msb = NumberConversions.HexStringToByte(new String(new char[] { (char)msb_value_high_nibble, (char)msb_value_low_nibble })); byte lsb_value_high_nibble = buffer[5]; byte lsb_value_low_nibble = buffer[6]; byte lsb = NumberConversions.HexStringToByte(new String(new char[] { (char)lsb_value_high_nibble, (char)lsb_value_low_nibble })); ushort value = (ushort)(((short)msb << 8) + (short)lsb); Debug.Print("Command 0x" + NumberConversions.ByteToHexString(command_byte) + ": setting with short value = " + value.ToString()); return(value); }
//------------------------------------------------------------------------------------------------------------------------------------------- private bool ValidateCommandPacket(byte command_byte, byte[] buffer) { if (buffer.Length < (int)GetCommandPacketLength(command_byte)) { Debug.Print("ERROR: Command parsing for command 0x" + NumberConversions.ByteToHexString(command_byte) + " (" + ByteToCommandName(command_byte) + ") was skipped because not enough data was available"); return(false); } if (buffer[1] == 0 || buffer[2] == 0) { Debug.Print("ERROR: Command parsing for command 0x" + NumberConversions.ByteToHexString(command_byte) + " (" + ByteToCommandName(command_byte) + ") failed because of null byte(s) in variable index"); return(false); } Debug.Print("Command " + ByteToCommandName(command_byte) + " validation OK"); return(true); }
//------------------------------------------------------------------------------------------------------------------------------------------- private void SendResponse(byte command_byte, byte[] buffer, byte[] value) { int value_length = value.Length; byte[] response = new byte[3 + value_length * 2 + 1]; // need to create extra space since each byte is broken up into high and low nibbles, plus 1 for null terminator response[0] = (byte)(command_byte + 0x10); response[1] = buffer[1]; response[2] = buffer[2]; for (int i = 0; i < value_length; i++) { char[] element_nibbles = NumberConversions.ByteToCharArray(value[i]); response[3 + (i * 2)] = (byte)element_nibbles[0]; response[3 + (i * 2) + 1] = (byte)element_nibbles[1]; } Debug.Print("Sending response: "); NumberConversions.PrintByteArray(response); _port.Write(response, 0, response.Length); }
//------------------------------------------------------------------------------------------------------------------------------------------- private void SendResponse(byte command_byte, byte[] buffer, string value) { // for null termination ---------------------v int total_response_size = 3 + value.Length + 1; byte[] response = new byte[total_response_size]; response[0] = (byte)(command_byte + 0x10); response[1] = buffer[1]; response[2] = buffer[2]; // get the string characters and cast to byte one by one char[] value_array = value.ToCharArray(); for (int i = 0; i < value.Length; i++) { response[3 + i] = (byte)value_array[i]; } Debug.Print("Sending response: "); NumberConversions.PrintByteArray(response); _port.Write(response, 0, response.Length); }
//------------------------------------------------------------------------------------------------------------------------------------------- public ushort[] GetWordVariableArray(byte index) { bool print_array = false; // here we will just return a byte array with 128 random values const int size = 61; ushort[] value = new ushort[size]; for (int i = 0; i < size; i++) { // scale result - SPOT.Math returns Sin * 1000, so shift up by 1000 since LineGraph doesn't seem to do negative numbers? value[i] = (ushort)(Microsoft.SPOT.Math.Sin(_sin_word_counter++) + 1000); } Debug.Print("[AmuletTestClient] GetWordVariableArray " + index + ":"); if (print_array) { NumberConversions.PrintWordArray(value); } return(value); }
//------------------------------------------------------------------------------------------------------------------------------------------- public byte[] GetByteVariableArray(byte index) { bool print_array = false; // here we will just return a byte array with 128 random values const int size = 111; byte[] value = new byte[size]; //new Random().NextBytes( value); for (int i = 0; i < size; i++) { // scale result - SPOT.Math returns Sin * 1000, so divide result by 10 and shift up by 100 since LineGraph doesn't seem to do negative numbers? value[i] = (byte)(Microsoft.SPOT.Math.Sin(_sin_int_counter++) / 10 + 100); } Debug.Print("[AmuletTestClient] GetByteVariableArray " + index + ":"); if (print_array) { NumberConversions.PrintByteArray(value); } return(value); }
//------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Parses the serial data buffer and responds as appropriate. Buffer should start with a valid command byte. /// </summary> private void HandleCommand(byte[] buffer) { try { Debug.Print("Command packet contents:"); NumberConversions.PrintByteArray(buffer); byte command_byte = buffer[0]; if (!ValidateCommandPacket(command_byte, buffer)) { return; } byte index = GetVariableIndexFromBuffer(command_byte, buffer); if (!CheckForAmuletClient()) { return; } switch (command_byte) { case (byte)Commands.GetByte: { // acknowledge the command, but need to get data from IAmuletClient try { byte value = _client.GetByte(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetByte failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.GetWord: { // acknowledge the command try { ushort value = _client.GetWord(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetWord failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.GetString: { try { string value = _client.GetString(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetString failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.GetLabel: { try { string value = _client.GetLabel(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetLabel failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.GetByteVariableArray: { try { byte[] value = _client.GetByteVariableArray(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetLabel failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.GetWordVariableArray: { try { ushort[] value = _client.GetWordVariableArray(index); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: GetLabel failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.SetByte: { byte value = GetByteValueFromBuffer(command_byte, buffer); // acknowledge the command try { _client.SetByte(index, value); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: SetByte failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.SetWord: { ushort value = GetShortValueFromBuffer(command_byte, buffer); // acknowledge the command try { _client.SetWord(index, value); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: SetByte failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.SetString: { string value = GetStringValueFromBuffer(command_byte, buffer); // acknowledge the command try { _client.SetString(index, value); SendResponse(command_byte, buffer, value); } catch (Exception ex) { Debug.Print("ERROR: SetString failed in client call: " + ex.Message); SendAck(); } break; } case (byte)Commands.InvokeRpc: { // acknowledge the command, but need to call into IAmuletClient try { _client.InvokeRpc(index); SendResponse(command_byte, buffer); } catch (Exception ex) { Debug.Print("ERROR: GetByte failed in client call: " + ex.Message); SendAck(); } break; } } // now process any remaining commands // we can pass 0 because we know that anytime a command is processed, the next valid // command, if any, will end up at index 0 if (CommandPacketAvailable(0)) { byte[] data = ExtractCommandPacketFromRxBuffer(0); HandleCommand(data); } } catch (Exception ex) { Debug.Print(ex.Message); } }
//------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Returns the command packet and shifts remaining data in RX buffer down /// </summary> /// <param name="index_of_command_byte"></param> /// <returns></returns> private byte[] ExtractCommandPacketFromRxBuffer(int index_of_command_byte) { // the following variables are only used for the debug print statement that is going to // try to help visualize what's in the buffer, and what is getting extracted for command processing, e.g. // | command bytes here | rest of buffer here // print all buffer bytes up to index_of_command_byte // index_of_command_byte: print | before this position // print all buffer bytes up to index_of_command_byte + command_packet_length // print | after last command packet byte // print rest of buffer bytes // determine the number of bytes that should be in the command packet, based on the command byte command_id = _rx_buffer[index_of_command_byte]; byte command_packet_length = GetCommandPacketLength(command_id); Debug.Print("Handling command ID: " + ByteToCommandName(command_id) + ", expected packet length = " + command_packet_length); #region VISUALIZATION DEBUG MESSAGE // now print the debug buffer visualization line string viz = ""; // print all bytes up to command byte position for (int i = 0; i < index_of_command_byte; i++) { viz += NumberConversions.ByteToHexString(_rx_buffer[i]) + " "; } viz += "> "; // print command packet for (int i = index_of_command_byte; i < index_of_command_byte + command_packet_length; i++) { viz += NumberConversions.ByteToHexString(_rx_buffer[i]) + " "; if (i == index_of_command_byte + command_packet_length - 1) { viz += "< "; } } // print remaining bytes in buffer for (int i = index_of_command_byte + command_packet_length; i < RX_BUFFER_SIZE; i++) { if (_rx_buffer[i] == 0) { break; } viz += NumberConversions.ByteToHexString(_rx_buffer[i]) + " "; } Debug.Print(viz); #endregion // now create the array for just the packet byte[] packet = new byte[command_packet_length]; Array.Copy(_rx_buffer, index_of_command_byte, packet, 0, command_packet_length); //Debug.Print( "copied command packet from buffer into new packet array"); // we need to save the current _rx_buffer_pointer, because that's the ONLY way we know what the new // _rx_buffer_pointer should be once we shift down the bits. int old_rx_buffer_pointer = _rx_buffer_pointer; // modify the rx buffer and shift down the remaining bytes _rx_buffer_pointer = index_of_command_byte + command_packet_length; // now it points to the element after the command packet we're handling // the new rx buffer is where the end of the existing data will end up once we shift all of the bytes down int new_rx_buffer_pointer = old_rx_buffer_pointer - _rx_buffer_pointer; Debug.Assert(new_rx_buffer_pointer >= 0, "RX buffer pointer problems!"); //Debug.Print( "rx buffer pointer points at: " + _rx_buffer_pointer); int bytes_remaining_in_buffer = RX_BUFFER_SIZE - _rx_buffer_pointer; //Debug.Print( bytes_remaining_in_buffer.ToString() + " bytes left in buffer"); // shift down //Debug.Print( "shifting down bytes"); for (int i = 0; i < bytes_remaining_in_buffer; i++) { _rx_buffer[i] = _rx_buffer[_rx_buffer_pointer + i]; } //Debug.Print( "clearing remaining space"); // clear remaining space (possibly unnecessary) for (int i = bytes_remaining_in_buffer; i < RX_BUFFER_SIZE; i++) { _rx_buffer[i] = 0; } //Debug.Print( "Setting new RX buffer pointer to " + new_rx_buffer_pointer); _rx_buffer_pointer = new_rx_buffer_pointer; return(packet); }