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 + -
显示快捷键?