?? nec_ir.c
字號:
/* **************************************************************************************
* Copyright (c) 2002 ZORAN Corporation, All Rights Reserved
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
*
* File: $Workfile: nec_ir.c $
*
* Description:
* ============
* NEC IR implementation
*
* Log:
* ====
* $Revision: 17 $
* Last Modified by $Author: Rinata $ at $Modtime: 3/11/04 5:06p $
****************************************************************************************
* Updates:
****************************************************************************************
* $Log: /I76/I76_Common/I76_Reference/Remote/nec_ir/nec_ir.c $
*
* 17 3/11/04 5:45p Rinata
* cpu check remote signal after v8 wake it up when remote signal was
* changed
*
* 16 03-08-01 11:57 Wesleyj
* remove video_mode_detect
*
* 15 7/09/03 6:05p Mikex
* cancel transfer cpu_soft_reset() function on second standby key
* pressed. The cpu_soft_reset() function will be transfered by core task.
*
* 14 03-07-07 16:14 Ivany
* Added a mapping table and condition for the keys which repeat-pressed
* message should not be sent when is pressed.
*
* 13 03-06-19 17:08 Wesleyj
* add video_mode_detect charge (Av in stat)
*
* 12 03-06-17 18:28 Admin
* Merge for ExinoII project
*
* 11 03-05-19 18:54 Kennyz
* Clear code.
*
* 10 2/02/03 6:22p Lyncolnc
* Added LONG_REPEAT_DELAY.
*
* 12 17/07/02 20:25 Nirm
* - Adjustments to timer_0 in order to increase timer-measurement
* accuracy throughout the system.
*
* 11 5/28/02 18:47 Rinata
* FF and FB are not with valid repeat
*
* 10 23/04/02 9:37 Nirm
* - Added dependency in "Config.h".
*
* 9 7/03/02 17:45 Nirm
* Removed EMERGENCY_EJECT_ENABLED -> replaced by the Exceptioning
* mechanism.
*
* 8 18/02/02 11:01 Atai
* make global to static
*
* 7 2/17/02 12:21p Tomasp
* Code clean up.
*
* 6 1/28/02 19:55 Rinata
* fix gen timer values for ir
*
* 5 9/01/02 16:58 Nirm
* Corrected Include-Paths.
*
* 4 1/06/02 15:46 Rinata
*
* 3 1/01/02 19:10 Atai
* Code cleaning
*
* 2 25/12/01 12:29 Atai
* Code cleaning
**************************************************************************************** */
#include "Config.h" // Global Configuration - do not remove!
#include "Kernel\ker_api.h"
#include "Kernel\eventdef.h"
#include "CPU\cpu_api.h"
#include "Playcore\Coremain\coremain.h"
#include "Playcore\Coremain\coredefs.h"
#include "Playcore\Coremain\coregdef.h"
#include "Devices\Remote\ir_api.h"
#include "Devices\Remote\ir_ll.h"
#include "UI_Manager\UI_Input\ui_input_ir.h"
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
#include "Kernel\Timers\Timers.h"
#endif
#ifdef I96_CPU_POWER_DOWN
#include "Dec_Power.h"
#endif
#ifdef D_HOLD_STOP_3S_AS_EJECT_KEY
#define IRKC_NULL 0xFF
#define STOPKEY_DELAY 0x20
#endif
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
//the time of 2 seconds for hold the skip key
#define SKIPKEY_DELAY 0x10 //counter value for about 2 seconds
//the time slice between two repeated skip key
#define HOLDSKIP_TIMEOUT_TIME 120 //millisecond
//the handler of the timer
static UINT8 hHoldSkipTimer = 0;
//used to remember we pressed skipf or skipr
static BYTE lastSkipKey = 0xFF;
#endif //D_HOLD_SKIP_2S_AS_FAST_SCAN
extern CONST WORD g_ir_system_code;
extern CONST WORD g_ir_power_key_code;
#ifdef MODIFIED_FOR_T1_2002
extern const WORD g_ir_volume_up_key ;//add for t1.
extern const WORD g_ir_volume_down_key ;//
#endif
#ifdef I96_CPU_POWER_DOWN
extern BOOL bPowerUpKeyPressed;
extern BOOL bWakeFromPowerDown;
#endif
//the time increment for gen_time is 1.25us
#define IR_MARGIN ((WORD)130UL)
#define time_9000_us ((WORD)9000UL)
#define time_4500_us ((WORD)4500UL)
#define time_2250_us ((WORD)2250UL)
#define time_1125_us ((WORD)1125UL)
// State of the remote key decoder
#define IDLE 0
#define LEADER_ON 1
#define LEADER_OFF 2
#define CUSTOM 3
#define DATA1 4
#define DATA2 5
// Hoe many repeat message will ignire before send it to the FSM's
#ifdef LONG_REPEAT_DELAY
#define REPEAT_DELAY 25
#else
#define REPEAT_DELAY 5
#endif //LONG_REPEAT_DELAY
#ifdef IR_NO_REPEAT_PULSE
#define IR_INTERVAL 240/20
BYTE last_key = 0;
BYTE ir_interval = 0;
#endif
//<<<YY_ZCH
#define MAX_NO_REPEAT_PULSE_KEY_NUM 1
#define IR_ENTER 0x73
CONST BYTE mkey_no_repeat_pluse[MAX_NO_REPEAT_PULSE_KEY_NUM]=
{
IR_ENTER
};
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
/**********************************************************************************
* Name : HoldSkipTimerIR
* Purpose : The timeout function for hold skip key, when timeout happens, it will send out
* the skip key user pressed.
* Input :
* Return Value :
* Description :
* Comments :
**********************************************************************************/
#pragma argsused
static void HoldSkipTimerIR(UINT8 hTimer)
{
send_remote_event((WORD)KEY_SOURCE_IR|lastSkipKey);
timer_service_delete(hHoldSkipTimer);
}
#endif //D_HOLD_SKIP_2S_AS_FAST_SCAN
BOOL ir_need_no_repeat_pulse(BYTE uKey)
{
int i;
for(i=0;i < MAX_NO_REPEAT_PULSE_KEY_NUM;i++)
{
if(uKey == mkey_no_repeat_pluse[i])
return TRUE;
}
//if(i == MAX_NO_REPEAT_PULSE_KEY_NUM)
return FALSE;
}
//>>>YY_ZCH
static unsigned long time_count_old;
void ir_init(void)
{
ir_interrupt_init( FALLING_EDGE );
time_count_old = cpu_gen_timer();
}
void ir_isr( void )
{
static BYTE key; // Hold the key code
static BYTE repeat_delay = REPEAT_DELAY; // Repeat code counter
static WORD custom; // Hold the custom (remote ID) code
static BYTE state = 0; // State holder
static BYTE count; // bits counter
static BYTE data1, data2; // Temporary for holding the decoded data
static BYTE valid_repeat = 0;
#ifdef D_HOLD_STOP_3S_AS_EJECT_KEY
static BYTE lastkey = IRKC_NULL;
static BYTE stopkey_repeatDelay = REPEAT_DELAY;
#endif
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
// 2 seconds timeout counter
static BYTE skipkey_repeatDealy = REPEAT_DELAY;
#endif
unsigned long time_count, t0;
#ifdef I96_CPU_POWER_DOWN
if (bWakeFromPowerDown == TRUE)
{
DEC_PowerCpu(TRUE);
}
#endif
time_count = cpu_gen_timer();
t0 = time_count - time_count_old;
switch (state) {
case IDLE:
time_count_old = time_count;
ir_interrupt_set_edge(RISING_EDGE);
state = LEADER_ON;
break;
case LEADER_ON:
time_count_old = time_count;
ir_interrupt_set_edge(FALLING_EDGE);
state = ((t0>(time_9000_us-8*IR_MARGIN)) && (t0<(time_9000_us+8*IR_MARGIN))) ? LEADER_OFF:IDLE;
break;
case LEADER_OFF:
if (t0 > time_4500_us - (4*IR_MARGIN) && t0 < time_4500_us + (4*IR_MARGIN)) {
state = CUSTOM;
custom = 0;
count = 0;
repeat_delay = REPEAT_DELAY;
}
else {
if (t0 > time_2250_us - (2*IR_MARGIN) && t0 < time_2250_us + (2*IR_MARGIN)) {
#ifdef D_HOLD_STOP_3S_AS_EJECT_KEY
if(key == IRKC_STOP)
{
if(stopkey_repeatDelay)
stopkey_repeatDelay--;
else
{
if(lastkey != IRKC_EJECT)
{
send_remote_event((WORD)IRKC_EJECT&0x00FF);
lastkey = IRKC_EJECT; // Eject only once
//lastkey = IRKC_STOP; // Eject at STOPKEY_DELAY interval
stopkey_repeatDelay = STOPKEY_DELAY;
}
}
}
else
#endif //D_HOLD_STOP_3S_AS_EJECT_KEY
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
if(IRKC_SKIPB == key || IRKC_SKIPF == key)
{
//reset the timer
timer_service_enable(hHoldSkipTimer, TRUE);
if(skipkey_repeatDealy)
{
skipkey_repeatDealy--;
}
else
{
//clear the timer
timer_service_delete(hHoldSkipTimer);
//translate the skip key to "hold" scan key
if(IRKC_SKIPF == key)
{
send_remote_event((WORD)KEY_STATUS_HOLD|KEY_SOURCE_IR|IRKC_FASTF);
}
else
{
send_remote_event((WORD)KEY_STATUS_HOLD|KEY_SOURCE_IR|IRKC_FASTR);
}
}
}
else
#endif //D_HOLD_SKIP_2S_AS_FAST_SCAN
if (repeat_delay) {
// Delay before sendnig the first repeat
repeat_delay--;
}
else { // repeat last key
if (valid_repeat) {//<<<YY_ZCH
if(!ir_need_no_repeat_pulse(key))//>>>YY_ZCH
send_remote_event( (KEY_STATUS_HOLD|KEY_SOURCE_IR)|key );
}
}
}
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
}
time_count_old = time_count;
break;
case CUSTOM:
time_count_old = time_count;
if (t0 > time_1125_us - IR_MARGIN && t0 < time_1125_us + IR_MARGIN) {
custom <<= 1; /* a zero bit */
}
else {
if (t0 > time_2250_us - (2*IR_MARGIN) && t0 < time_2250_us + (2*IR_MARGIN)) {
custom = (custom << 1) | 1; /* a one bit */
}
else {
{
// Garbage ... ignored
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
valid_repeat = 0;
break;
}
}
}
/* count 16 'custom' bits */
if (++count == 16) {
if (custom != g_ir_system_code) {
// Noise from other remote ... ignore
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
valid_repeat = 0;
break;
}
state = DATA1;
time_count_old = time_count;
count = 0;
data1 = 0;
}
break;
case DATA1:
time_count_old = time_count;
count++;
if (t0 > time_1125_us - IR_MARGIN && t0 < time_1125_us + IR_MARGIN) {
data1 <<= 1; /* a zero bit */
}
else {
if (t0 > time_2250_us - (2*IR_MARGIN) && t0 < time_2250_us + (2*IR_MARGIN)) {
data1 = (data1 << 1) | 1; /* a one bit */
}
else {
{
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
valid_repeat = 0;
break;
}
}
}
if (count == 8) {
state = DATA2;
count = 0;
data2 = 0;
}
break;
case DATA2:
time_count_old = time_count;
count++;
if (t0 > time_1125_us - IR_MARGIN && t0 < time_1125_us + IR_MARGIN) {
data2 <<= 1; /* a zero bit */
}
else {
if (t0 > time_2250_us - (2*IR_MARGIN) && t0 < time_2250_us + (2*IR_MARGIN)) {
data2 = (data2 << 1) | 1; /* a one bit */
}
else {
{
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
valid_repeat = 0;
break;
}
}
}
if (count == 8) {
ir_interrupt_set_edge(FALLING_EDGE);
state = IDLE;
if (data1 == (~data2 & 0xff))
{ // Check if data is valid
key = (0x00FF&data1);
/* Removed by NirM 07-Mar-02: Replaced by the Exceptioning mechanism
// Emergency eject
#ifdef EMERGENCY_EJECT_ENABLED
if((key == IRKC_EJECT)
&&((gcs.mstate == MST_LOADING)||(gcs.mstate == MST_DISC_READY)))
{
gcs.bEmergencyEject = TRUE;
}
#endif
*/
#ifdef IR_NO_REPEAT_PULSE
if (((last_key&0x00FF) == key) && (ir_interval != 0)) { /* If a key was pushed continuously. */
}
else {
#endif
valid_repeat = 1; //allow key repeat
#ifdef D_HOLD_STOP_3S_AS_EJECT_KEY
if(key == IRKC_STOP)
{
stopkey_repeatDelay = STOPKEY_DELAY;
lastkey = IRKC_NULL;
}
#endif //D_HOLD_STOP_3S_AS_EJECT_KEY
#ifdef D_HOLD_SKIP_2S_AS_FAST_SCAN
if(IRKC_SKIPF == key || IRKC_SKIPB == key)
{
lastSkipKey = key;
skipkey_repeatDealy = SKIPKEY_DELAY;
hHoldSkipTimer = timer_service_create(HoldSkipTimerIR, HOLDSKIP_TIMEOUT_TIME, TIMER_ONCE |TIMER_DISABLED);
timer_service_enable(hHoldSkipTimer, TRUE);
//when press the skip key or press down the skip key first,
//we just ignore it here. It will be sent out when "holdkey" timeout happens.
break;
}
#endif //D_HOLD_SKIP_2S_AS_FAST_SCAN
if (key == (BYTE)(0x00FF&g_ir_power_key_code))
{
switch(g_power_state)
{
case POWER_SEQUENCE_IN_ON_STATE:
g_power_state = POWER_SEQUENCE_OFF_REQUESTED;
break;
case POWER_SEQUENCE_IN_OFF_STATE:
g_power_state = POWER_SEQUENCE_ON_REQUESTED;
break;
case POWER_SEQUENCE_OFF_REQUESTED:
g_power_state = POWER_SEQUENCE_ON_REQUESTED;
//03-07-09 cpu_soft_reset();
}
}
#ifdef I96_CPU_POWER_DOWN
if( key == (BYTE)g_ir_power_key_code )
{
bPowerUpKeyPressed = TRUE;
}
#endif
send_remote_event(KEY_SOURCE_IR|key);
#ifdef IR_NO_REPEAT_PULSE
last_key = key;
ir_interval = IR_INTERVAL;
}
#endif
}
}
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -