ir.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 1,376 行 · 第 1/3 页
C
1,376 行
/* Copyright 1996-1997, ESS Technology, Inc. *//* SCCSID @(#)ir.c 4.9.1.1 12/01/04 *//* * This module is used to receive and transmit IR signals. * * Transmitting of IR in the current version is interrupt driven (it * uses timer 1 to keep track of time). *//* * The current code supports: * 1) New 3881/3883 style interrupt handling (when DSC_IRQ is defined.) * 2) Original timer2 style interrupt handling (when DSC_IRQ is not * defined.) * * It also supports 3 styles of R/C: NEC, SANYO and PHILIPS. */#include "vcxi.h"#include "const.h"#include "ir.h"#include "timedef.h"#include "util.h"#define BYTE_TRANSFER /* only for HOST_SLAVE function */#ifndef HOST_SLAVE#ifdef IR/************************************************************************ * Macros relate to remote control ************************************************************************/#ifdef IR_PHILIPS#define IR_SYSCODE 0x6#endif /* IR_PHILIPS */#ifdef IR_NEC#ifdef BAOAN49_REMOTE#define IR_SYSCODE 0x00ff#else#define IR_SYSCODE 0x20df#endif#endif /* IR_NEC */#ifdef IR_SANYO#define IR_SYSCODE 0x0cc0#endif#define ASSIGN_SYSCODE sysIRcode = IR_SYSCODE#ifdef DSC_IRQ/* For the new style of IR handling (i.e. via 3881) *//************************************************************************ * Local variables. * ************************************************************************/PRIVATE unsigned short dataIR; /* System/customer IR code */PRIVATE char cntIRbits = 0; /* Number of IR sys/cust. bits */PRIVATE volatile char stateIR = IR_IDLE; /* IR state machine state */PRIVATE char trigger_edge;#ifdef IR_SANYOPRIVATE unsigned short IR_sanyo_codebar;/* Sanyo IR only */#endif /* IR_SAYNO */#ifdef IRREPPRIVATE unsigned char previous_data; /* Record the previous ID code */PRIVATE int rep_timeout; /* 121602 chengfeng*/#endif/************************************************************************ * Local routines * ************************************************************************/PRIVATE void IR_core_NEC(unsigned int, int);PRIVATE void IR_core_Philips(unsigned int);void IR_init(){ ASSIGN_SYSCODE; /* Initialize IR system code */ CLEAR_IRXOR; /* Clear IR XOR (EAUX11 is active high!! */#ifdef IR_GAMEPAD sysDANCERcode = T_DANCER_syscode[0]; /*Initialize gameIR system code */#endif#ifdef IR_SANYO IR_sanyo_codebar = (~sysIRcode) & 0x1fff;#endif /* IR_SANYO */ DSC_INIT_IR(1, DSC_FALLING_EDGE, 1); /* Start 3881 IR */ trigger_edge = 0; mvd[riface_clear_dbgirq] = 0; /* Clear debug_irq */ enable_int(debug);}#if (IR_NEC || IR_SANYO)PRIVATE void IR_core_NEC(width, overflow)unsigned int width;int overflow;{#define LEADER_MIN ir_tbl[0]#define LEADER_MAX ir_tbl[1]#define DATA_1_MIN ir_tbl[2]#define DATA_1_MAX ir_tbl[3]#define DATA_0_MIN ir_tbl[4]#define DATA_0_MAX ir_tbl[5]#ifdef IRREP#define REPEAT_MIN ir_tbl[6]#define REPEAT_MAX ir_tbl[7]#endif IRREP#ifdef IR_GAMEPADextern GB_ir_key;#define LEADER_DANCER_MIN ir_tbl[6]#define LEADER_DANCER_MAX ir_tbl[7]#define DATA_1_DANCER_MIN ir_tbl[8]#define DATA_1_DANCER_MAX ir_tbl[9]#define DATA_0_DANCER_MIN ir_tbl[10]#define DATA_0_DANCER_MAX ir_tbl[11]#endif unsigned int *ir_tbl; unsigned char data; char reset = 0; ir_tbl = T_IR_powerup_tbl; /* * If 3881's clock overflows, then reset. The only exception is * when REP is considered!! */ reset = overflow; if (stateIR == IR_CUSTOM) { dataIR <<= 1; if ((width >= DATA_1_MIN) && (width <= DATA_1_MAX)) { dataIR |= 0x1; } else if ((width < DATA_0_MIN) || (width > DATA_1_MAX)) {#ifdef IR_NEC reset = 1;#endif /* IR_NEC */#ifdef IR_SANYO reset = 1; /* we do not care about repeat key for Sanyo yet */#endif /* IR_SANYO */ } cntIRbits++; #ifdef IR_NEC /* First 16 bits are syscode */ if ((cntIRbits == 16) && (dataIR != sysIRcode)) reset = 1; if (cntIRbits == 24) { data = dataIR & 0xff; /* reverse data bits to fit look up table */ mvd[riface_reflect] = data; data = mvd[riface_reflect];#ifdef IRREP previous_data = data; rep_timeout = glbTimer + QUARTER_SECOND; /* 121602 chengfeng*/#endif codeIR = data | 0x100; /* Indicate a new code */ } else if (cntIRbits == 32) reset = 1;#endif /* IR_NEC */#ifdef IR_SANYO if (cntIRbits == 13) { dataIR &= 0x1fff; if (dataIR != sysIRcode) reset = 1; dataIR = 0; } else if (cntIRbits == 26) { unsigned short tmp = (~sysIRcode) & 0x1fff; if (dataIR != tmp) reset = 1; dataIR = 0; } else if (cntIRbits == 34) { data = dataIR; mvd[riface_reflect] = data; data = mvd[riface_reflect]; codeIR = data; dataIR = 0; } else if (cntIRbits == 42) { data = dataIR; mvd[riface_reflect] = data; data = ~(mvd[riface_reflect]); if (data == codeIR) { codeIR = data | 0x100; } else codeIR = 0; reset = 1; }#endif /* IR_SANYO */#ifdef IR_GAMEPAD } else if (stateIR == DANCER_CUSTOM){ dataIR <<= 1; if ((width >= DATA_1_DANCER_MIN) && (width <= DATA_1_DANCER_MAX)) { dataIR |= 0x1; } else if ((width < DATA_1_DANCER_MIN) || (width > DATA_0_DANCER_MAX)) { reset = 1; /*ERR 1 */ } cntIRbits++; if ((cntIRbits == 13) && ((dataIR & 0x06) != sysDANCERcode)){ reset = 1; /*ERR */ } if (cntIRbits == 13){ int i; int parity; int one_num = 0; parity = dataIR & 0x02; data = (dataIR>>5) & 0xff; for (i=0;i<8;i++){ if ((data & 0x1) == 1) one_num ++; data >>= 1; } if (!(one_num & 1) && !parity) reset = 1; /*ERR parity */ else if ((one_num & 1) && parity) reset = 1; /*ERR parity */ else { data = dataIR >> 5; codeIR = data | 0x00; /*??*/ /* Indicate a new code */ GB_ir_key = codeIR; } } else if (cntIRbits == 14) reset = 1; /*ERR */#endif /* IR_GAMEPAD */ } else { if ((width >= LEADER_MIN) && (width <= LEADER_MAX)) { stateIR = IR_CUSTOM; dataIR = cntIRbits = 0;#ifdef IRREP } else if ((width >= REPEAT_MIN) && (width <= REPEAT_MAX)) { /* if the width is 2.25 ms, it is repeat code leader */ if (rep_timeout > glbTimer) { /* 121602 chengfeng*/ if (repeat_IRkey_allowed(previous_data)) { codeIR = previous_data | 0x100; /* Indicate a new code */ rep_timeout = glbTimer + QUARTER_SECOND; } } else { previous_data = 0xff; }#endif#ifdef IR_GAMEPAD } else if ((width >= LEADER_DANCER_MIN) && (width <= LEADER_DANCER_MAX)){ stateIR = DANCER_CUSTOM; dataIR = cntIRbits = 0;#endif } else reset = 1; } if (reset) { /* Reset all, start from the very beginning */ stateIR = IR_IDLE; }}#endif /* IR_NEC || IR_SANYO */#ifdef IR_PHILIPSPRIVATE unsigned int data_half = 0; /* Mark whether or nor have half_bit data before edge of intr. coming*/PRIVATE void IR_core_Philips(width)unsigned int width;{ unsigned int *ir_tbl; int reset; int is_half_bit; int is_full_bit;#define HALFBIT_MIN ir_tbl[0]#define HALFBIT_MAX ir_tbl[1]#define ONEBIT_MIN ir_tbl[2]#define ONEBIT_MAX ir_tbl[3] ir_tbl = T_IR_powerup_tbl; reset = 0; is_half_bit = (width >= HALFBIT_MIN) && (width <= HALFBIT_MAX); is_full_bit = (width >= ONEBIT_MIN) && (width <= ONEBIT_MAX); if (stateIR == IR_IDLE) { /* We shall get a rising edge, since the first bit is fixed */ dataIR = 0; cntIRbits = 0; stateIR = IR_CUSTOM; if (is_half_bit) data_half = 0; else if (is_full_bit) data_half = 1; else { stateIR = IR_IDLE; } } else { if (data_half) { /* * We were in half bit position, so this edge shall either * conclude the previous cycle or go the the half position * of the next bit. Record the last bit. */ dataIR <<= 1; if (!trigger_edge) dataIR |= 1; cntIRbits++; if (is_half_bit) data_half = 0; else if (!is_full_bit) reset = 1; } else { /* * We started at a sampling cycle, so we shall only get half bit, * otherwise, something is wrong! */ if (is_half_bit) data_half = 1; else reset = 1; } if ((cntIRbits == 12) && trigger_edge && data_half) { /* This is the last rising edge, no more. So collect the bit */ dataIR <<= 1; dataIR |= 1; cntIRbits = 13; } if (reset) { /* * Abnormal exist. Maybe we are out of sync. If this * is falling edge, maybe this is the sync of a new * input! */ stateIR = IR_IDLE; if (trigger_edge) stateIR = IR_LEADER; } else if (cntIRbits == 13) { /* We only care the case when system code matches */ if (((dataIR >> 6) & 0x1f) == sysIRcode) { unsigned int prevctlbit; prevctlbit = IR_ctlbit; IR_ctlbit = (dataIR >> 11) & 1; if ((unsigned int) IR_ctlbit != prevctlbit) { int tmp = (dataIR >> 12) & 1; if (tmp) tmp = 0x40; codeIR = (dataIR & 0x3f) | tmp | 0x100; IR_rep_cnt = 0; } else IR_rep_cnt++; IR_int_time = (unsigned int) mvd[riface_timer2]; } stateIR = IR_IDLE; } }}#endif /* IR_PHILIPS *//* Interrupt via 3881 */void IR_recv_interrupt_service(status)unsigned int status;{ unsigned char width; int overflow = 0; int clear = 0x4; if (status & 0x80) { overflow = 1; /* 3881's clock overflowed */ clear = 0x84; /* Clear the overflow bit */ } width = DSC_cmd(dsc_ir_diffm, 0); /* Get the counter */ DSC_cmd(dsc_sys_status, clear); /* Clear 3881's IR int */#if (IR_NEC || IR_SANYO) IR_core_NEC((unsigned int) width, overflow);#endif /* IR_NEC || IR_SAYNO */#ifdef IR_PHILIPS if (!trigger_edge) DSC_INIT_IR(1, DSC_RISING_EDGE, 0); /* detect rising edge */ else DSC_INIT_IR(1, DSC_FALLING_EDGE, 0); /* detect falling edge */ IR_core_Philips((unsigned int) width); trigger_edge = 1-trigger_edge;#endif /* IR_PHILIPS */}#else/* For the original style of IR handling */#define _8259_EOI() (*(int *)0x14000600=0x20)#define _8259_ICW (*(int *)0x14000600)#define _8259_OCW (*(int *)0x14000604)/************************************************************************ * Local variables. * ************************************************************************//* For IR receiving */PRIVATE unsigned int prevIRtime = 0; /* Last time IR intr. happens */PRIVATE unsigned short dataIR; /* System/customer IR code */PRIVATE unsigned int diffIR[2]; /* Array to store time gap */PRIVATE char cntIRchg = 0; /* Number of unprocessed IR intr*/PRIVATE char cntIRbits = 0; /* Number of IR sys/cust. bits */PRIVATE char killIR = 0; /* Whether to "kill" next IR bit*/PRIVATE volatile char stateIR = IR_IDLE; /* IR state machine state */#ifdef IR_SANYOPRIVATE unsigned short IR_sanyo_codebar;/* Sanyo IR only */#endif /* IR_SAYNO */#ifdef IRREPPRIVATE unsigned char previous_data; /* Record the previous id code */PRIVATE int rep_timeout;#endif/************************************************************************ * Local routines. * ************************************************************************/PRIVATE void IR_core_NEC(int);PRIVATE void IR_core_Philips(int);/* * Initialization. Properly set internal XOR's input value, then turn * on interrupt. */void IR_init(){#ifdef FLIP_IR /* * If incoming IR signal is flipped, then the first incoming edge * will be a rising edge, so we need to clear the build-in * XOR gate. */ CLEAR_IRXOR;#else SET_IRXOR; /* Set IR XOR to high at first */#endif#ifdef IRXMT if (!connect_inout) { OUTIR_HIGH; /* IR output */ }#endif ASSIGN_SYSCODE; /* initialize sys code */#ifdef IR_SANYO IR_sanyo_codebar = (~sysIRcode) & 0x1fff;#endif /* IR_SANYO */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?