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

📄 irc_1200.c

📁 WinCE 5.0下的软件解码红外遥控器的指令
💻 C
字号:

#include <windows.h>
#include <Pm.h>

#include "platform.h"
#include "bceddk.h"
#include "gpio.h"

#define IRC_DATA_PIN  (203-200)  

// Use the Software Counter as our tick base
#define IRC_CLOCK_SWCNT

DWORD g_dwIrcSysIntr;

// Set IRC thread at the highest real-time priority
#define IRC_THREAD_PRIO (0)

BOOL g_bExit = FALSE;
HANDLE g_hIrdaDataIST = NULL;
HANDLE g_hIrdaDataEvent = NULL;

static DWORD WINAPI IRCDecodeIST(LPVOID pContext);
void IRCDispatchCode(BYTE key);

////////////////////////////////////////////////////////////////////////////////

static UINT32 g_dwIRCTick0 = 0;
static UINT32 g_dwIRCTick1 = 0;

static UINT32 g_dwIRCBitCount = 0;
static UINT32 g_dwIRCBitCode = 0;

static VOID IRCDecodeHelper(VOID);

////////////////////////////////////////////////////////////////////////////////


DWORD IRC_Open(DWORD hDeviceContext,
			   DWORD AccessCode,
               DWORD ShareMode)
{
	return hDeviceContext;
}

BOOL IRC_Close(DWORD hOpenContext) 
{ 
	return TRUE; 
}

DWORD IRC_Read(DWORD hOpenContext,
               LPVOID pBuffer,
               DWORD Count)
{
	return 0;
}

DWORD IRC_Seek(DWORD hOpenContext,
               long Amount,
               DWORD Type)
{
	return 0;
}

DWORD IRC_Write(DWORD hOpenContext,
                LPCVOID pBuffer,
                DWORD Count)
{
	return 0;
}

VOID IRC_PowerDown(DWORD hDeviceContext) 
{ 
	
}

VOID IRC_PowerUp(DWORD hDeviceContext)
{ 
	
}

BOOL IRC_IOControl(DWORD Handle, 
                   DWORD dwIoControlCode, 
                   PDWORD pInBuf, 
                   DWORD nInBufSize,
                   PBYTE pOutBuf, 
                   DWORD nOutBufSize, 
                   PDWORD pBytesReturned)
{
	return TRUE;
}

BOOL IRC_Deinit(DWORD hContext)
{
    g_bExit = TRUE;
    CloseHandle(g_hIrdaDataEvent);
    CloseHandle(g_hIrdaDataIST);
    
	return TRUE;
}



BOOL IRC_Init(DWORD dwContext)
{
    UINT32 pinDir;
    
	RETAILMSG(1, (TEXT("IrDA Remote Control: +IRC_Init\r\n")));
	
    {
        // Set IRC_DATA GPIO as input (GPIO2_DIR = 0xB1700000)        
        pinDir = *(volatile UINT32 *)(0xB1700000);   
        __asm("sync");
        pinDir &= (~(0x1 << IRC_DATA_PIN));
        *(volatile UINT32 *)(0xB1700000) = pinDir;
        __asm("sync");
    }  

#ifdef IRC_CLOCK_SWCNT

    // Enable the Software Counter by setting swcnt_control[EN] = 1
    *(volatile UINT32 *)(0xB110010C) = 1;

#else
    
    // We don't use the sys_rtcread as RTC is running at 1ms at WinCE and
    // RTC ticks are used by keyboard and mouse drivers!
    // Set sys_toytrim to let sys_toyread running at 32.768KHz resulution
    // FIXME!!
    while ((*(volatile UINT32 *)(0xB1900014)) & (0x1<<4));
    *(volatile UINT32 *)(0xB1900000) = 0;
    while ((*(volatile UINT32 *)(0xB1900014)) & (0x1<<4));
    
#endif
    
	g_hIrdaDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  //初始化全局事件

    if (g_hIrdaDataEvent == NULL)     
    {
        RETAILMSG(1, (TEXT("IRC_Init:: CreateEvent g_hIrDAData failed\r\n")));
        return FALSE;
    }
    
    //把事件与中断关联在一起
    g_dwIrcSysIntr = InterruptConnect(Internal,
	                                  0,
	                                  HWINTR_EXT_IRC,   
	                                  0);
	                                
    if (g_dwIrcSysIntr == SYSINTR_NOP)  
    	/*果该中断未注册,则返回 SYSINTR_NOP 
ISR 返回下列值之一: 

 SYSINTR_NOP — 没有任何 ISR 包含该中断 
 
SYSINTR_RESCHED — 重新调度计时器已到期 
 
 SYSINTR — ISR 已经包含该中断 
 
 SYSINTR_RTC_ALARM — 闹钟已到期 
 
*/
    {
        RETAILMSG(1, (TEXT("InterruptConnect returned SYSINTR_NOP\r\n")));
        goto Error_Done;
    }
    
    
    g_hIrdaDataIST = CreateThread(NULL, 0, IRCDecodeIST, NULL, 0, NULL);
    if (g_hIrdaDataIST == NULL) 
    {
        RETAILMSG(1, (TEXT("IRC_Init:: CreateThread g_hIrdaDataIST failed\r\n")));
        goto Error_Done;
    }
    
    CeSetThreadPriority(g_hIrdaDataIST, IRC_THREAD_PRIO);
            
	RETAILMSG(1, (TEXT("IrDA Remote Control: -IRC_Init\r\n")));
	return TRUE;

Error_Done:
    CloseHandle(g_hIrdaDataEvent);    
    return FALSE;    
}

