File: RC6RC5Decoder
Details
File: RC6RC5Decoder.cs
Dir: http://www.ofitselfso.com/IRSky/IRSky.php
Date: Mon, Dec 15, 2014
using System;
using System.Threading;
using BBBCSIO;
/// +------------------------------------------------------------------------------------------------------------------------------+
/// | TERMS OF USE: MIT License |
/// +------------------------------------------------------------------------------------------------------------------------------|
/// |Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
/// |files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
/// |modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
/// |is furnished to do so, subject to the following conditions: |
/// | |
/// |The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
/// | |
/// |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
/// |WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
/// |COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
/// |ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
/// +------------------------------------------------------------------------------------------------------------------------------+
namespace IRSkyBBB
{
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
///
/// RC6RC5Decoder - Provides signal decoding functionality for SKY+ IR Remotes
/// but should be adaptable for any IR Remote using the RC5 or
/// RC6 protocol
///
/// Some notes on SKY+ remotes
///
/// SKY+ remotes operate in two modes: SKY mode and TV mode. SKY Mode is toggled on
/// when the SKY button is pressed and most buttons will then emit IR codes which
/// use the RC6-6-20 protocol. The TV mode is toggled on when the TV button is
/// pressed. The IR codes emitted in this mode are intended to control a TV, not
/// the Sky box, and since TV's use a wide variety of IR protocols the codes output
/// are dependent on the current TV setting of the SKY remote. If the SKY remote
/// is configured to a Phillips TV then the output codes will be standard
/// RC5. It is up to the user to configure the remote to the type of TV (see below)
///
/// There are specific exceptions. Some buttons (Volume+/- and Mute) always emit
/// the configured TV codes even in SKY mode. Some buttons do not send any codes in
/// TV mode (Play, Pause) and some (TV Guide, Box Office) always toggle SKY mode
/// back on and then send a SKY mode code.
///
/// NOTE: In order for this code to properly interpret all buttons on the SKY+ remote
/// the SKY + remote must be set to a Phillips TV. This makes the buttons send RC5
/// IR remote codes in TV Mode. To set a SKY+ remote into Phillips RC5 TV mode
/// have a look at the link below
///
/// http://www.skyremotecodes.co.uk/Philips-sky-remote-codes
///
/// This signal interpretation is designed to be both accurate and lossy. What this
/// means is that it may not get every signal the IR remote sends but for the IR codes
/// it does receive, the processing will be complete and reasonably error checked. The
/// reception and processing of every IR code is not usually expected when using a remote
/// - they repeat the codes as long as the button is pressed in order to ensure something
/// makes it through. However, if a code is received, it should be accurate.
///
/// Some links which may help you understand the RC5, RC6 and RC6 Mode 6 protocols
///
/// RC6 PROTOCOL
/// http://www.sbprojects.com/knowledge/ir/rc6.php
/// http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/
///
/// RC6 MODE 6A PROTOCOL
/// http://www.guiott.com/wrc/RC6-6.html
///
/// RC5 PROTOCOL
/// http://www.sbprojects.com/knowledge/ir/rc5.php
///
/// Ultimately every IR code received is placed in the latestProcessedIRSignalBytes
/// int variable. This is overwritten as new ones come in and are processed. The
/// processing is done in the interrupt of the last pulse of the signal. It is
/// up to the external code to poll this value often enough to get each value
/// if that is what it needs.
///
/// The data output is the complete information in the signal including SMODE
/// CONTROL, TOGGLE and INFO fields as appropriate to the protocol. Also included
/// is a field which indicates if the signal came in as RC6 or RC5. All of this
/// data is bundled up and stuffed into an Int32 for easy transport. See the
/// comments below on OUTPUT DATA for the structure of this Int32
///
/// NOTE: the SKY+ remote does not seem to send a toggle bit in RC6 - it is
/// always 0. In RC5 mode the toggle bit will change as expected
///
/// This code is written in C#, for a Beaglebone Black and uses the BBBCSIO Library
///
/// Tested with a Sparkfun IR Receiver Breakout SEN-08554 and a SKY+ Remote Rev4
/// Also tested with a SKY+ Remote Rev6
///
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public class RC6RC5Decoder
{
// this is the interrupt on which the IR Receiver places its pulses
public InterruptPortMM edgeInterrupt = null;
// this is the decoder for the IR pulses
public ManchesterDecoder manchesterDecoder = null;
// this is the number of 1T time periods we expect to see in a RC6-6-20 signal
// NOTE: if the last bit is a 0 we will get a H->L transition to mark it.
// If it is a 1, manchester encoding is already low so it does not go high again
// this means we do not get a 60th trailing pulse to mark the end of the last
// odd bit. We could add this ourselves from the timing but as you will see
// when you read the comments in the ProcessPulsesReceivedRC6_6_20 function
// we can safely ignore its non-presence
private const int SKYPLUS_RC6_6_20_PULSECOUNT = 59;
// this is the number of 1T time periods we expect to see in a RC5 signal
private const int SKYPLUS_RC5_PULSECOUNT = 52;
// used to embed the protocol type in the output databytes
private const int RC5_PROTOCOLFLAG = 1;
private const int RC6_PROTOCOLFLAG = 2;
// this is the number of complete and valid IR codes we have processed
private int processedIRCodeCount = 0;
// this is the number of processed IR Codes that were consumed by an
// external object calling GetData();
private int consumedIRCodeCount = 0;
// if true, data is ready. If false - no new data.
// the GetData() call will reset this to false
private bool dataReady=false;
// OUTPUT DATA
// latestProcessedIRSignalBytes is the data which we have processed out of
// the IR pulse stream we represent it as an int (4 bytes) because that is
// such an handy way of passing information around. It is a value type - not
// an object and so we do not have the object creation overhead and subsequent
// garbage collection etc.
// The data will be returned as nibbles and bytes. The meaning is dependent
// on the protocol being interpreted. All diagrams are MSB to LSB each [] is
// a byte
// FOR RC6-6-20 (most keys on SKY+ remotes in SKY mode)
// [protocol|modeField][controlField][trailerField|sField][infoField]
// where
// protocol - 4 bit nibble hardcoded to RC6_PROTOCOLFLAG
// modefield - 4 bit nibble with the mode number. will be 6 for RC6-6
// controlField - 8 bits of the control field information
// trailerField - 4 bit nibble which will be either 1 or 0
// sField - 4 bit nibble containing the sField info 0x0c for SKY+ remotes
// infoField - 8 bits of information from the information field
// FOR RC5 (most keys on SKY+ remotes in TV mode with Phillips TV configured)
// [protocol|0000][controlField][trailerField|0000][infoField]
// where
// protocol - 4 bit nibble hardcoded to RC5_PROTOCOLFLAG
// controlField - 8 bits of the control field information
// trailerField - 4 bit nibble which will be either 1 or 0
// infoField - 8 bits of information from the information field
private int latestProcessedIRSignalBytes = 0;
// used to sync access to the returning data
private object lockObject = new object();
// for diagnostics
public int lastProcessPulsesResult = 0;
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Constructor
/// </summary>
/// <param name="eventInterruptModeIn">The interrupt mode</param>
/// <param name="gpioIn">The GPIO this interrupt is on.
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public RC6RC5Decoder(GpioEnum gpioIn, InterruptMode eventInterruptModeIn)
{
// build the interrupt, note we are trapping both rising and falling interrupts here
edgeInterrupt = new InterruptPortMM(gpioIn, eventInterruptModeIn);
// Set the interrupt handler.
edgeInterrupt.OnInterrupt += new InterruptEventHandlerMM(HandleEdgeInterrupt);
// we will not get any data if it is not enabled
edgeInterrupt.EnableInterrupt();
// build the decoder class
manchesterDecoder = new ManchesterDecoder();
manchesterDecoder.ResetForNewInput(11);
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Handle an edge interrupt. This is the function that will get the incoming
/// interrupts from the class edgeInterrupt.
///
/// The basic operation is to call the decoder for every pulse. When the decoder
/// is done we see how many pulses we have. If everything looks right for an
/// RC5 or RC6 signal we process it into bits and place it in the
/// latestProcessedIRSignalByte variable for consumption by some process that polls
/// for it. The update and read of latestProcessedIRSignalBytes variable is done
/// in a lock.
///
/// SPEED matters here - you are in an interrupt - do not faff around
///
/// </summary>
/// <param name="evGpio">The gpio the event is configured on</param>
/// <param name="evState">The event state (1 or 0)</param>
/// <param name="evTime">The event datetime</param>
/// <param name="evData">The event data structure</param>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public void HandleEdgeInterrupt(GpioEnum evGpio, bool evState, DateTime evDateTime, EventData evData)
{
uint data2 ;
// should never happen
if (evData == null) return;
// should never happen
if (evData.PortObject == null) return;
// set the data2 and time variables so we can be consistent with the standard IRSky Implementation
if (evData.EvValue == 0) data2 = 0;
else data2 = 1;
// we differentiate based on rising or falling pulses
if (data2 == 1)
{
manchesterDecoder.RecordPulseEvent(PulseTypeEnum.PULSE_FALLING, evDateTime);
}
else
{
manchesterDecoder.RecordPulseEvent(PulseTypeEnum.PULSE_RISING, evDateTime);
}
// by the time we get here we have added the signal content to the pulseArray
// in the decoder and that array will contain a sequence of 1T pulse information
// see the comments in that class for more details
// certain byte counts are triggers to tell us process data
if ((manchesterDecoder.RC6Detected==false) && (manchesterDecoder.PulsesReceived == SKYPLUS_RC5_PULSECOUNT))
{
// we may well have an even RC5 command from the sky+ IR remote
lastProcessPulsesResult = ProcessPulsesReceivedRC5();
// always reset - we are done here
manchesterDecoder.ResetForNewInput(22);
}
else if ((manchesterDecoder.RC6Detected==true) && (manchesterDecoder.PulsesReceived == SKYPLUS_RC6_6_20_PULSECOUNT))
{
// we may well have an even RC6-6-20 command from the sky+ IR remote
lastProcessPulsesResult = ProcessPulsesReceivedRC6_6_20();
// always reset - we are done here
manchesterDecoder.ResetForNewInput(23);
}
// make sure we clear
evData.PortObject.ClearInterrupt();
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Processes the pulses in the signal decoder as if it were an RC5 signal
///
/// NOTE: we are still in the interrupt when this is called. SPEED is of the essence!
///
/// </summary>
/// <returns>z success - ir code processed, nz fail code provides reason</returns>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
private int ProcessPulsesReceivedRC5()
{
int pulseArray = manchesterDecoder.PulsesReceived;
int trailerField = 0;
int infoField = 0;
int controlField = 0;
// there are an assumed two -2 1T pulses here which will not be recorded by the
// decoder. We begin processing on the rising part of the first pulse
// we require the first 2 values to be "+2" this indicates that the first start
// pulse happened.
if (manchesterDecoder.pulseArray[0] != 2) return 10;
// we can assume the following and do not need to test - see notes in the decoder
// if (manchesterDecoder.pulseArray[1] != 2) return false;
// we require the next two values to be "-2" this indicates that the low
// part of the second start pulse happened.
if (manchesterDecoder.pulseArray[2] != -2) return 11;
// the line below can be assumed
// if (manchesterDecoder.pulseArray[3] != -2) return false;
// we require the next two values to be "+2" or +4 this indicates that the high
// part of the second start pulse happened.
if (((manchesterDecoder.pulseArray[4] == 2) || (manchesterDecoder.pulseArray[4] == 4))==false) return 12;
// the line below can be assumed
// if (manchesterDecoder.pulseArray[5] != 2 ...or... 4) return false;
// A NOTE on how we decode the pulses into bits. Once we get past the first start
// pulses with its missing leading low, each bit is represented by four sequential
// values in the manchesterDecoder.pulseArray array putting those in there is pretty
// much the entire purpose of the manchesterDecoder - review the comments there
// These pulses will either be LowLow then HighHigh represented by a -ve-ve+ve+ve
// which in RC5 is a 1. Or a HighHigh then LowLow represented by a +ve+ve-ve-ve
// which in RC5 is a 0. No other permutations permitted by the protocol.
// If manchesterDecoder.pulseArray[10] is < 0 and manchesterDecoder.pulseArray[12]>0
// we have a 1 bit. Of course this assumes we know to consider [10] and [12] as the bit
// and not [11],[13] Or [12],[14]. However, at this point we are pretty sure we know where
// we are in the signal so as long as we did not miss the start pulses we are pretty
// sure we are interpreting correctly
// So the upshot is that for any one bit we do not have to look at all 1T values that
// make it up. Remember we are optimizing for speed here. All we need to do is look at
// the even numbered array entries. If this is -ve we have a 0, if it is +ve we have a 1
// this saves time.
// the next 4 slots will be the Trailer - as discussed above all we need to do is look at
// the first slot
if (manchesterDecoder.pulseArray[6] < 0) trailerField = 0;
else if (manchesterDecoder.pulseArray[6] > 0) trailerField = 1;
else return 13;
// now we parse the control field. This begins at array entry [10]
// or 10T if we are counting that way, We build the control byte
// from the ones and zeros
if (manchesterDecoder.pulseArray[10] < 0) controlField++; // msb
controlField <<= 1;
if (manchesterDecoder.pulseArray[14] < 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[18] < 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[22] < 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[26] < 0) controlField++; // lsb
// now we parse the command data. This begins at array entry [30]
// or 30T if we are counting that way, We build the info byte
// from the ones and zeros
if (manchesterDecoder.pulseArray[30] < 0) infoField++; // msb
infoField <<= 1;
if (manchesterDecoder.pulseArray[34] < 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[38] < 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[42] < 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[46] < 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[50] < 0) infoField++; // lsb
// set the output data, we do this inside a lock
lock (lockObject)
{
// build our output int - in the format is below [is a byte] pipes "|" are nibble separators
// [protocol|0000][controlField][trailerField|0000][infoField]
latestProcessedIRSignalBytes = (RC5_PROTOCOLFLAG << 28) + (controlField << 16) + (trailerField << 12) + infoField;
processedIRCodeCount++;
dataReady = true;
}
// it is all good
return 0;
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Processes the pulses in the signal decoder as if it were an RC6-6-20 signal
///
/// NOTE: we are still in the interrupt when this is called. SPEED is of the essence!
///
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
private int ProcessPulsesReceivedRC6_6_20()
{
int pulseArray = manchesterDecoder.PulsesReceived;
int modeField =0;
int trailerField = 0;
int infoField = 0;
int controlField = 0;
int sField = 0;
// we require the first 6 values to be "+6" this indicates that the 6T starting
// pulse happened.
if (manchesterDecoder.pulseArray[0] != 6) return 100;
// we can assume the following and do not need to test - see notes in the decoder
// if (manchesterDecoder.pulseArray[1] != 6) return false;
// if (manchesterDecoder.pulseArray[2] != 6) return false;
// if (manchesterDecoder.pulseArray[3] != 6) return false;
// if (manchesterDecoder.pulseArray[4] != 6) return false;
// if (manchesterDecoder.pulseArray[5] != 6) return false;
// we require the next two values to be "-2" this indicates that the 2T low
// part of the start pulse happened.
if (manchesterDecoder.pulseArray[6] != -2) return 200;
// the line below can be assumed
// if (manchesterDecoder.pulseArray[7] != -2) return false;
// A NOTE on how we decode the pulses into bits. Once we get past the leader
// (and other than the trailer bit special case at positions 16-19) each bit
// is represented by two sequential values in the manchesterDecoder.pulseArray array
// that is pretty much the entire purpose of the manchesterDecoder - review the comments there
// These pulses will either be a High to Low (H->L) transition represented by a +ve and
// a subsequent -ve. Or a Low to High (L->H) represented by a -ve and a subsequent
// +ve. Thats it. There is never a case of +ve,+ve or -ve,-ve outside of the leader
// and trailer. This is not permitted by the protocol and if it occurred would
// immediately reset the decoder software so it will never appear in there.
// so if manchesterDecoder.pulseArray[10] is > 0 and manchesterDecoder.pulseArray[11]<0
// we have a 1 bit. Of course this assumes we know to consider [10] and [11] as the bit
// and not [11],[12]. We know to start on the even entries because (once again) the
// decoder has busted the signal up on 1T boundaries and all pulses, even the special cases
// take an even number of 1T time periods to complete - the protocol specifies this.
// So the upshot is that for regular single bit transitions, we do not have to look at
// both values. Remember we are optimizing for speed here. All we need to do is look at
// the even numbered array entries. If this is -ve we have a 0, if it is +ve we have a one
// this saves time.
// check the start bit is 1 (+ve,-ve) - the protocol requires this
if (manchesterDecoder.pulseArray[8] <=0) return 300;
// now the mode bits in slots [10], [12] and [14]
if (manchesterDecoder.pulseArray[10] > 0) modeField = modeField + 4; // msb of 3 mode bits
if (manchesterDecoder.pulseArray[12] > 0) modeField = modeField + 2; // middle of 3 mode bits
if (manchesterDecoder.pulseArray[14] > 0) modeField = modeField + 1; // lsb of 3 mode bits
// the trailer bit is a special case and will be the next 4 slots. These this will
// either be a -2-2+2+2 which signals a 0 bit (L->H) over two 2T periods) or a
// +2+2-2-2 which signals a 1 bit (H->L) Either way we can figure out what it is
// just by looking at the first value. We do both tests because we want
// to check for a +/- 2 and fail if that is not there
if (manchesterDecoder.pulseArray[16] < 0) trailerField = 0;
else if (manchesterDecoder.pulseArray[16] > 0) trailerField = 1;
else return 400;
// now we parse the control field. This begins at array entry [20]
// or 20T if we are counting that way, We build the control byte
// from the ones and zeros
if (manchesterDecoder.pulseArray[20] > 0) controlField++; // msb
controlField <<= 1;
if (manchesterDecoder.pulseArray[22] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[24] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[26] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[28] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[30] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[32] > 0) controlField++;
controlField <<= 1;
if (manchesterDecoder.pulseArray[34] > 0) controlField++; // lsb
// now we parse the S field. This begins at array entry [36]
// or 36T if we are counting that way, We build the s nibble
// from the ones and zeros
if (manchesterDecoder.pulseArray[36] > 0) sField++; // msb
sField <<= 1;
if (manchesterDecoder.pulseArray[38] > 0) sField++;
sField <<= 1;
if (manchesterDecoder.pulseArray[40] > 0) sField++;
sField <<= 1;
if (manchesterDecoder.pulseArray[42] > 0) sField++; // lsb
// now we parse the information data. This begins at array entry [44]
// or 44T if we are counting that way, We build the info byte
// from the ones and zeros
if (manchesterDecoder.pulseArray[44] > 0) infoField++; // msb
infoField <<= 1;
if (manchesterDecoder.pulseArray[46] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[48] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[50] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[52] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[54] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[56] > 0) infoField++;
infoField <<= 1;
if (manchesterDecoder.pulseArray[58] > 0) infoField++; // lsb
// set the output data, we do this inside a lock
lock (lockObject)
{
// build our output int - the format is below [is a byte], pipes "|" are nibble separators
// [protocol|modeField][controlField][trailerField|sField][infoField]
latestProcessedIRSignalBytes = (RC6_PROTOCOLFLAG << 28) + (modeField << 24) + (controlField << 16) + (trailerField << 12)+ (sField << 8) + infoField;
processedIRCodeCount++;
dataReady = true;
}
// it is all good
return 0;
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Detects if data is available
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public bool IsDataAvailable()
{
// no need to lock() here. it is either ready or it isn't
return dataReady;
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the 4 data bytes as an int. The meaning of those bytes is dependent on
/// the protocol interpreted. See the comments. If this is called when
/// DataReady != true it will just return whatever happens to be in the
/// latestProcessedIRSignalBytes value at that time. It does not check.
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public int GetData()
{
// we do this inside a lock
lock (lockObject)
{
dataReady=false;
consumedIRCodeCount++;
return latestProcessedIRSignalBytes;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the number of times we processed a complete IR code. Does not indicate
/// if it was actually consumed by a GetData() call
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public int ProcessedIRCodeCount
{
get
{
return processedIRCodeCount;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the number of times we processed a complete IR code. This is the number
/// actually consumed by a GetData() call
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public int ConsumedIRCodeCount
{
get
{
return consumedIRCodeCount;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the number of times we reset for a new code. This value includes
/// corrupted streams that were discarded as well as complete IR codes that
/// were processed and/or consumed
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public int ResetCount
{
get
{
return manchesterDecoder.PulseArrayResetCount;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Returns a marker code indicating the reason for the last reset
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public int LastResetReason
{
get
{
// this the marker indicating the reason for the last reset
return manchesterDecoder.LastResetReason;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Forces a reset on the manchesterDecoder object
/// </summary>
/// <history>
/// 20 Jan 14 Cynic - originally written
/// </history>
public void ForceReset()
{
// just reset it
manchesterDecoder.ResetForNewInput(99);
}
}
}