📄 rc5decode.cpp
字号:
//
// File: rc5decode.cpp
// Description: implementation of class RC5Decode
//
// Created: Wed. Jan 15, 2003
//
//
// Copyright and Disclaimer:
//
// ---------------------------------------------------------------
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL CONEXANT BE LIABLE TO ANY PARTY FOR DIRECT,
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
// AND ITS DOCUMENTATION, EVEN IF CONEXANT HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2000-2001 Conexant Systems, Inc.
//
// All Rights Reserved.
// ---------------------------------------------------------------
//
// Module Revision Id:
//
//
#include "common.h"
#include "rc5decode.h"
/////////////////////////////////////////////////////////////////////////////////////////
// RC5 commands are 14 bits in length. Two start bits, one toggle bit, 5 address bits,
// and 6 command bits. The first start bit is always 1. The second start bit could
// be zero if the remote wants to address a very high-numbered device. The toggle bit
// changes state every time a button is pressed on the remote so that it is possible to
// tell when a single button was pressed multiple times. The address is usually 0, and
// represents the device the command is directed to.
//
// When a button is pressed on the remote, the command for that button is sent over and
// over again until the user stops pressing the button.
//
// Each bit of a command takes the same amount of time to send and changes state, from
// zero to one, or from one to zero, at the midpoint of the command. Therefore, a one
// would be several zeros followed by several ones.
//
// Our device inverts these bits, however. We get a long string of ones when the remote
// is not active. There are also long strings of ones between key presses which mark the
// end of a command.
//
// The class works by searching for groups of zeros and groups of ones. It can also handle
// double groups of each type. Double groups occur whenever a 1 follows a 0 or a 0 follows
// a 1. The group size is defined by the constant members
// _min_bits_in_group and _max_bits_in_group. These numbers could be changed to support
// remotes that might send longer or shorter pulses.
//
// The class closes a group or double group when the next bit in the incoming stream is
// of a different value. If there is a long stream of ones, it is acknowledged as such
// as soon as it becomes larger than the largest double group. When a large string of
// ones is recognized, the class attempts to complete the previous command and reset the
// class to receive the next command.
//
/////////////////////////////////////////////////////////////////////////////////////////
//_min_bits_in_group and _max_bits_in_group define the size of
// groups of 0's and 1's. These values may need to be adjusted for
// remote controls that take longer or shorter to transmit each bit.
//
// A group is valid if the number of 0's or 1's in the group falls
// between these values.
//
// A double group is between _max_bits_in_group+1 and 2*_max_bits_in_group.
//
const BYTE RC5Decode::_min_bits_in_group = 2;
const BYTE RC5Decode::_max_bits_in_group = 4;
/////////////////////////////////////////////////////////////////////////////////////////
//RC5Decode::RC5Decode
//
// Constructor
//
RC5Decode::RC5Decode(DWORD ir_command_table):
_group_index(0),
_bit_count(0),
_current_bit(0),
_last_command(0),
_rc5_command((BYTE)ir_command_table)
{
}
/////////////////////////////////////////////////////////////////////////////////////////
//RC5Decode::submitSample
//
// This is the main entry point, called when there is a DWORD sample available. The
// function resolves the sample into groups of 0's or 1's, and calls foundGroup() for
// each group of a valid size that it finds.
//
// foundEndOfCommand() is called when a long string of 1's is recognized, marking the
// boundary between commands.
//
// The samples can cross DWORD boundaries, so this function saves the current bit it is
// looking at and the number of bits found in the group in _bit_count and _current_bit.
//
// Returns the command if it finds the end of a command in the current DWORD. Otherwise,
// it returns 0xFFFFFFFF.
//
ULONG RC5Decode::submitSample(DWORD sample)
{
ULONG command = 0xFFFFFFFF;
//Search for groups of bits in the sample
for(LONG i = 31; i >= 0; i--)
{
BYTE current_bit = getBit(sample, (BYTE)i);
if(current_bit == _current_bit)
{
//Another bit in the current group.
_bit_count++;
if((current_bit == 1) && (_bit_count == 2*_max_bits_in_group + 1))
{
//When we have more than a double group of ones, the command
// has finished transmitting.
command = foundEndOfCommand();
}
}
else
{
dbgLogTrace(("Found group of %d, %d's\n", _bit_count, _current_bit));
//We've just switched to a new group. Check if the
// last group was valid.
if((_bit_count >= _min_bits_in_group) &&
(_bit_count <= _max_bits_in_group))
{
//Found a valid group
foundGroup((GROUP_TYPE)_current_bit);
}
//Check for a double group: > max bits, but less than 2* max bits
else if ((_bit_count > _max_bits_in_group) &&
(_bit_count <= 2*_max_bits_in_group))
{
//Found a valid double group
foundGroup((GROUP_TYPE)_current_bit);
foundGroup((GROUP_TYPE)_current_bit);
}
//Switch the bit to check and reset the bit count
_current_bit = current_bit;
_bit_count = 1;
}
}
return command;
}
/////////////////////////////////////////////////////////////////////////////////////////
//RC5Decode::foundEndOfCommand
//
// The end of a command is detected when a large group of ones is detected. (More than
// the maximum for a double group)
//
// If the command ended in a zero, the last group of ones in the last zero is part of
// the large group of ones detected after the command. In this case we need to add a last
// group of ones to our array of groups.
//
// This function checks to see if the right number of groups have been stored in the
// array. If the number of groups is correct, it attempts to resolve them into a command.
//
// Returns the command found or 0xFFFFFFF if no command was available.
//
ULONG RC5Decode::foundEndOfCommand()
{
//If we are short one group, the last group must
// have been a group of ones. Insert it now.
if(_group_index == (BITS_PER_COMMAND*GROUPS_PER_BIT-1))
{
foundGroup(GROUP_OF_ONES);
}
//If we have the correct number of groups, resolve them
// into a command
ULONG command = 0xFFFFFFFF;
if(_group_index == BITS_PER_COMMAND*GROUPS_PER_BIT)
{
command = getCommand();
if(command != 0xFFFFFFFF)
{
dbgLogTrace(("Found command %x\n", command));
}
}
//Reset the array for the next command
_group_index = 0;
//Add an initial group of ones. RC5 commands always start with a one, which means
// that the first group of ones is in the group between commands.
foundGroup(GROUP_OF_ONES);
return command;
}
/////////////////////////////////////////////////////////////////////////////////////////
//RC5Decode::getCommand
//
// getCommand is called when the class thinks it has found a valid command. This function
// resolves the groups of 0's and 1's found, and stored in _group_array into an RC5 command.
//
// It returns the command, or 0xFFFFFFFF if the command is not valid.
//
ULONG RC5Decode::getCommand()
{
//There must be 28 groups for the command to be valid.
if(_group_index != (BITS_PER_COMMAND*GROUPS_PER_BIT))
{
return 0xFFFFFFF;
}
ULONG command = 0;
for(BYTE index = 0; index < (BITS_PER_COMMAND*GROUPS_PER_BIT); index = index + 2)
{
if((_group_array[index] == GROUP_OF_ONES) &&
(_group_array[index+1] == GROUP_OF_ZEROS))
{
//We have a one if there is a group of ones followed by a group of zeros.
//The bits need to be or'ed into the command in reverse order
command |= ( 1 << (BITS_PER_COMMAND - (index/2) - 1));
}
else if((_group_array[index] == GROUP_OF_ZEROS) &&
(_group_array[index+1] == GROUP_OF_ONES))
{
//We have a zero if there is a group of zeros followed by a group of ones.
//There's no need to or in zero's
}
else
{
//Invalid command if there are two groups of zero or one for a single bit
return 0xFFFFFFFF;
}
}
if(command == _last_command)
{
command = DECODE_REPEAT_COMMAND;
}
else
{
_last_command = command;
_rc5_command.initialize(command);
}
return command;
}
IR_Command* RC5Decode::getIrCommand()
{
return &_rc5_command;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -