|
本帖最后由 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 */
|
-
-
-
-
IR.rar
10.54 KB, 下载次数: 12, 下载积分: 黑币 -5
评分
-
查看全部评分
|