public void ChangeFilter(IPropoPlusFilter filter) { Filter = filter; Settings.Default.Filter = Filters.First(f => f.Value == filter)?.Metadata?.UniqueIdentifier; Settings.Default.Save(); }
public FilterChangedEventArgs(bool isEnabled, string name = null, string description = null, IPropoPlusFilter filter = null) : this() { Filter = filter; Name = name; Description = description; IsEnabled = isEnabled && filter != null; }
/// <summary> /// <para>Process Pulse for Standard PPM</para> /// <para>A long (over 200 samples) leading high, then a short low, then up to six highs followed by short lows.</para> /// <para>The size of a high pulse may vary between 30 to 70 samples, mapped to joystick values of 1024 to 438</para> /// <para>where the mid-point of 50 samples is translated to joystick position of 731.</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> /// <param name="filterChannels"></param> /// <param name="filter"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } if (width < PpmGlitch) { return; } //if (gDebugLevel >= 2 && gCtrlLogFile && !(_strtime_s(tbuffer, 10))/*&& !(i++%50)*/) // fprintf(gCtrlLogFile, "\n%s - ProcessPulsePpm(width=%d, input=%d)", tbuffer, width, input); /* If pulse is a separator then go to the next one */ if (width < PpmSeparator || FormerSync) { _prevSeparator = true; FormerSync = false; return; } // Two separators in a row is an error - resseting if ((width < PpmSeparator) && _prevSeparator) { _prevSeparator = true; RawChannelCount = 0; DataCount = 0; return; } /* sync is detected at the end of a very long pulse (over 200 samples = 4.5mSec) */ if (/*sync == 0 && */ width > PpmTrig) { Sync = true; if (!DataCount.Equals(0)) { PosUpdateCounter++; } RawChannelCount = DataCount; DataCount = 0; FormerSync = true; _prevSeparator = false; return; } if (!Sync) { /* still waiting for sync */ return; } // Two long pulse in a row is an error - resseting if (width > PpmSeparator) { if (!_prevSeparator) { RawChannelCount = 0; DataCount = 0; _prevSeparator = false; return; } _prevSeparator = false; } // Cancel jitter /* Version 3.3.3 */ width = PrevWidth[DataCount].Filter(width, PpmJitter); int newdata; /* * convert pulse width in samples to joystick position values (newdata) * joystick position of 0 correspond to width over 100 samples (2.25mSec) * joystick position of 1023 correspond to width under 30 samples (0.68mSec) */ if (input || JsChPostProc_selected != -1) { newdata = (int)(1024 - (width - PpmMinPulseWidth) / (PpmMaxPulseWidth - PpmMinPulseWidth) * 1024); /* JR */ } else { newdata = (int)((width - PpmMinPulseWidth) / (PpmMaxPulseWidth - PpmMinPulseWidth) * 1024); /* Futaba */ } /* Trim values into 0-1023 boundries */ if (newdata < 0) { newdata = 0; } else if (newdata > 1023) { newdata = 1023; } /* Update _data - do not allow abrupt change */ if (DataBuffer[DataCount] - newdata > 100) { DataBuffer[DataCount] -= 100; } else if (newdata - DataBuffer[DataCount] > 100) { DataBuffer[DataCount] += 100; } else { DataBuffer[DataCount] = (DataBuffer[DataCount] + newdata) / 2; } //if (input|| m_JsChPostProc_selected!=-1) ChannelData[DataCount] = DataBuffer[DataCount]; /* JR - Assign data to joystick channels */ //else // switch (datacount) //{ // Futaba //case 0: m_Position[1] = data[datacount]; break;/* Assign data to joystick channels */ //case 1: m_Position[2] = data[datacount]; break;/* Assign data to joystick channels */ //case 2: m_Position[0] = data[datacount]; break;/* Assign data to joystick channels */ //case 3: m_Position[3] = data[datacount]; break;/* Assign data to joystick channels */ //case 4: m_Position[4] = data[datacount]; break;/* Assign data to joystick channels */ //case 5: m_Position[5] = data[datacount]; break;/* Assign data to joystick channels */ //case 6: m_Position[6] = data[datacount]; break;/* Assign data to joystick channels */ //case 7: m_Position[7] = data[datacount]; break;/* Assign data to joystick channels */ //case 8: m_Position[8] = data[datacount]; break;/* Assign data to joystick channels */ //case 9: m_Position[9] = data[datacount]; break;/* Assign data to joystick channels */ //case 10: m_Position[10] = data[datacount]; break;/* Assign data to joystick channels */ //case 11: m_Position[11] = data[datacount]; break;/* Assign data to joystick channels */ //}; // Send Position and number of channels to the virtual joystick JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); //if (gDebugLevel >= 3 && gCtrlLogFile /*&& !(i++%50)*/) // fprintf(gCtrlLogFile, " data[%d]=%d", datacount, data[datacount]); if (DataCount == 11) { Sync = false; /* Reset _sync after channel 12 */ } DataCount++; }
/// <summary> /// <para>Process Walkera PCM pulse (Tested with Walkera WK-0701)</para> /// <para>ProcessPulseWalPcm</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> /// <param name="filterChannels"></param> /// <param name="filter"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } width = Convert.ToInt32(Math.Floor(width / PwFutaba)); /* * Sync is determined as 18-bit wide pulse * If detected, move state machine to sync=1 (wait for parity marker) * and initialize all static params */ if (Sync == 0 && width == 18) { Sync = 1; if (DataCount != 0) { PosUpdateCounter++; } Bit = 0; BitStream = 0; BitCount = 0; DataCount = 0; //if (gDebugLevel>=2 && gCtrlLogFile && !( _strtime_s( tbuffer, 9 ))/*!(i++%50)*/) // fprintf(gCtrlLogFile,"\n%s - ProcessPulseFutabaPcm(%d) %02d %02d %02d %02d ; %02d %02d %02d %02d ; %02d %02d %02d %02d ; %02d %02d %02d %02d - %02d %02d %02d %02d ; %02d %02d %02d %02d ; %02d %02d %02d %02d ; %02d %02d %02d %02d", tbuffer, width,\ // data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],\ // data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],\ // data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],\ // data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31]\ // ); return; } if (Sync == 0) { return; } BitStream = (BitStream << width) | (Bit >> (32 - width)); Bit ^= Convert.ToInt32(0xFFFFFFFF); BitCount += width; /* * Parity marker must follow the sync pulse (sync==1) * It might take one of two forms: * - EVEN parity marker is 000011. * - ODD parity marker is 00000011. * If either is found mode state machine to sync=2 (read raw data) */ if (Sync == 0) { if (BitCount >= 6) { BitCount -= 6; if (((BitStream >> BitCount) & 0x3F) == 0x03) { /* Even? */ Sync = 2; DataCount = 0; /* Even: Reset sextet counter to read the first (even) 16 ones */ } else if (((BitStream >> BitCount) & 0x3F) == 0x00) { /* Odd? */ Sync = 2; DataCount = 16; /* Odd: Set sextet counter to 16 to read the last (odd) 16 ones */ BitCount -= 2; } else { Sync = 0; } } return; } /* * Read the next ten bits of raw data * Convert then into a sextet * Increment sextet counter * If data is illegal reset state machine to sync=0 */ if (BitCount >= 10) { BitCount -= 10; if ((DataBuffer[DataCount++] = FutabaSymbol[(BitStream >> BitCount) & 0x3FF]) < 0) { Sync = 0; return; } } /* * Convert sextet data into channel (m_Position) data * Every channel is 10-bit, copied from POS in the corresponding packet. * Every channel is calculated only after the corresponding packet is ready (forth sextet is ready). */ switch (DataCount) { /* Even frame */ case 3: /* 4th sextet of first packet is ready */ if (DataBuffer[0] >> 4 != 0) { ChannelData[2] = (DataBuffer[1] << 4) | (DataBuffer[2] >> 2); /* Ch3: m_Position: packet[6:15] */ } break; case 7: /* 4th sextet of second packet is ready */ if (DataBuffer[0] >> 4 != 0) { ChannelData[3] = (DataBuffer[5] << 4) | (DataBuffer[6] >> 2); /* Ch4: m_Position: packet[6:15] */ } ChannelData[9] = ((DataBuffer[20] >> 4) & 1) * 512; /* Ch 10: One of the auxilliary bits */ break; case 11: /* 4th sextet of 3rd packet is ready */ if (DataBuffer[0] >> 4 != 0) { ChannelData[4] = (DataBuffer[9] << 4) | (DataBuffer[10] >> 2); /* Ch5: m_Position: packet[6:15] */ } break; case 15: /* 4th sextet of 4th packet is ready */ if (DataBuffer[0] >> 4 != 0) { ChannelData[6] = (DataBuffer[13] << 4) | (DataBuffer[14] >> 2); /* Ch7: m_Position: packet[6:15] */ } ChannelData[8] = ((DataBuffer[12] >> 4) & 1) * 512; /* Ch 9: One of the auxilliary bits */ Sync = 0; /* End of even frame. Wait for sync */ break; /* Odd frame */ case 19: /* 4th sextet of 4th packet is ready */ if (DataBuffer[16] >> 4 != 1) { ChannelData[1] = (DataBuffer[17] << 4) | (DataBuffer[18] >> 2); /* Ch2: m_Position: packet[6:15] */ } break; case 23: /* 4th sextet of 4th packet is ready */ if (DataBuffer[16] >> 4 != 1) { ChannelData[0] = (DataBuffer[21] << 4) | (DataBuffer[22] >> 2); /* Ch1: m_Position: packet[6:15] */ } ChannelData[9] = ((DataBuffer[20] >> 4) & 1) * 512; /* Ch 10: One of the auxilliary bits */ break; case 27: /* 4th sextet of 4th packet is ready */ if (DataBuffer[16] >> 4 != 1) { ChannelData[5] = (DataBuffer[25] << 4) | (DataBuffer[26] >> 2); /* Ch6: m_Position: packet[6:15] */ } break; case 31: /* 4th sextet of 4th packet is ready */ if (DataBuffer[16] >> 4 != 1) { ChannelData[7] = (DataBuffer[29] << 4) | (DataBuffer[30] >> 2); /* Ch8: m_Position: packet[6:15] */ } ChannelData[8] = ((DataBuffer[28] >> 4) & 1) * 512; /* Ch 9: One of the auxilliary bits */ break; case 32: Sync = 0; /* End of odd frame. Wait for sync */ RawChannelCount = 10; // Fixed number of channels JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); break; } }
/// <summary> /// <para>Process Walkera PCM pulse (Tested with Walkera WK-0701)</para> /// <para>ProcessPulseWalPcm</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> /// <param name="filterChannels"></param> /// <param name="filter"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } //if (gDebugLevel >= 2 && gCtrlLogFile && i++ % 10 && !(_strtime_s(tbuffer, 9))) // fprintf(gCtrlLogFile, "\n%s - ProcessPulseAirPcm1(%d)", tbuffer, width); if (width < 25) { return; } if (width < 50) { _pulse = 1; } else if (width < 90) { _pulse = 2; } else if (width < 130) { _pulse = 3; } else { _pulse = 4; } // 4-bit pulse marks a bigining of a data chunk if (_pulse == 4) { if (!input) { // First data chunk - clear chunnel counter DataCount = 0; } else { // Second data chunk - get joystick m_Position from channel data ChannelData[0] = Smooth(ChannelData[0], Convert15Bits(DataBuffer[8])); // Elevator (Ch1) ChannelData[1] = Smooth(ChannelData[1], Convert15Bits(DataBuffer[7])); // Ailron (Ch2) ChannelData[2] = Smooth(ChannelData[2], Convert15Bits(DataBuffer[6])); // Throttle (Ch3) ChannelData[3] = Smooth(ChannelData[3], Convert15Bits(DataBuffer[9])); // Rudder (Ch4) ChannelData[4] = Smooth(ChannelData[4], Convert15Bits(DataBuffer[1])); // Gear (Ch5) ChannelData[5] = Smooth(ChannelData[5], Convert15Bits(DataBuffer[2])); // Flaps (Ch6) ChannelData[6] = Smooth(ChannelData[6], Convert15Bits(DataBuffer[3])); // Aux1 (Ch7) ChannelData[7] = Smooth(ChannelData[7], Convert15Bits(DataBuffer[4])); // Aux2 (Ch8) JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); } // Sync bit is set for the first 10 bits of the chunk (No channel data here) Sync = true; BitStream = 0; BitCount = -1; // Mark chunk polarity - 0: Low channels, 1: High channels _chunk = input ? 1 : 0; //return 0; if (DataCount == 5 && width < 160) { PosUpdateCounter++; } } // 9: Read the first 10 bits // 15: Read a channel data var shift = Sync ? 9 : 15; BitStream = ((BitStream << 1) + 1) << (_pulse - 1); BitCount += _pulse; if (BitCount >= shift) { BitCount -= shift; DataBuffer[DataCount] = (BitStream >> BitCount) & 0x7FFF; // Put raw 15-bit channel data DataCount++; Sync = false; if (DataCount >= BufferLength + 2) { DataCount = 0; } } }
public void ChangeFilter(IPropoPlusFilter filter) { Filter = filter; }
protected abstract override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter);
/// <summary> /// <para>Process Pulse for Walkera WK-2401 PPM</para> /// <para>This is just a permiscuous PPM that does not follow the PPM standard</para> /// <para>This is how it works:</para> /// <para>1. Minimal pulse width is 5</para> /// <para>2. Any pulse of over PPMW_TRIG(=200) is considered as a _sync pulse.</para> /// <para>3. _polarity('input') of the Sync pulse is the polarity of the following _data pulses</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> /// <param name="filterChannels"></param> /// <param name="filter"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } //var tbuffer = new char[9]; if (width < 5) { return; } //if (gDebugLevel >= 2 && gCtrlLogFile && !(_strtime_s(tbuffer, 9))) // fprintf(gCtrlLogFile, "\n%s - ProcessPulseWk2401Ppm(width=%d, input=%d)", tbuffer, width, input); //_sync is detected at the end of a very long pulse (over 4.5mSec) if (width > PpmTrig) { Sync = true; if (!DataCount.Equals(0)) { PosUpdateCounter++; } RawChannelCount = DataCount; DataCount = 0; _polarity = input; return; } if (!Sync) { /* still waiting for _sync */ return; } // If this pulse is a separator - read the next pulse if (_polarity != input) { return; } // Cancel jitter /* Version 3.3.3 */ width = PrevWidth[DataCount].Filter(width, PpmJitter); //var jitterValue = Math.Abs(PrevWidth[DataCount].Value - width); //if (jitterValue < PpmJitter) //{ // width = PrevWidth[DataCount].Value; //} //PrevWidth[DataCount].Value = width; /* convert pulse width in samples to joystick Position values (newdata) * joystick Position of 0 correspond to width over 100 samples (2.25mSec) * joystick Position of 1023 correspond to width under 30 samples (0.68mSec)*/ var newdata = (int)((width - PpmMinPulseWidth) / (PpmMaxPulseWidth - PpmMinPulseWidth) * 1024); /* Trim values into 0-1023 boundries */ if (newdata < 0) { newdata = 0; } else if (newdata > 1023) { newdata = 1023; } /* Update _data - do not allow abrupt change */ if (DataBuffer[DataCount] - newdata > 100) { DataBuffer[DataCount] -= 100; } else if (newdata - DataBuffer[DataCount] > 100) { DataBuffer[DataCount] += 100; } else { DataBuffer[DataCount] = (DataBuffer[DataCount] + newdata) / 2; } //Assign _data to joystick channels ChannelData[DataCount] = DataBuffer[DataCount]; // Send Position and number of channels to the virtual joystick ////SendPPJoy(11, _mPosition); JoystickInteraction.Instance.Send(11, ChannelData, filterChannels, filter); //if (gDebugLevel >= 3 && gCtrlLogFile /*&& !(i++%50)*/) // fprintf(gCtrlLogFile, " _data[%d]=%d", _datacount, _data[_datacount]); //Debug.WriteLine($"data[{DataCount}]={DataBuffer[DataCount]}"); if (DataCount == 11) { Sync = false; /* Reset _sync after channel 12 */ } DataCount++; }
/// <summary> /// <para>Process Walkera PCM pulse (Tested with Walkera WK-0701)</para> /// <para>ProcessPulseWalPcm</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> /// <param name="filterChannels"></param> /// <param name="filter"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } //const int fixed_n_channel = 8; //var m_nChannels = 8; int vPulse; width = (int)(width * 44.1 / 192); // Normalize to 44.1K /* Detect Sync pulse - if detected then reset pulse counter and return */ if (width > 56) { _nPulse = 1; return; } ; if (width < 11) { return; } /* Even pulses are binary, Odd pulses are Octal */ if ((_nPulse & 1) != 0) { vPulse = WalkeraConvert2Bin(width); } else { vPulse = WalkeraConvert2Oct(width); } if (vPulse < 8) { _cycle[_nPulse] = vPulse; } _nPulse++; /* At the end of the 50-pulse cycle - calculate the channels */ if (_nPulse == 50) { /* Channels */ var elevator = WalkeraElevator(_cycle); var ailerons = WalkeraAilerons(_cycle); var throttle = WalkeraThrottle(_cycle); var rudder = WalkeraRudder(_cycle); var gear = WalkeraGear(_cycle); var pitch = WalkeraPitch(_cycle); var gyro = WalkeraGyro(_cycle); /* version 3.3.1 */ var ch8 = WalkeraChannel8(_cycle); /* version 3.3.1 */ /* Checksum */ var checkSum = WalkeraCheckSum(_cycle); /* Copy data to joystick positions if checksum is valid (ch1-ch4) */ if (checkSum[0] == _cycle[21] && checkSum[1] == _cycle[22]) { ChannelData[0] = Smooth(ChannelData[0], elevator); ChannelData[1] = Smooth(ChannelData[1], ailerons); ChannelData[2] = Smooth(ChannelData[2], throttle); ChannelData[3] = Smooth(ChannelData[3], rudder); } /* Copy data to joystick positions if checksum is valid (ch5-ch8) */ if (checkSum[2] == _cycle[47] && checkSum[3] == _cycle[48]) { ChannelData[4] = Smooth(ChannelData[4], gear); ChannelData[5] = Smooth(ChannelData[5], pitch); ChannelData[6] = Smooth(ChannelData[6], gyro); ChannelData[7] = Smooth(ChannelData[7], ch8); } _nPulse = 0; //Send2vJoy(fixed_n_channel, m_Position); JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); } }
/// <summary> /// <para>Process Walkera PCM pulse (Tested with Walkera WK-0701)</para> /// <para>ProcessPulseWalPcm</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } //if (gDebugLevel >= 2 && gCtrlLogFile && !(i++ % 50) && !(_strtime_s(tbuffer, 9))) // fprintf(gCtrlLogFile, "\n%s - ProcessPulseJrPcm(%d)", tbuffer, width); if (!Sync && Convert.ToInt32(Math.Floor(2.0 * width / PwJr + 0.5)) == 5) { Sync = true; if (DataCount >= 8) { PosUpdateCounter++; } BitStream = 0; BitCount = -1; DataCount = 0; return; } if (!Sync) { return; } width = Convert.ToInt32(Math.Floor((double)width / PwJr + 0.5)); BitStream = ((BitStream << 1) + 1) << (width - 1); BitCount += width; if (BitCount >= 8) { BitCount -= 8; if ((DataBuffer[DataCount++] = JrSymbol[(BitStream >> BitCount) & 0xFF]) < 0) { for (int dt = 0; dt < DataBuffer.Length; dt++) { DataBuffer[dt] = 0; } Sync = false; return; } } switch (DataCount) { case 3: ChannelData[2] = 1023 - ((DataBuffer[1] << 5) | DataBuffer[2]); break; case 6: ChannelData[0] = 1023 - ((DataBuffer[4] << 5) | DataBuffer[5]); break; case 11: ChannelData[5] = 1023 - ((DataBuffer[9] << 5) | DataBuffer[10]); break; case 14: ChannelData[7] = 1023 - ((DataBuffer[12] << 5) | DataBuffer[13]); break; case 18: ChannelData[3] = 1023 - ((DataBuffer[16] << 5) | DataBuffer[17]); break; case 21: ChannelData[1] = 1023 - ((DataBuffer[19] << 5) | DataBuffer[20]); break; case 26: ChannelData[4] = 1023 - ((DataBuffer[24] << 5) | DataBuffer[25]); break; case 29: ChannelData[6] = 1023 - ((DataBuffer[27] << 5) | DataBuffer[28]); break; case 30: Sync = false; RawChannelCount = BufferLength; // Fixed number of channels JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); break; } ; }
/// <summary> /// <para>Process Walkera PCM pulse (Tested with Walkera WK-0701)</para> /// <para>ProcessPulseWalPcm</para> /// </summary> /// <param name="width"></param> /// <param name="input"></param> protected override void Process(int width, bool input, bool filterChannels, IPropoPlusFilter filter) { if (Monitor.IsEntered(MonitorLock)) { return; } int pulse; int shift; //if (gDebugLevel >= 2 && gCtrlLogFile && !(i++ % 50) && !(_strtime_s(tbuffer, 9))) // fprintf(gCtrlLogFile, "\n%s - ProcessPulseAirPcm2(Width=%d, input=%d)", tbuffer, width, input); if (width < 10) { return; } if (width < 70) { pulse = 1; } else if (width < 140) { pulse = 2; } else { pulse = 7; } if (pulse == 7) // 4-bit pulse marks a biginind of a data chunk { if (!input) { // First data chunk - clear chunnel counter DataCount = 0; } else { // Second data chunk - get joystick m_Position from channel data ChannelData[0] = Smooth(ChannelData[0], Convert20bits(DataBuffer[2])); // Elevator (Ch1) ChannelData[1] = Smooth(ChannelData[1], Convert20bits(DataBuffer[3])); // Ailerons (Ch2) ChannelData[2] = Smooth(ChannelData[2], Convert20bits(DataBuffer[6])); // Throtle (Ch3) ChannelData[3] = Smooth(ChannelData[3], Convert20bits(DataBuffer[7])); // Rudder (Ch4) ChannelData[4] = Smooth(ChannelData[4], Convert20bits(DataBuffer[1])); // Gear (Ch5) ChannelData[5] = Smooth(ChannelData[5], Convert20bits(DataBuffer[5])); // Flaps (Ch6) RawChannelCount = 6; JoystickInteraction.Instance.Send(RawChannelCount, ChannelData, filterChannels, filter); if (width < 420 && width > 390) { PosUpdateCounter++; } }; Sync = true; // Sync bit is set for the first 10 bits of the chunk (No channel data here) BitStream = 0; BitCount = -1; _chunk = input; // Mark chunk polarity - 0: Low channels, 1: High channels //return 0; } ; if (Sync) { shift = 7; // Read the first 10 bits } else { shift = 20; // Read a channel data }; BitStream = ((BitStream << 1) + 1) << (pulse - 1); BitCount += pulse; if (BitCount >= shift) { BitCount -= shift; DataBuffer[DataCount] = (BitStream >> BitCount) & 0xFFFFF; // Put raw 20-bit channel data DataCount++; Sync = false; if (DataCount >= 8) { DataCount = 0; } } ; return; }