⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ir_decode.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 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 + -