/// <summary> /// Transmit an infrared command. /// </summary> /// <param name="port">Port to transmit on.</param> /// <param name="data">Data to transmit.</param> /// <returns><c>true</c> if successful, otherwise <c>false</c>.</returns> public bool Transmit(string port, byte[] data) { BlasterPort blasterPort = BlasterPort.Both; try { blasterPort = (BlasterPort)Enum.Parse(typeof(BlasterPort), port, true); } catch { #if TRACE Trace.WriteLine(String.Format("Invalid Blaster Port ({0}), using default ({1})", port, blasterPort)); #endif } IrCode code = IrCode.FromByteArray(data); if (code == null) { throw new ArgumentException("Invalid IR Command data", "data"); } _driver.Send(code, (int)blasterPort); return(true); }
/// <summary> /// Converts an IrCode into raw data for the device. /// </summary> /// <param name="code">IrCode to convert.</param> /// <returns>Raw device data.</returns> private static byte[] DataPacket(IrCode code) { DebugWriteLine("DataPacket()"); if (code.TimingData.Length == 0) { return(null); } // Construct data bytes into "packet" ... List <byte> packet = new List <byte>(); for (int index = 0; index < code.TimingData.Length; index++) { double time = code.TimingData[index]; byte duration = (byte)Math.Abs(Math.Round(time / TimingResolution)); bool pulse = (time > 0); DebugWrite("{0}{1}, ", pulse ? '+' : '-', duration * TimingResolution); while (duration > 0x7F) { packet.Add((byte)(pulse ? 0xFF : 0x7F)); duration -= 0x7F; } packet.Add((byte)(pulse ? 0x80 | duration : duration)); } DebugWriteNewLine(); // Insert byte count markers into packet data bytes ... int subpackets = (int)Math.Ceiling(packet.Count / (double)4); byte[] output = new byte[packet.Count + subpackets + 1]; int outputPos = 0; for (int packetPos = 0; packetPos < packet.Count;) { byte copyCount = (byte)(packet.Count - packetPos < 4 ? packet.Count - packetPos : 0x04); output[outputPos++] = (byte)(0x80 | copyCount); for (int index = 0; index < copyCount; index++) { output[outputPos++] = packet[packetPos++]; } } output[outputPos] = 0x80; return(output); }
/// <summary> /// Learn an IR Command. /// </summary> /// <param name="learnTimeout">How long to wait before aborting learn.</param> /// <param name="learned">Newly learned IR Command.</param> /// <returns>Learn status.</returns> public override LearnStatus Learn(int learnTimeout, out IrCode learned) { DebugWriteLine("Learn()"); learned = null; _learningCode = new IrCode(); SetInputPort(InputPort.Learning); int learnStartTick = Environment.TickCount; _readThreadMode = ReadThreadMode.Learning; // Wait for the learning to finish ... while (_readThreadMode == ReadThreadMode.Learning && Environment.TickCount < learnStartTick + learnTimeout) { Thread.Sleep(PacketTimeout); } DebugWriteLine("End Learn"); ReadThreadMode modeWas = _readThreadMode; _readThreadMode = ReadThreadMode.Receiving; SetInputPort(InputPort.Receive); LearnStatus status = LearnStatus.Failure; switch (modeWas) { case ReadThreadMode.Learning: status = LearnStatus.Timeout; break; case ReadThreadMode.LearningFailed: status = LearnStatus.Failure; break; case ReadThreadMode.LearningDone: DebugDump(_learningCode.TimingData); if (_learningCode.FinalizeData()) { learned = _learningCode; status = LearnStatus.Success; } break; } _learningCode = null; return(status); }
/* * public static ushort[] ConvertIrCodeToPronto(IrCode irCode) * { * CodeType codeType; * Int64 value; * * if (Decode(irCode, out codeType, out value)) * return EncodePronto(codeType, value); * else * return null; * } */ /// <summary> /// Converts the ir code into Pronto raw format. /// </summary> /// <param name="irCode">The ir code to convert.</param> /// <returns>Pronto data (raw format).</returns> public static ushort[] ConvertIrCodeToProntoRaw(IrCode irCode) { List <ushort> prontoData = new List <ushort>(); double carrier; ushort prontoCarrier; CodeType codeType; int irCodeCarrier = IrCode.CarrierFrequencyDefault; switch (irCode.Carrier) { case IrCode.CarrierFrequencyDCMode: codeType = CodeType.RawUnmodulated; irCodeCarrier = IrCode.CarrierFrequencyDefault; break; case IrCode.CarrierFrequencyUnknown: codeType = CodeType.RawOscillated; irCodeCarrier = IrCode.CarrierFrequencyDefault; break; default: codeType = CodeType.RawOscillated; irCodeCarrier = irCode.Carrier; break; } prontoCarrier = ConvertToProntoCarrier(irCodeCarrier); carrier = prontoCarrier * ProntoClock; for (int index = 0; index < irCode.TimingData.Length; index++) { int duration = Math.Abs(irCode.TimingData[index]); prontoData.Add((ushort)Math.Round(duration / carrier)); } if (prontoData.Count % 2 != 0) { prontoData.Add(SignalFree); } ushort burstPairs = (ushort)(prontoData.Count / 2); prontoData.Insert(0, (ushort)codeType); // Pronto Code Type prontoData.Insert(1, prontoCarrier); // IR Frequency prontoData.Insert(2, burstPairs); // First Burst Pairs prontoData.Insert(3, 0x0000); // Repeat Burst Pairs return(prontoData.ToArray()); }
/// <summary> /// Determines the pulse count and total time of the supplied IrCode. /// This is used to determine the carrier frequency. /// </summary> /// <param name="code">The IrCode to analyse.</param> /// <param name="pulseTime">The total ammount of pulse time.</param> /// <param name="pulseCount">The total count of pulses.</param> private static void GetIrCodeLengths(IrCode code, out int pulseTime, out int pulseCount) { pulseTime = 0; pulseCount = 0; foreach (int time in code.TimingData) { if (time > 0) { pulseTime += time; pulseCount++; } } }
/// <summary> /// Creates an IrCode object from Pronto format file bytes. /// </summary> /// <param name="data">IR file bytes.</param> /// <returns>New IrCode object.</returns> private static IrCode FromProntoData(byte[] data) { string code = Encoding.ASCII.GetString(data); string[] stringData = code.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); ushort[] prontoData = new ushort[stringData.Length]; for (int i = 0; i < stringData.Length; i++) { prontoData[i] = ushort.Parse(stringData[i], NumberStyles.HexNumber); } IrCode newCode = Pronto.ConvertProntoDataToIrCode(prontoData); if (newCode != null) { newCode.FinalizeData(); } // Seems some old files have excessively long delays in them .. this might fix that problem ... return(newCode); }
/// <summary> /// Creates an IrCode object from old IR file bytes. /// </summary> /// <param name="data">IR file bytes.</param> /// <returns>New IrCode object.</returns> private static IrCode FromOldData(byte[] data) { List <int> timingData = new List <int>(); int len = 0; for (int index = 0; index < data.Length; index++) { byte curByte = data[index]; if ((curByte & 0x80) != 0) { len += (curByte & 0x7F); } else { len -= curByte; } if ((curByte & 0x7F) != 0x7F) { timingData.Add(len * 50); len = 0; } } if (len != 0) { timingData.Add(len * 50); } IrCode newCode = new IrCode(timingData.ToArray()); newCode.FinalizeData(); // Seems some old files have excessively long delays in them .. this might fix that problem ... return(newCode); }
/// <summary> /// Send an IR Command. /// </summary> /// <param name="code">IR Command data to send.</param> /// <param name="port">IR port to send to.</param> public override void Send(IrCode code, int port) { DebugWrite("Send(): "); DebugDump(code.TimingData); // Reset device (hopefully this will stop the blaster from stalling) //WriteSync(ResetPacket); SetOutputPort(port); SetCarrierFrequency(code.Carrier); // Send packet byte[] data = DataPacket(code); // If the code would go longer than the allowable limit, truncate the code if (data.Length > 341) // 340 minus the overhead of 1 byte in 4 for header is 255 bytes of actual time code data, add one for a terminator byte { Array.Resize(ref data, 341); // Shrink the array to fit data[340] = 0x80; // Set the terminator byte } WriteSync(data); }
/// <summary> /// Device read thread method. /// </summary> private void ReadThread() { byte[] packetBytes; WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] { waitHandle, _stopReadThread }; IntPtr deviceBufferPtr = IntPtr.Zero; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) { throw new InvalidOperationException("Failed to initialize safe wait handle"); } try { IntPtr dangerousWaitHandle = safeWaitHandle.DangerousGetHandle(); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(dangerousWaitHandle); deviceBufferPtr = Marshal.AllocHGlobal(DeviceBufferSize); while (_readThreadMode != ReadThreadMode.Stop) { int lastError; int bytesRead; bool readDevice = ReadFile(_readHandle, deviceBufferPtr, DeviceBufferSize, out bytesRead, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (!readDevice) { if (lastError != ErrorSuccess && lastError != ErrorIoPending) { throw new Win32Exception(lastError); } while (true) { int handle = WaitHandle.WaitAny(waitHandles, 2 * PacketTimeout, false); if (handle == ErrorWaitTimeout) { continue; } if (handle == 0) { break; } if (handle == 1) { throw new ThreadInterruptedException("Read thread stopping by request"); } throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); } bool getOverlapped = GetOverlappedResult(_readHandle, overlapped.Overlapped, out bytesRead, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) { throw new Win32Exception(lastError); } } if (bytesRead == 0) { continue; } packetBytes = new byte[bytesRead]; Marshal.Copy(deviceBufferPtr, packetBytes, 0, bytesRead); DebugWrite("Received bytes ({0}): ", bytesRead); DebugDump(packetBytes); int[] timingData = null; if (_decodeCarry != 0 || packetBytes[0] >= 0x81 && packetBytes[0] <= 0x9E) { timingData = GetTimingDataFromPacket(packetBytes); } else { double firmware = 0.0; int indexOfFF = Array.IndexOf(packetBytes, (byte)0xFF); while (indexOfFF != -1) { if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x0B) // FF 0B XY - Firmware X.Y00 { byte b1 = packetBytes[indexOfFF + 2]; firmware += (b1 >> 4) + (0.1 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x1B) // FF 1B XY - Firmware 0.0XY { byte b1 = packetBytes[indexOfFF + 2]; firmware += (0.01 * (b1 >> 4)) + (0.001 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 1) { indexOfFF = Array.IndexOf(packetBytes, (byte)0xFF, indexOfFF + 1); } else { break; } } } switch (_readThreadMode) { case ReadThreadMode.Receiving: { IrDecoder.DecodeIR(timingData, _remoteCallback, _keyboardCallback, _mouseCallback); break; } case ReadThreadMode.Learning: { if (timingData == null) { if (_learningCode.TimingData.Length > 0) { _learningCode = null; _readThreadMode = ReadThreadMode.LearningFailed; } break; } if (_learningCode == null) { throw new InvalidOperationException("Learning not initialised correctly, _learningCode object is null"); } _learningCode.AddTimingData(timingData); // Example: 9F 01 02 9F 15 00 BE 80 int indexOf9F = Array.IndexOf(packetBytes, (byte)0x9F); while (indexOf9F != -1) { if (packetBytes.Length > indexOf9F + 3 && packetBytes[indexOf9F + 1] == 0x15) // 9F 15 XX XX { byte b1 = packetBytes[indexOf9F + 2]; byte b2 = packetBytes[indexOf9F + 3]; int onTime, onCount; GetIrCodeLengths(_learningCode, out onTime, out onCount); double carrierCount = (b1 * 256) + b2; if (carrierCount / onCount < 2.0) { _learningCode.Carrier = IrCode.CarrierFrequencyDCMode; } else { double carrier = 1000000 * carrierCount / onTime; // TODO: Double-Check this calculation. if (carrier > 32000) { _learningCode.Carrier = (int)(carrier + 0.05 * carrier - 0.666667); // was: _learningCode.Carrier = (int) (carrier + 0.05*carrier - 32000/48000); } else { _learningCode.Carrier = (int)carrier; } } _readThreadMode = ReadThreadMode.LearningDone; break; } if (packetBytes.Length > indexOf9F + 1) { indexOf9F = Array.IndexOf(packetBytes, (byte)0x9F, indexOf9F + 1); } else { _readThreadMode = ReadThreadMode.LearningFailed; break; } } break; } } } } catch (ThreadInterruptedException ex) { DebugWriteLine(ex.Message); if (_readHandle != null) { CancelIo(_readHandle); } } catch (Exception ex) { DebugWriteLine(ex.ToString()); if (_readHandle != null) { CancelIo(_readHandle); } } finally { if (deviceBufferPtr != IntPtr.Zero) { Marshal.FreeHGlobal(deviceBufferPtr); } safeWaitHandle.DangerousRelease(); waitHandle.Close(); } DebugWriteLine("Read Thread Ended"); }
/// <summary> /// Send an IR Command. /// </summary> /// <param name="code">IR Command data to send.</param> /// <param name="port">IR port to send to.</param> public abstract void Send(IrCode code, int port);
/// <summary> /// Send an IR Command. /// </summary> /// <param name="code">IR Command data to send.</param> /// <param name="port">IR port to send to.</param> public override void Send(IrCode code, int port) { DebugWrite("Send(): "); DebugDump(code.TimingData); byte[] data = DataPacket(code); int portMask = 0; // Hardware ports map to bits in mask with Port 1 at left, ascending to right switch ((BlasterPort)port) { case BlasterPort.Both: portMask = _txPortMask; break; case BlasterPort.Port_1: portMask = GetHighBit(_txPortMask, _numTxPorts); break; case BlasterPort.Port_2: portMask = GetHighBit(_txPortMask, _numTxPorts - 1); break; } TransmitIR(data, code.Carrier, portMask); }
/// <summary> /// Creates an IrCode object from old IR file bytes. /// </summary> /// <param name="data">IR file bytes.</param> /// <returns>New IrCode object.</returns> private static IrCode FromOldData(byte[] data) { List<int> timingData = new List<int>(); int len = 0; for (int index = 0; index < data.Length; index++) { byte curByte = data[index]; if ((curByte & 0x80) != 0) len += (curByte & 0x7F); else len -= curByte; if ((curByte & 0x7F) != 0x7F) { timingData.Add(len * 50); len = 0; } } if (len != 0) timingData.Add(len * 50); IrCode newCode = new IrCode(timingData.ToArray()); newCode.FinalizeData(); // Seems some old files have excessively long delays in them .. this might fix that problem ... return newCode; }
/* public static ushort[] ConvertIrCodeToPronto(IrCode irCode) { CodeType codeType; Int64 value; if (Decode(irCode, out codeType, out value)) return EncodePronto(codeType, value); else return null; } */ /// <summary> /// Converts the ir code into Pronto raw format. /// </summary> /// <param name="irCode">The ir code to convert.</param> /// <returns>Pronto data (raw format).</returns> public static ushort[] ConvertIrCodeToProntoRaw(IrCode irCode) { List<ushort> prontoData = new List<ushort>(); double carrier; ushort prontoCarrier; CodeType codeType; int irCodeCarrier = IrCode.CarrierFrequencyDefault; switch (irCode.Carrier) { case IrCode.CarrierFrequencyDCMode: codeType = CodeType.RawUnmodulated; irCodeCarrier = IrCode.CarrierFrequencyDefault; break; case IrCode.CarrierFrequencyUnknown: codeType = CodeType.RawOscillated; irCodeCarrier = IrCode.CarrierFrequencyDefault; break; default: codeType = CodeType.RawOscillated; irCodeCarrier = irCode.Carrier; break; } prontoCarrier = ConvertToProntoCarrier(irCodeCarrier); carrier = prontoCarrier * ProntoClock; for (int index = 0; index < irCode.TimingData.Length; index++) { int duration = Math.Abs(irCode.TimingData[index]); prontoData.Add((ushort) Math.Round(duration / carrier)); } if (prontoData.Count % 2 != 0) prontoData.Add(SignalFree); ushort burstPairs = (ushort) (prontoData.Count / 2); prontoData.Insert(0, (ushort) codeType); // Pronto Code Type prontoData.Insert(1, prontoCarrier); // IR Frequency prontoData.Insert(2, burstPairs); // First Burst Pairs prontoData.Insert(3, 0x0000); // Repeat Burst Pairs return prontoData.ToArray(); }
/// <summary> /// Learn an IR Command. /// </summary> /// <param name="learnTimeout">How long to wait before aborting learn.</param> /// <param name="learned">Newly learned IR Command.</param> /// <returns>Learn status.</returns> public abstract LearnStatus Learn(int learnTimeout, out IrCode learned);
/// <summary> /// Converts an IrCode into raw data for the device. /// </summary> /// <param name="code">IrCode to convert.</param> /// <returns>Raw device data.</returns> private static byte[] DataPacket(IrCode code) { DebugWriteLine("DataPacket()"); if (code.TimingData.Length == 0) return null; // Construct data bytes into "packet" ... List<byte> packet = new List<byte>(); for (int index = 0; index < code.TimingData.Length; index++) { double time = code.TimingData[index]; byte duration = (byte) Math.Abs(Math.Round(time / TimingResolution)); bool pulse = (time > 0); DebugWrite("{0}{1}, ", pulse ? '+' : '-', duration * TimingResolution); while (duration > 0x7F) { packet.Add((byte) (pulse ? 0xFF : 0x7F)); duration -= 0x7F; } packet.Add((byte) (pulse ? 0x80 | duration : duration)); } DebugWriteNewLine(); // Insert byte count markers into packet data bytes ... int subpackets = (int) Math.Ceiling(packet.Count / (double) 4); byte[] output = new byte[packet.Count + subpackets + 1]; int outputPos = 0; for (int packetPos = 0; packetPos < packet.Count;) { byte copyCount = (byte) (packet.Count - packetPos < 4 ? packet.Count - packetPos : 0x04); output[outputPos++] = (byte) (0x80 | copyCount); for (int index = 0; index < copyCount; index++) output[outputPos++] = packet[packetPos++]; } output[outputPos] = 0x80; return output; }
/// <summary> /// Learn an IR Command. /// </summary> /// <param name="learnTimeout">How long to wait before aborting learn.</param> /// <param name="learned">Newly learned IR Command.</param> /// <returns>Learn status.</returns> public override LearnStatus Learn(int learnTimeout, out IrCode learned) { DebugWriteLine("Learn()"); RestartReadThread(ReadThreadMode.Learning); learned = null; _learningCode = new IrCode(); int learnStartTick = Environment.TickCount; // Wait for the learning to finish ... while (_readThreadMode == ReadThreadMode.Learning && Environment.TickCount < learnStartTick + learnTimeout) Thread.Sleep(PacketTimeout); DebugWriteLine("End Learn"); ReadThreadMode modeWas = _readThreadMode; RestartReadThread(ReadThreadMode.Receiving); LearnStatus status = LearnStatus.Failure; switch (modeWas) { case ReadThreadMode.Learning: status = LearnStatus.Timeout; break; case ReadThreadMode.LearningFailed: status = LearnStatus.Failure; break; case ReadThreadMode.LearningDone: DebugDump(_learningCode.TimingData); if (_learningCode.FinalizeData()) { learned = _learningCode; status = LearnStatus.Success; } break; } _learningCode = null; return status; }
/// <summary> /// Device read thread method. /// </summary> private void ReadThread() { byte[] packetBytes; WaitHandle waitHandle = new ManualResetEvent(false); SafeHandle safeWaitHandle = waitHandle.SafeWaitHandle; WaitHandle[] waitHandles = new WaitHandle[] {waitHandle, _stopReadThread}; IntPtr deviceBufferPtr = IntPtr.Zero; bool success = false; safeWaitHandle.DangerousAddRef(ref success); if (!success) throw new InvalidOperationException("Failed to initialize safe wait handle"); try { IntPtr dangerousWaitHandle = safeWaitHandle.DangerousGetHandle(); DeviceIoOverlapped overlapped = new DeviceIoOverlapped(); overlapped.ClearAndSetEvent(dangerousWaitHandle); deviceBufferPtr = Marshal.AllocHGlobal(DeviceBufferSize); while (_readThreadMode != ReadThreadMode.Stop) { int lastError; int bytesRead; bool readDevice = ReadFile(_readHandle, deviceBufferPtr, DeviceBufferSize, out bytesRead, overlapped.Overlapped); lastError = Marshal.GetLastWin32Error(); if (!readDevice) { if (lastError != ErrorSuccess && lastError != ErrorIoPending) throw new Win32Exception(lastError); while (true) { int handle = WaitHandle.WaitAny(waitHandles, 2 * PacketTimeout, false); if (handle == ErrorWaitTimeout) continue; if (handle == 0) break; if (handle == 1) throw new ThreadInterruptedException("Read thread stopping by request"); throw new InvalidOperationException(String.Format("Invalid wait handle return: {0}", handle)); } bool getOverlapped = GetOverlappedResult(_readHandle, overlapped.Overlapped, out bytesRead, true); lastError = Marshal.GetLastWin32Error(); if (!getOverlapped && lastError != ErrorSuccess) throw new Win32Exception(lastError); } if (bytesRead == 0) continue; packetBytes = new byte[bytesRead]; Marshal.Copy(deviceBufferPtr, packetBytes, 0, bytesRead); DebugWrite("Received bytes ({0}): ", bytesRead); DebugDump(packetBytes); int[] timingData = null; if (_decodeCarry != 0 || packetBytes[0] >= 0x81 && packetBytes[0] <= 0x9E) { timingData = GetTimingDataFromPacket(packetBytes); } else { double firmware = 0.0; int indexOfFF = Array.IndexOf(packetBytes, (byte) 0xFF); while (indexOfFF != -1) { if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x0B) // FF 0B XY - Firmware X.Y00 { byte b1 = packetBytes[indexOfFF + 2]; firmware += (b1 >> 4) + (0.1 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 2 && packetBytes[indexOfFF + 1] == 0x1B) // FF 1B XY - Firmware 0.0XY { byte b1 = packetBytes[indexOfFF + 2]; firmware += (0.01 * (b1 >> 4)) + (0.001 * (b1 & 0x0F)); DebugWriteLine("Firmware: {0}", firmware); } if (packetBytes.Length > indexOfFF + 1) indexOfFF = Array.IndexOf(packetBytes, (byte) 0xFF, indexOfFF + 1); else break; } } switch (_readThreadMode) { case ReadThreadMode.Receiving: { IrDecoder.DecodeIR(timingData, _remoteCallback, _keyboardCallback, _mouseCallback); break; } case ReadThreadMode.Learning: { if (timingData == null) { if (_learningCode.TimingData.Length > 0) { _learningCode = null; _readThreadMode = ReadThreadMode.LearningFailed; } break; } if (_learningCode == null) throw new InvalidOperationException("Learning not initialised correctly, _learningCode object is null"); _learningCode.AddTimingData(timingData); // Example: 9F 01 02 9F 15 00 BE 80 int indexOf9F = Array.IndexOf(packetBytes, (byte) 0x9F); while (indexOf9F != -1) { if (packetBytes.Length > indexOf9F + 3 && packetBytes[indexOf9F + 1] == 0x15) // 9F 15 XX XX { byte b1 = packetBytes[indexOf9F + 2]; byte b2 = packetBytes[indexOf9F + 3]; int onTime, onCount; GetIrCodeLengths(_learningCode, out onTime, out onCount); double carrierCount = (b1 * 256) + b2; if (carrierCount / onCount < 2.0) { _learningCode.Carrier = IrCode.CarrierFrequencyDCMode; } else { double carrier = 1000000 * carrierCount / onTime; // TODO: Double-Check this calculation. if (carrier > 32000) { _learningCode.Carrier = (int) (carrier + 0.05 * carrier - 0.666667); // was: _learningCode.Carrier = (int) (carrier + 0.05*carrier - 32000/48000); } else { _learningCode.Carrier = (int) carrier; } } _readThreadMode = ReadThreadMode.LearningDone; break; } if (packetBytes.Length > indexOf9F + 1) { indexOf9F = Array.IndexOf(packetBytes, (byte) 0x9F, indexOf9F + 1); } else { _readThreadMode = ReadThreadMode.LearningFailed; break; } } break; } } } } catch (ThreadInterruptedException ex) { DebugWriteLine(ex.Message); if (_readHandle != null) CancelIo(_readHandle); } catch (Exception ex) { DebugWriteLine(ex.ToString()); if (_readHandle != null) CancelIo(_readHandle); } finally { if (deviceBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(deviceBufferPtr); safeWaitHandle.DangerousRelease(); waitHandle.Close(); } DebugWriteLine("Read Thread Ended"); }
/// <summary> /// Converts an IrCode into raw data for the device. /// </summary> /// <param name="code">IrCode to convert.</param> /// <returns>Raw device data.</returns> private static byte[] DataPacket(IrCode code) { DebugWriteLine("DataPacket()"); if (code.TimingData.Length == 0) return null; byte[] data = new byte[code.TimingData.Length * 4]; int dataIndex = 0; for (int timeIndex = 0; timeIndex < code.TimingData.Length; timeIndex++) { uint time = (uint)(50 * (int)Math.Round((double)code.TimingData[timeIndex] / 50)); for (int timeShift = 0; timeShift < 4; timeShift++) { data[dataIndex++] = (byte)(time & 0xFF); time >>= 8; } } return data; }