找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2266|回复: 3
收起左侧

多年前的VCD多种遥控格式解码源码,值得学习和提取

[复制链接]
ID:138443 发表于 2020-6-18 22:57 | 显示全部楼层 |阅读模式
本帖最后由 lizhendong 于 2020-6-18 23:19 编辑

多年前的VCD多种遥控格式解码源码,值得学习和提取!!!

/* Copyright 1996-1997, ESS Technology, Inc. */
/* SCCSID @(#)ir.c        4.9 02/17/03 */


/*
* 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
#define IR_SYSCODE              0x00ff
#endif


#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_SANYO
PRIVATE        unsigned short IR_sanyo_codebar;/* Sanyo IR only                */
#endif /* IR_SAYNO */


#ifdef IRREP
PRIVATE 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_GAMEPAD
extern 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 */
            /*debug_osd("IR",data,10);*/
            /*hlx*/
        } 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_PHILIPS
PRIVATE 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_SANYO
PRIVATE        unsigned short IR_sanyo_codebar;/* Sanyo IR only                */
#endif /* IR_SAYNO */


#ifdef IRREP
PRIVATE 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 */


    mvd[riface_clear_dbgirq] = 0;                /* Clear debug_irq        */
    enable_int(debug);
}




#if (IR_NEC || IR_SANYO)
PRIVATE void IR_core_NEC(falling_edge)
int falling_edge;
{
    unsigned int *ir_tbl;


#define LEADER_LOW_MIN        ir_tbl[0]
#define LEADER_LOW_MAX        ir_tbl[1]
#define LEADER_HIGH_MIN        ir_tbl[2]
#define LEADER_HIGH_MAX        ir_tbl[3]
#define DATA_1_MIN        ir_tbl[4]
#define DATA_1_MAX        ir_tbl[5]
#define DATA_0_MIN        ir_tbl[6]
#define DATA_0_MAX        ir_tbl[7]
#ifdef IRREP
#define REPEAT_HIGH_MIN ir_tbl[8]
#define REPEAT_HIGH_MAX ir_tbl[9]
#define REPEAT_DATA_MIN        ir_tbl[10]
#define REPEAT_DATA_MAX ir_tbl[11]
#endif


    ir_tbl = T_IR_powerup_tbl;
#ifdef DSC
    if (IS_POWER_DOWN) ir_tbl = T_IR_powerdn_tbl;
#endif


    /* First IR interrupt should be a falling edge */
    if (stateIR == IR_IDLE) {
        if (falling_edge) stateIR = IR_LEADER_LOW;
        else cntIRchg = prevIRtime = 0;
    }


    /*
     * We only process things when we get 2 bits (i.e. 2 time period).
     */
    if (cntIRchg == 2) {
        unsigned char data;
        char reset = 0;
        unsigned int  width;


        cntIRchg = 0;
        width = diffIR[1];


        if (stateIR == IR_CUSTOM) {/* Put most common case first */
            /*
             * We are collecting system code or custom code
             */
            width += diffIR[0];        /* Get data + gap */
            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
                /*
                 * I am assert kill here because we may not recognize
                 * the singal because our checks are too tight; yet
                 * the external micro controller can still recognize it.
                 * By killing it, we guarantee that external logic won't
                 * recognize it.
                 *
                 * However, there may also be a downside: if IR input
                 * has noise, the external micro controll may still
                 * properly receive signal if we don't kill the input;
                 * if killIR is asserted, then this may be a problem.
                 */
                killIR = 1;
                reset = 1;
#endif /* IR_NEC */


#ifdef IR_SANYO
                if (cntIRbits == 0) {
                    /*
                     * SANYO's repeat is the same as leader low/high.
                     * So we may mistaken repeat as a new code. So if
                     * we are broken on the first bit of new cutsom code,
                     * we shall assume it is a new code overall.
                     *
                     * The last one is probably a repeat, so this is
                     * really the first bit of leader low.
                     */
                    cntIRchg = 1;        /* We just need one more edge */
                    stateIR = IR_LEADER_LOW;
                } else {
                    killIR = 1;
                    reset = 1;
                }
#endif /* IR_SANYO */
            }


            cntIRbits++;


#ifdef IR_NEC
            /* First 16 bits are syscode */
            if ((cntIRbits == 16) && (dataIR != sysIRcode))
                reset = 1;


            if (cntIRbits == 24) {
                /*
                 * We will not wait for data bar. Base on data, we'll
                 * decide whether we want to pass the IR to CD loader.
                 * If we decided that the code shouldn't be passed on,
                 * we'll intentionally destroy the output IR so CD
                * loader will not get it.
                */
                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;
#endif
                codeIR = data | 0x100;        /* Indicate a new code */
                /* Get the kill bit from the kill IR table */
#ifdef IRXMT
                killIR = tblKillIR[data >> 3] & ptrLshift[data & 7];
#endif
            } 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 */
        } else if (stateIR == IR_LEADER_LOW) {
            if ((width >= LEADER_LOW_MIN) && (width <= LEADER_LOW_MAX)) {
                stateIR = IR_LEADER_HIGH;
                cntIRchg = 1; /* We'll only collect 1 change next time */
            } else reset = 1;
#ifdef IRREP
        } else if (stateIR == IR_REPEAT) {
            if ((width >= REPEAT_DATA_MIN) && (width <= REPEAT_DATA_MAX)) {
                /* the width is 0.56 ms */
                if (rep_timeout > glbTimer) {
                    if (repeat_IRkey_allowed(previous_data)) {
                        codeIR = previous_data | 0x100; /* Indicate a new code */
                        rep_timeout = glbTimer + QUARTER_SECOND;
                    }
                } else {
                    previous_data = 0xff;
                }
            }
            reset = 1;
#endif
        } else {
            /* stateIR has to be equal to IR_LEADER_HIGH */
            if ((width >= LEADER_HIGH_MIN) && (width <= LEADER_HIGH_MAX)) {
                dataIR = cntIRbits = 0;
                stateIR = IR_CUSTOM;
#ifdef IRREP
            } else if ((width >= REPEAT_HIGH_MIN) &&
                       (width <= REPEAT_HIGH_MAX)) {
                /* if the width is 2.25 ms, it is repeat code leader */
                cntIRchg = 1; /* We'll only collect 1 change next time */
                stateIR = IR_REPEAT;
#endif
            } else reset = 1;
        }


        if (reset) {
            /* Reset all, start from the very beginning */
            stateIR = IR_IDLE;
            cntIRchg = prevIRtime = 0;
        }
    }
}
#endif /* IR_NEC || IR_SAYNO */


#ifdef IR_PHILIPS
PRIVATE unsigned int    data_half = 0;        /* Mark whether or nor have half_bit
                                           data before edge of intr. coming*/
PRIVATE void IR_core_Philips(falling_edge)
int falling_edge;
{
    unsigned int *ir_tbl;
    unsigned int width;
    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;
#ifdef DSC
    if (IS_POWER_DOWN) ir_tbl = T_IR_powerdn_tbl;
#endif


    width = diffIR[0];
    cntIRchg = 0;
    reset = 0;
    is_half_bit = (width >= HALFBIT_MIN) && (width <= HALFBIT_MAX);
    is_full_bit = (width >= ONEBIT_MIN)  && (width <= ONEBIT_MAX);


    if (stateIR == IR_IDLE) {
        if (falling_edge) stateIR = IR_LEADER;
        else prevIRtime = 0;
    } else if (stateIR == IR_LEADER) {
        /* 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;
            prevIRtime = 0;
        }
    } 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 (falling_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) && !falling_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 (falling_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 */


/*
* DBG IRQ  INTERUPT SERVICE for IR
*
* This routine recognizes IR input and selectively retransmit signals.
*/
void IR_recv_interrupt_service()
{
    /* I shift data bit coming from IR from LSB to the left.        */
    int falling_edge = 0, tmp;
    unsigned int currIRtime, tmp1;
    currIRtime = ((unsigned int) mvd[riface_timer2]);
    tmp1 = currIRtime - prevIRtime;
    if (currIRtime < prevIRtime) {/* Wrap around case */
        tmp1 += -timer2_period;
    }
    diffIR[cntIRchg++] = tmp1;
    prevIRtime = currIRtime;


    /* Toggle XOR to get next interupt */
#ifdef FLIP_IR
    /*
     * If the polarity of the incoming IR is flipped (e.g. on the Internet
     * board), then if the internal XOR input is 1, we received a falling
     * edge from the remote sensor, and we want to send out a rising edge.
     * Vice versa.
     *
     * To make minimum change to the remaining code, when we recive a
     * falling edge, we'll tell the internal code that we have received
     * a rising edge. Vice versa.
     */
    if (IS_IRXOR_HIGH) {
        CLEAR_IRXOR;                /* set to low */
        /* If we want to kill IR, then send 0; else send 1 */
        tmp = killIR ? 0 : 1;
    } else {
        SET_IRXOR;
        falling_edge = 1;         /* Interupt caused by IR falling edge */
        /* If we want to kill IR, then send 1; else send 0 */
        tmp = killIR ? 1 : 0;
    }
#else
    if (IS_IRXOR_HIGH) {
        CLEAR_IRXOR;                /* set to low */
        falling_edge = 1;         /* Interupt caused by IR falling edge */
        /* If we want to kill IR, then send 1; else send 0 */
        tmp = killIR ? 1 : 0;
    } else {
        SET_IRXOR;
        /* If we want to kill IR, then send 0; else send 1 */
        tmp = killIR ? 0 : 1;
    }
#endif




#ifdef IRXMT
    if (!connect_inout) {
        /* IR comes from us, so we'll send it now */
        if (tmp) {OUTIR_HIGH;}
        else     {OUTIR_LOW;}
    }


    /*
     * If we meant to kill IR, then IR is effectly killed now
     * i.e. CD won't get the correct key bar.
     */
    killIR = 0;
#endif


#if (IR_NEC || IR_SANYO)
    IR_core_NEC(falling_edge);
#endif /* IR_NEC || IR_SAYNO */


#ifdef IR_PHILIPS
    IR_core_Philips(falling_edge);
#endif /* IR_PHILIPS */


}


#endif /* else of DSC_IRQ */
#endif /* IR */


#ifdef IRXMT


PRIVATE        void                RISC_start_timer1(unsigned int);
/************************************************************************
* Local typedef.                                                        *
************************************************************************/
typedef struct {
    unsigned char  level;        /* Assert this output level                */
    unsigned char  next;        /* Goto this state                        */
    unsigned short timer;        /* Timer1 value (need to << 9)                */
} IR_XMIT_INFO;




/* For IR transmission */
PRIVATE        unsigned char        IR_xmit_state         = IR_XMIT_IDLE;
PRIVATE        unsigned char        IR_xmit_bitcount = 0;
PRIVATE        unsigned int        IR_xmit_code;
PRIVATE        char                origConnectInOut;


/* State machine for transmitting IR                                        */
PRIVATE IR_XMIT_INFO IR_xmit_array[] = {        /* Current state        */
    {0, IR_XMIT_LEADER_LOW,  IRW_LEADER_LOW},        /* IR_XMIT_IDLE                */
    {1, IR_XMIT_LEADER_HIGH, IRW_LEADER_HIGH},        /* IR_XMIT_LEADER_LOW        */
    {0, IR_XMIT_GAP,         IRW_GAP_LOW},        /* IR_XMIT_LEADER_HIGH        */
    {0, IR_XMIT_GAP,         IRW_GAP_LOW},        /* IR_XMIT_DATA                */
    {1, IR_XMIT_DATA,        IRW_DATA_ONE},        /* IR_XMIT_GAP                *
                                                 * (Possible targets         *
                                                 * are IDLE, DATA, and        *
                                                 * REP_HIGH1)                */
    {0, IR_XMIT_REP_LOW1,    IRW_REP_LOW1},        /* IR_XMIT_REP_HIGH1        */
    {1, IR_XMIT_REP_HIGH2,   IRW_REP_HIGH2},        /* IR_XMIT_REP_LOW1        */
    {0, IR_XMIT_REP_LOW2,    IRW_REP_LOW2},        /* IR_XMIT_REP_HIGH2        */
                                                    /* IR_XMIT_REP_LOW2        *
                                                 * (disable timer1)        */
};


/************************************************************************
* Start timer1 (for transmitting IR signals)                                *
************************************************************************/
PRIVATE void RISC_start_timer1(period)
unsigned int period;
{
    mvd[riface_clear_timer1] = 0;
    mvd[riface_timer1] = 0 - (period << 9);
    /*
     * Since this routine will be called repeatedly, it is better
     * to enable interrupt outside.
     */
}


/*
* Main routine to start tranmission of IR signal. IR transmission is
* interrupt driven (by timer1). Therefore, this routine will enable
* the timer1 interrupt.
*
* Inputs;
*        code:                user code to be transmitted
*        repeate:        1 transmit repeat
*                        0 transmit code
*/
void IR_send_data(unsigned char code, int repeat)
{
    register int psw;
    unsigned char code_bar;
    unsigned int begTimer = glbTimer;
    unsigned int period;


    /*
     * We'll do detailed checking only if interrupt is enabled.
     * If this routine is called inside the interrupt service routine,
     * then interrupt can't come in (i.e. glbTimer won't change).
     * In which case, just send the code (at worst, we'll loss the code,
     * but the machine won't hang)
     */
    asm volatile("movfrs psw,%0":  "=r" (psw) );


    if (!(psw & 0x10)) {
        /*
         * If we are in the middle of receiving, then wait up to 1/8 of
         * a second to finish reciving. Otherwise, if we are in the middle
         * of FF/FB/SLOW, IR misses at high frequency.
         */
        do {
            if (stateIR == IR_IDLE) break;
        } while ((glbTimer - begTimer) < EIGHTH_SECOND);


        /*
         * If we are in the middle of transmitting an IR, then wait it to
         * finish
         */
        begTimer = glbTimer;
        do {
            if (IR_xmit_state == IR_XMIT_IDLE) break;
        } while ((glbTimer - begTimer) < EIGHTH_SECOND);
    }


    /* reverse data to meet NEC remote control standard        */
    mvd[riface_reflect] = code;
    code = mvd[riface_reflect];


    code_bar = ~code;
    IR_xmit_code = (((unsigned int) sysIRcode) << 16) | (code << 8) | code_bar;


    origConnectInOut = connect_inout;


    connect_inout = 1; /* While transmitting IR, don't relay any IR input */
    if (repeat) {
        IR_xmit_state = IR_XMIT_REP_LOW1;
        period = IRW_REP_LOW1;
    } else {
        /* Leader low is 9ms wide */
        IR_xmit_bitcount = 32;
        IR_xmit_state = IR_XMIT_LEADER_LOW;
        period = IRW_LEADER_LOW;
    }
    OUTIR_LOW;
    RISC_start_timer1(period);
    enable_int(tim1);
}




/*
* Timer 1 interrupt service routine. This service routine goes through
* a state machine to transmit IR.
*/
void IR_xmit_interrupt_service(void)
{
    IR_XMIT_INFO *ptrXmit = &IR_xmit_array[IR_xmit_state];


    if (IR_xmit_state == IR_XMIT_REP_LOW2) {
        OUTIR_HIGH;
        IR_xmit_state = IR_XMIT_IDLE;
        disable_int(tim1);
        connect_inout = origConnectInOut;
    } else if (IR_xmit_state == IR_XMIT_GAP) {
        /* We have to make some decision here */
        OUTIR_HIGH;
        if (IR_xmit_bitcount != 0) {
            /* More bits to transmit */
            IR_xmit_state = IR_XMIT_DATA;
            RISC_start_timer1((IR_xmit_code & x80000000) ? IRW_DATA_ONE
                                                               : IRW_DATA_ZERO);
            IR_xmit_code <<= 1;
            IR_xmit_bitcount--;
        } else {
#ifdef JIANGHAI
            IR_xmit_state = IR_XMIT_REP_HIGH1;
            RISC_start_timer1(IRW_REP_HIGH1);
#else
            IR_xmit_state = IR_XMIT_IDLE;
            disable_int(tim1);
            connect_inout = origConnectInOut;
#endif
        }
    } else {
        /* Do a table lookup */
        IR_xmit_state = ptrXmit->next;
        if (ptrXmit->level) {OUTIR_HIGH;}
        else {OUTIR_LOW;}
        RISC_start_timer1((unsigned int) ptrXmit->timer);
    }
}


#endif /* IRXMT */


#else /* HOST_SLAVE */


#include "slave.h"


extern void Slave_Receive_Command();
extern unsigned char Receive_Buffer[RECEIVE_BUFFER_MAX];
extern unsigned char Send_Buffer[SEND_BUFFER_MAX];
volatile unsigned int receive_index = 0;
extern unsigned char Check_Sum;
extern unsigned char Total_Byte;


extern volatile unsigned int Receive_Flag;
unsigned int Time_Temp;
unsigned int Time_Temp2;


/*** External Interrupt Disable ***/
#define DISABLE_INTERRUPT                 disable_int(debug)


/*** External Interrupt Enable ***/
#define ENABLE_INTERRUPT                enable_int(debug)


#define READTIMER                        mvd[riface_timer2]
#define COMM_TIMEOUT                        50000                                /*** 500 us ***/


#define SET_DATAOUT                        SET_AUX7
#define CLEAR_DATAOUT                        CLEAR_AUX7


#define TOGGLE_STROBE                        if(AUX5_HIGH) {CLEAR_AUX5;} \
                                                else {SET_AUX5;}
#define READ_ACK                        AUX6_HIGH   /** AUX6  **/
#define DATAIN_IS_LOW                        EAUX15_LOW
#define DATAIN_IS_HIGH                        EAUX15_HIGH
#define BIT                                unsigned char


#define TRUE        1
#define FALSE        0
#define Byte_interval       3375000             /* 50ms */




void IR_init()
{
    SET_DATAOUT;                                /* Ready to receive */
    DSC_INIT_IR(1, DSC_FALLING_EDGE, 1);        /* Start 3881 IR        */
    mvd[riface_clear_dbgirq] = 0;                /* Clear debug_irq        */
    enable_int(debug);
}






unsigned char Check_Ack(unsigned char Flag)
{
    if (Flag  == READ_ACK)
    {
        Time_Temp = READTIMER;
        do
        {
            if (Flag != READ_ACK )      break;


            Time_Temp2 = READTIMER;
            if(Time_Temp2 < Time_Temp)
            {
                Time_Temp2 += -timer2_period;
            }


            if((Time_Temp2 - Time_Temp) > COMM_TIMEOUT)
                               return 1;         /* timeout */
        } while(1);
       }
     return 0;
  }


#ifdef BYTE_TRANSFER


unsigned char Send_Data(unsigned char data, unsigned char ending)
{
   register unsigned char temp, i, Count;
   unsigned char Pin_Flag;


   if (DATAIN_IS_LOW)   /* host is not ready */
                return FALSE;


/* Request for sending  */
   DISABLE_INTERRUPT;
   Pin_Flag = READ_ACK;
   CLEAR_DATAOUT;


   if(Check_Ack(Pin_Flag))
                    goto Send_Fail;


/*   Send data  */
   temp = data;
   for (i=0;i<8;i++)
    {
        if (temp&0x80)
             { SET_DATAOUT; }
          else
            { CLEAR_DATAOUT; }


        Pin_Flag = READ_ACK;
        TOGGLE_STROBE;
           temp <<= 1;          /* data shif left */
        if(Check_Ack(Pin_Flag))
                goto Send_Fail;
     }


   if(ending)             /* last byte? */
       { SET_DATAOUT; }
     else
        {CLEAR_DATAOUT; }


     Pin_Flag = READ_ACK;
     TOGGLE_STROBE;
     if(Check_Ack(Pin_Flag))   goto Send_Fail;


/*  End of sending data  */
   if(ending)
     {
        Pin_Flag = READ_ACK;
        TOGGLE_STROBE;             /* ask for check sum result */


      if(Check_Ack(Pin_Flag))  goto Send_Fail;


      if(DATAIN_IS_LOW)           /* host checksum error */
        {
                TOGGLE_STROBE;
                goto Send_Fail;
        }


        TOGGLE_STROBE;    /* sending data OK! */
        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;
      }
        SET_DATAOUT;            /* prepare for next sending */
        ENABLE_INTERRUPT;
        return TRUE;


Send_Fail:
        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;


        ENABLE_INTERRUPT;
        return FALSE;
}




/* Interrupt via 3881 */
void IR_recv_interrupt_service(status)
unsigned int status;
{
    register unsigned char i,temp;
    BIT Pin_Flag;
/*---------------------------------------------------------------------
                Start Syncronization
---------------------------------------------------------------------*/
        DISABLE_INTERRUPT;
        Pin_Flag = READ_ACK;
        TOGGLE_STROBE;        /* answer  communication request */
/*----------------------------------------------------------------------
                Receive data
----------------------------------------------------------------------*/
        temp=0;
         for (i=0;i<8;i++)
        {
          if(Check_Ack(Pin_Flag)) goto Receive_Fail;
          if (DATAIN_IS_HIGH)        temp|=(0x80>>i);
          Pin_Flag = READ_ACK;
          TOGGLE_STROBE;
        }


/*** bit 9 ***/
         if(Check_Ack(Pin_Flag)) goto Receive_Fail;


         if (DATAIN_IS_LOW) {    /* Not Last byte  */
             Pin_Flag = READ_ACK;
             TOGGLE_STROBE;       /* ninth bit received */


             Receive_Buffer[receive_index]=temp;
             receive_index++;
             Check_Sum += temp;          /* add checksum */


          } else {    /* Last Byte received */
             Pin_Flag = READ_ACK;
             TOGGLE_STROBE;     /* ninth bit received */
             Receive_Buffer[receive_index]=temp;
             receive_index++;         /* still keep the last byte */


             /*--End receive data --------------*/
             if(Check_Ack(Pin_Flag)) goto Receive_Fail;
             /* wait for check sum request */
             if (temp == Check_Sum) {                /* Checksum verification */
                 SET_DATAOUT;                        /* Receive OK! */
                 Receive_Flag = 1;
                } else {
                   CLEAR_DATAOUT;                /* Checksum error */
                   receive_index = 0;
                }
              Check_Sum=0;                   /* Clear Check Sum */
              Pin_Flag = READ_ACK;
              TOGGLE_STROBE;


              if(Check_Ack(Pin_Flag)) goto Receive_Fail;
           }


        SET_DATAOUT;           /* set for next sending */
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;
        ENABLE_INTERRUPT;
        return;


Receive_Fail:
        receive_index=0;
        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;
        ENABLE_INTERRUPT;
        return;
}


#else /* BLOCK_TRANSFER  */


unsigned char Send_Data()
{
    register unsigned char temp, i, Count;
    BIT Pin_Flag;


/*---------------------------------------------------------------------
                Start Syncronization
---------------------------------------------------------------------*/
        if (DATAIN_IS_LOW)
                return FALSE;


        DISABLE_INTERRUPT;
        Pin_Flag = READ_ACK;
        CLEAR_DATAOUT;


             if(Check_Ack(Pin_Flag)) goto Send_Fail;
/*----------------------------------------------------------------------
                Send data
----------------------------------------------------------------------*/
      for (Count=0;Count<Total_Byte;Count++)
        {
                temp = Send_Buffer[Count];
                  for (i=0;i<8;i++)
                 {
                        if (temp&0x80)                 { SET_DATAOUT; }
                        else                                { CLEAR_DATAOUT; }
                        Pin_Flag = READ_ACK;
                        TOGGLE_STROBE;
                        temp <<= 1;
                        if(Check_Ack(Pin_Flag)) goto Send_Fail;
                }


                 if(Count==Total_Byte-1)
                     { SET_DATAOUT; }
                 else
                     {CLEAR_DATAOUT; }


                Pin_Flag = READ_ACK;
                TOGGLE_STROBE;


                if(Check_Ack(Pin_Flag)) goto Send_Fail;
        }
/*----------------------------------------------------------------------
        End send data
----------------------------------------------------------------------*/
      Pin_Flag = READ_ACK;
        TOGGLE_STROBE;


        if(Check_Ack(Pin_Flag)) goto Send_Fail;
      if(DATAIN_IS_LOW)
        {
                TOGGLE_STROBE;
                goto Send_Fail;
        }


        TOGGLE_STROBE;


        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;


        ENABLE_INTERRUPT;


        return TRUE;


Send_Fail:
        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;


        ENABLE_INTERRUPT;
        return FALSE;
}


/* Interrupt via 3881 */
void IR_recv_interrupt_service(status)
unsigned int status;
{
    register unsigned char i,Count,temp,Check_Sum_temp = 0;
    BIT Pin_Flag;
/*---------------------------------------------------------------------
                Start Syncronization
---------------------------------------------------------------------*/
        DISABLE_INTERRUPT;
        Pin_Flag = READ_ACK;
        TOGGLE_STROBE;
/*----------------------------------------------------------------------
                Receive data
----------------------------------------------------------------------*/
     for (Count=0;Count<=0x30;Count++)
        {
                 temp=0;
                  for (i=0;i<8;i++)
                 {
                        if(Check_Ack(Pin_Flag)) goto Receive_Fail;
                        if (DATAIN_IS_HIGH)                        temp|=(0x80>>i);
                        Pin_Flag = READ_ACK;
                        TOGGLE_STROBE;
                }


/*** bit 9 ***/
                if(Check_Ack(Pin_Flag)) goto Receive_Fail;
                if (DATAIN_IS_HIGH)    /* Last byte received */
                {
                        Pin_Flag = READ_ACK;
                        TOGGLE_STROBE;
                        break;
                }


                Pin_Flag = READ_ACK;
                TOGGLE_STROBE;


                Receive_Buffer[Count]=temp;
                 Check_Sum_temp+=temp;          /* add checksum */
         }
/*----------------------------------------------------------------------
        End receive data
----------------------------------------------------------------------*/
        if(Check_Ack(Pin_Flag)) goto Receive_Fail;
        if (temp == Check_Sum_temp)                /* Checksum verification */
        {
                SET_DATAOUT;                        /* Receive OK! */
                Receive_Flag = 1;
        }
        else
        {
                CLEAR_DATAOUT;                /* Checksum error */
                Receive_Flag = 0;
        }




        Pin_Flag = READ_ACK;
        TOGGLE_STROBE;


/*        if(Check_Ack(Pin_Flag)) goto Receive_Fail;


        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;
        ENABLE_INTERRUPT;
        return;  */


Receive_Fail:


        SET_DATAOUT;
        DSC_cmd(dsc_sys_status, 0x4);
        mvd[riface_clear_dbgirq] = 0;


        ENABLE_INTERRUPT;


}
#endif /* BYTE_TRANSFER */
#endif /* HOST_SLAVE */



1.JPG
2.JPG

IR.rar

10.54 KB, 下载次数: 12, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:600596 发表于 2020-6-18 23:40 来自手机 | 显示全部楼层
这个是什么编译器
回复

使用道具 举报

ID:138443 发表于 2020-6-28 23:33 | 显示全部楼层
236983 发表于 2020-6-18 23:40
这个是什么编译器

原厂的专用编译器!!! 编辑器用Source Insight
回复

使用道具 举报

ID:495287 发表于 2020-6-29 12:50 | 显示全部楼层
谢谢楼主分享,我是在一阵阵发蒙中看了三遍,还没测试到这个功能,很好很好的参考。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表