BOOL WINAPI IRC_DllEntry(HINSTANCE hInstance,
                         DWORD dwReason,
                         LPVOID pReserved)
{
    switch (dwReason) 
    {
        case DLL_PROCESS_ATTACH:
            RETAILMSG(1, (TEXT("IRC_DllEntry: DLL_PROCESS_ATTACH\r\n")));
            break;

        case DLL_PROCESS_DETACH:
            RETAILMSG(1, (TEXT("IRC_DllEntry: DLL_PROCESS_DETACH\r\n")));
            break;
    }

    // return TRUE for success
    return TRUE;
}

/*
 KEYS       Codes       Virtual-Key Codes
 ====       =====       =================   
 
 PWR	    40          VK_ESCAPE
 CALL	    D8          VK_ESCAPE
 
 1	        00          VK_NUMPAD1
 2	        10          VK_NUMPAD2
 3	        08          VK_NUMPAD3
 4	        18          VK_NUMPAD4
 5	        04	        VK_NUMPAD5
 6	        14          VK_NUMPAD6
 7	        0C          VK_NUMPAD7
 8	        1C	        VK_NUMPAD8
 9	        80          VK_NUMPAD9
 0	        90          VK_NUMPAD0
 
 -/--	    88          VK_MENU
 SS	        98          VK_SHIFT
 
 Vol+	    44		    VK_UP
 Vol-	    54          VK_DOWN
 SEL	    8C          VK_LEFT
 Prog-	    48          VK_RIGHT
 MENU	    E8          VK_TAB
 Prog+	    50          VK_RETURN
 
 KOK	    84          
 TV/AV	    5C	
 MUTE	    4C	
 PIC	    D0
 LANG	    94	        VK_LBUTTON
 LOCK	    E4	
 COLOR	    F8	
 SYS	    F4          VK_RBUTTON
*/

BOOL ScanCodeToVK(BYTE ch)
{
    BYTE byVK;
    BOOL bRet = TRUE;

    switch(ch)
    {
        // Key PWR
        case 0x40:	
            byVK = VK_ESCAPE;
            break;
            
        // Key CALL
        case 0xD8:
            byVK = VK_ESCAPE;
            break;
            
        // Key 1
        case 0x00:	
            byVK = VK_NUMPAD1;
            break;
        
        // Key 2
        case 0x10:	
            byVK = VK_NUMPAD2;
            break;

        // Key 3
        case 0x08:	
            byVK = VK_NUMPAD3;
            break;

        // Key 4
        case 0x18:	
            byVK = VK_NUMPAD4;
            break;          

        // Key 5
        case 0x04:	
            byVK = VK_NUMPAD5;
            break;           

        // Key 6
        case 0x14:	
            byVK = VK_NUMPAD6;
            break;           
 
         // Key 7
        case 0x0C:	
            byVK = VK_NUMPAD7;
            break;
          
        // Key 8
        case 0x1C:	
            byVK = VK_NUMPAD8;
            break;           

        // Key 9
        case 0x80:	
            byVK = VK_NUMPAD9;
            break;           

        // Key 0
        case 0x90:	
            byVK = VK_NUMPAD0;
            break;           

        // Key -/--
        case 0x88:	
            byVK = VK_MENU;
            break;           

        // Key SS
        case 0x98:	
            byVK = VK_SHIFT;
            break;                         

        // Key Vol+
        case 0x44:	
            byVK = VK_UP;
            break;

        // Key Vol-
        case 0x54:	
            byVK = VK_DOWN;
            break;
            
        // Key SEL
        case 0x8C:	
            byVK = VK_LEFT;
            break;

        // Key Prog-
        case 0x48:	
            byVK = VK_RIGHT;
            break;
            
        // Key MENU
        case 0xE8:	
            byVK = VK_TAB;
            break;       
            
        // Key Prog+
        case 0x50:	
            byVK = VK_RETURN;
            break;          
            
        // Key LANG
        case 0x94:	
            byVK = VK_LBUTTON;
            break;                             
            
        // Key SYS
        case 0xF4:	
            byVK = VK_RBUTTON;
            break;    
            
        default:
            bRet = FALSE;
    }
    
    keybd_event(byVK, 0, KEYEVENTF_SILENT, 0);
    Sleep(500);
    keybd_event(byVK, 0, KEYEVENTF_KEYUP, 0);
    
    return bRet;
}

static DWORD WINAPI 
IRCDecodeIST(LPVOID pContext)
{
    if (!InterruptInitialize(g_dwIrcSysIntr, g_hIrdaDataEvent, NULL, 0))
    {
        RETAILMSG(1, (TEXT("IRCDecodeIST: InterruptInitialize failed\r\n")));
        return 0;
    }
    
    while (!g_bExit) 
    {
        if (WAIT_OBJECT_0 == WaitForSingleObject(g_hIrdaDataEvent, INFINITE))
        {
            RETAILMSG(0, (TEXT("Got an IRC Event Code\r\n"))); 
            IRCDecodeHelper();           
        }    
        InterruptDone(g_dwIrcSysIntr);    
    }
    
    // Usually non-reachable line
    return 0; 
}

void IRCDispatchCode(BYTE key)
{
    RETAILMSG(0, (TEXT("IRCDispatchCode: key = 0x%02x\r\n"), key));
    ScanCodeToVK(key);
}

///////////////////////////////////////////////////////////////////////////
 
#ifdef IRC_CLOCK_SWCNT

static VOID IRCDecodeHelper(VOID)
{
    INT32 duration;
    
    /* 
     * The Software Counter is driven by the peripheral bus clock.
     * For Au1200@400MHz, periphera bus clock = 396MHz / (SD = 2) / 2 = 99MHz.
     * So 99 ticks of the Software Counter equal to 1us.
     *
     * The Software Counter only has 26-bit for counting. So its maximum time
     * is 2^26 = 0x4000000, which is about 678ms. Take into account of the
     * rollback situation!!
     */
     
    g_dwIRCTick1 = *(volatile UINT32 *)(0xB1100110);

    if (g_dwIRCTick0 != 0)
    {
        duration = (g_dwIRCTick1 - g_dwIRCTick0);
        if (duration < 0)
        {
            duration += (1 << 26);
        }
        g_dwIRCTick0 = g_dwIRCTick1;
    }
    else
    {   
        g_dwIRCTick0 = g_dwIRCTick1;
        return;
    }

    /* 
     * swcnt_count running at 99MHz, 99 ticks means 1us.
     * For code '0', its high duration is 1000us --> 99000.
     * For code '1', its high duration is 2000us --> 198000.
     *
     * The interval between two consecutive instructions is about 25ms.
     * So the duration between the last instruction's high status to 
     * the coming instructions low status is about 25ms.
     */
     
    duration >>= 10;
    RETAILMSG(0, (TEXT("Duration = %d\r\n"), duration));    
    
    if ((duration > 170) && (duration < 250))
    {
        RETAILMSG(0, (TEXT(" 1 ")));
        g_dwIRCBitCount++;
        g_dwIRCBitCode = (g_dwIRCBitCode << 1);
        g_dwIRCBitCode |= 1UL;
    }
    else if ((duration > 80) && (duration < 150))
    {
        RETAILMSG(0, (TEXT(" 0 ")));
        g_dwIRCBitCount++;
        g_dwIRCBitCode = (g_dwIRCBitCode << 1);
        g_dwIRCBitCode &= ~1UL;
    }
    else
    {
        /* 
         * As all instruction codes are ended with a short low then long high wave.
         * We think this as s new iteration of bit sampling.
         */
        if (duration > 500)
        {
            RETAILMSG(0, (TEXT(" + ")));
            g_dwIRCTick0 = g_dwIRCTick1;
	        return;
        }
    }

    if (g_dwIRCBitCount == 16)
    {
        RETAILMSG(0, (TEXT("g_dwIRCBitCode = 0x%04lx\r\n"), g_dwIRCBitCode));
        
        if (((g_dwIRCBitCode >> 8) & 0xFF) != 0xE2)
        {
            RETAILMSG(0, (TEXT("IRC error, reset the start tick\r\n")));
            g_dwIRCTick0 = 0;
        }
        else
        {
            IRCDispatchCode((BYTE)(g_dwIRCBitCode));
        }
                
        g_dwIRCBitCode = 0;
        g_dwIRCBitCount = 0;
    }
          
    return;
}

#else // ~IRC_CLOCK_SWCNT

static VOID IRCDecodeHelper(VOID)
{
    UINT32 duration;
    
    // 32.786KHz TOY counter SYS_TOYREAD @ 0x11900040
    g_dwIRCTick1 = *(volatile UINT32 *)(0xB1900040);

    if (g_dwIRCTick0 != 0)
    {
        duration = (g_dwIRCTick1 - g_dwIRCTick0);
        g_dwIRCTick0 = g_dwIRCTick1;
    }
    else
    {
        g_dwIRCTick0 = g_dwIRCTick1;
	    return;
    }

    RETAILMSG(0, (TEXT("Duration = %d\r\n"), duration));
    
    /* 
     * sys_toyread running at 32.768KHz, one tick means 30us.
     * For code '0', its high duration is 1000us --> 33.
     * For code '1', its high duration is 2000us --> 66.
     *
     * The interval between two consecutive instructions is about 25ms.
     * So the duration between the last instruction's high status to 
     * the coming instructions low status is about 25ms.
     */
    if ((duration > 55) && (duration < 80))
    {
        RETAILMSG(0, (TEXT(" 1 ")));
        g_dwIRCBitCount++;
        g_dwIRCBitCode = (g_dwIRCBitCode << 1);
        g_dwIRCBitCode |= 1UL;
    }
    else if ((duration > 20) && (duration < 55))
    {
        RETAILMSG(0, (TEXT(" 0 ")));
        g_dwIRCBitCount++;
        g_dwIRCBitCode = (g_dwIRCBitCode << 1);
        g_dwIRCBitCode &= ~1UL;
    }
    else
    {
        /* 
         * As all instruction codes are ended with a short low then long high wave.
         * We think this as s new iteration of bit sampling.
         */
        if (duration > 200)
        {
            RETAILMSG(0, (TEXT(" + ")));
            g_dwIRCTick0 = g_dwIRCTick1;
	        return;
        }
    }

    if (g_dwIRCBitCount == 16)
    {
        RETAILMSG(0, (TEXT("g_dwIRCBitCode = 0x%04lx\r\n"), g_dwIRCBitCode));
        
        if (((g_dwIRCBitCode >> 8) & 0xFF) != 0xE2)
        {
            RETAILMSG(1, (TEXT("IRC error, reset the start tick\r\n")));
            g_dwIRCTick0 = 0;
        }
        else
        {
            IRCDispatchCode((BYTE)(g_dwIRCBitCode));
        }
                
        g_dwIRCBitCode = 0;
        g_dwIRCBitCount = 0;
    }
          
    return;
}

#endif // IRC_CLOCK_SWCNT

////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -