📄 ir_decode.cpp
字号:
/*+++ *******************************************************************\
*
* 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 noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2008 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
/////////////////////////////////////////////////////////////////////////////////////////
//NEC-standard IR command codes are 32 bits long and consist of and 8-bit address and an 8-bit
// command. It is transmitted as the address, the inverse of the address, the command,
// and the inverse of the command. The address and command bits are transmitted with
// the least significant bit first.
//
// The NEC command code starts out by transmitting a pulse to indicate the start of
// a command. Shortly after, the command starts. 0's are represented by a short
// space, 1's by a long space. The command data is transmitted only once, but, as
// long as the key is held down, the start code followed by a single bit is transmitted
// every few milliseconds.
//
//
#include "ir_decode.h"
#include "debug.h"
//Long space is the period where the signal is high long enough to signal a 1
const DWORD IR_Decode::DecodeGroup::_min_long_space = 0x9;
const DWORD IR_Decode::DecodeGroup::_max_long_space = 0xF;
//Long space is the period where the signal is high long enough to signal a 0
const DWORD IR_Decode::DecodeGroup::_min_short_space = 0x2;
const DWORD IR_Decode::DecodeGroup::_max_short_space = 0x5;
//Leader code is the period where the signal is low long enough to signal the
// beginning of a command or repeat
const DWORD IR_Decode::DecodeGroup::_min_leader_code = 0x39;
const DWORD IR_Decode::DecodeGroup::_max_leader_code = 0x3D;
//Short repeat is the period where the signal is low following the 'repeat space'
const DWORD IR_Decode::DecodeGroup::_min_short_repeat = 0x2;
const DWORD IR_Decode::DecodeGroup::_max_short_repeat = 0x5;
//Repeat space is the period where the signal is high following a leader code
// in a repeat sequence
const DWORD IR_Decode::DecodeGroup::_min_repeat_space = 0x9;
const DWORD IR_Decode::DecodeGroup::_max_repeat_space = 0xF;
/////////////////////////////////////////////////////////////////////////////////////////
IR_Decode::IR_Decode():
_bit_index(0),
_address(0),
_inverse_address(0),
_command(0),
_inverse_command(0),
_found_leader_code(FALSE),
_command_is_valid(FALSE)
{
_p_decode_group = new DecodeGroup();
}
IR_Decode::~IR_Decode()
{
delete _p_decode_group;
}
/////////////////////////////////////////////////////////////////////////////////////////
ULONG IR_Decode::submitSample(WORD sample, DWORD* p_address)
{
ULONG command = 0xFFFFFFFF;
*p_address = 0;
BYTE current_bit = (sample & 0x8000) ? 1 : 0;
DWORD bit_count = sample & 0x7FFF;
if(_p_decode_group->isLongSpace(current_bit, bit_count))
{
if(_found_leader_code)
{
//If it comes immediately after a leader code,
//it may be a repeat space rather than a long space.
_found_repeat_space = TRUE;
}
else
{
//If we had a long space immediately after a leader code, the
// _found_repeat_space flag will be true. This could have been
// either part of a repeat code or a 1 beginning a command. If
// the next thing was another number, process it as a long space.
if(_found_repeat_space)
{
processLongSpace();
}
_found_repeat_space = FALSE;
processLongSpace();
//If we hit the end of a command, this will retreive it.
command = getCommand(p_address);
}
}
else if(_p_decode_group->isShortSpace(current_bit, bit_count))
{
//If we had a long space immediately after a leader code, the
// _found_repeat_space flag will be true. This could have been
// either part of a repeat code or a 1 beginning a command. If
// the next thing was another number, process it as a long space.
if(_found_repeat_space)
{
processLongSpace();
}
_found_repeat_space = FALSE;
processShortSpace();
//If we hit the end of a command, this will retreive it.
command = getCommand(p_address);
}
else if(_p_decode_group->isShortRepeat(current_bit, bit_count))
{
if(_found_repeat_space && _command_is_valid)
{
//It's a repeat command
command = DECODE_REPEAT_COMMAND;
}
_found_repeat_space = FALSE;
}
if(_p_decode_group->isLeaderCode(current_bit, bit_count))
{
_found_leader_code = TRUE;
_found_repeat_space = FALSE;
//Reset the bit index in case this is leading the new keypress
_bit_index = 0;
}
else
{
_found_leader_code = FALSE;
}
return command;
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Decode::processLongSpace()
{
//Reset if this is the first bit since the command started.
//This initializes all command fields to zero.
if(_bit_index == 0)
{
reset();
}
//Store the bit in the address, inverse address, command, or
// inverse command, depending on the bit index
if(_bit_index < 8)
{
_address |= (1 << _bit_index);
}
else if(_bit_index < 16)
{
_inverse_address |= (1 << (_bit_index - 8));
}
else if(_bit_index < 24)
{
_command |= (1 << (_bit_index - 16));
}
else
{
_inverse_command |= (1 << (_bit_index - 24));
}
_bit_index++;
}
/////////////////////////////////////////////////////////////////////////////////////////
ULONG IR_Decode::processShortRepeat()
{
ULONG command = 0xFFFFFFFF;
if(_found_repeat_space && _command_is_valid)
{
//It's a repeat command
DbgLogTrace(("Found Repeat command %x\n", _command))
DbgLogTrace(("Address %x\n", _address))
command = DECODE_REPEAT_COMMAND;
}
return command;
}
/////////////////////////////////////////////////////////////////////////////////////////
ULONG IR_Decode::getCommand(DWORD* p_address)
{
if(_bit_index == 32)
{
//We've just finished a command!
//Reset the index, (Don't destroy the command in case it repeats.)
_bit_index = 0;
//Return the command if it is valid
//NOTE: These are stored in byte variables to get around a compiler bug.
// If ~_inverse_command is in the if statement, it does the ~ operation
// on 32 bits. So if _command is 5 and _inverse_command is 0xFA,
//~inverse_command is 0xFFFFFF05 which will always fail the comparison. :-(
BYTE temp_command = ~_inverse_command;
if(_command == temp_command)
{
DbgLogInfo(("Found NEC command %x\n", _command));
_command_is_valid = TRUE;
//Get the address. There are two types of NEC commands, one
// that uses the entire 16-bit address field as the address and one
// that sends an 8-bit address and 8-bit inverse address.
//We assume it's using the whole address field if the address and
// inverse address aren't complements of each other.
ULONG address = _address;
BYTE temp_address = ~_inverse_address;
if(temp_address != _address)
{
address |= _inverse_address << 8;
}
*p_address = address;
return _command;
}
else
{
DbgLogError(("Error transmitting command %x\n", _command));
}
}
return 0xFFFFFFFF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -