📄 irc_1200.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 + -