📄 irstate.c
字号:
#include "fip_private.h"#include "fip.h"#include "irstate.h"// define DEBUG_REMOTE to be the scan code we want to check//#define DEBUG_REMOTE 0x00ffb847#ifndef FIP_NO_INTERRUPT/* for debugging */#ifdef DEBUG_REMOTEunsigned long tt[32];#endifstatic IR_STATE ir_state;int ir_pio(){ return ir_state_machine(&ir_state);}// 9281 is the default/original timer scale, so that TS(x) = x in the default case#define TS(x) (x*ir_state->timer_scale/9281)int ir_state_machine (IR_STATE *ir_state){ int t1, t;#ifdef VERBOSE DPRINTF("in ir_state_machine state=%d\n", ir_state->state);#endifnext_state: switch (ir_state->state) { // PIO 1 is high, we can proceed to state 2 only when PIO 1 goes low case IR_STATE_WAIT_FOR_COMMAND_START: // since the falling edge interrupt was signalled, we must be // already at state 2, so just fall through! // PIO 1 is low, save the time (t0) at this moment and go to state 3 case IR_STATE_COMMAND_START: ir_state->t0 = *(TIMER0_VAL_REG); ir_state->state = IR_STATE_COMMAND; // fall through! // PIO 1 is low, we can proceed to state 4 only when PIO 1 goes high case IR_STATE_COMMAND: // setup the PIO 1 interrupt to trigger on the next rising edge // and set the state to be the next state - the next time we // come here we will be at the next state *(PIO_0_POL_REG) = (0x00010000 << 1); ir_state->state = IR_STATE_COMMAND_END; break; // PIO 1 is high, current time = t1, if (t1-t0) < 8ms go back to // state 1, else proceed to state 5 case IR_STATE_COMMAND_END: t1 = *(TIMER0_VAL_REG); t = ir_state->t0 - t1; if (t < 0) t = ir_state->t0 + (ir_state->timer_load - t1); if (t > TS(30000)) { ir_state->state = IR_STATE_LEADER_PULSE_START; // fall through! } else { ir_state->state = IR_STATE_WAIT_FOR_COMMAND_START; // setup PIO 1 interrupt to signal on the falling edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; break; } // PIO 1 is high, save the time (t0) at this moment and go to state 6 case IR_STATE_LEADER_PULSE_START: ir_state->t0 = *(TIMER0_VAL_REG); ir_state->state = IR_STATE_LEADER_PULSE; // fall through! // PIO 1 is high, we can only proceed to state 7 when PIO 5 goes low case IR_STATE_LEADER_PULSE: // program PIO 1 to signal on the next falling edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; // and set the state to be the next state ir_state->state = IR_STATE_LEADER_PULSE_END; break; // PIO 1 is low, current time = t1, if (t1-t0) < 3.5ms, then the last // key was kept pressed down, go to state 8, else go to state 12 case IR_STATE_LEADER_PULSE_END: t1 = *(TIMER0_VAL_REG); t = ir_state->t0 - t1; if (t < 0) t = ir_state->t0 + (ir_state->timer_load - t1); if (t > TS(15000)) { ir_state->state = IR_STATE_READ_SCAN_CODE; goto next_state; } else { ir_state->state = IR_STATE_REPEAT_PULSE_START; // fall through! } // PIO 1 is low, we can proceed to state 1 only when PIO 1 goes high case IR_STATE_REPEAT_PULSE_START: // program PIO 1 to signal on the next *falling* edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; // and set the state to be the next state ir_state->state = IR_STATE_WAIT_FOR_COMMAND_START; // XXX key repeated ir_state->repeat++; ir_state->release_timeout = 0; if(ir_state->repeat >= IR_REPEAT && ir_state->scan_code) { ir_state->repeat = 0;// XXX vincent: perhaps we should send a special "repeat" scancode// fip_receive_scancode(ir_state->scan_code); } break; // PIO 1 is low, set bit_position to 31, set scan_code to 0, // save current time as t0, go to state 13 case IR_STATE_READ_SCAN_CODE: ir_state->t0 = *(TIMER0_VAL_REG); ir_state->scan_code = 0; ir_state->repeat = 0; ir_state->release_timeout = 0; ir_state->bit_position = 31; ir_state->state = IR_SUBSTATE_READ_BIT_START; // fall through! // PIO 1 is low, we can only proceed to state 14 when PIO 1 goes high case IR_SUBSTATE_READ_BIT_START: // program PIO 1 to signal on the next *falling* edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; // the next time we get an interrupt will be when the signal // has gone low again, so we actually skip state 14 ir_state->state = IR_SUBSTATE_READ_BIT_LOW; break; // PIO 1 is high, we can only go to state 15 when PIO 1 goes low case IR_SUBSTATE_READ_BIT_HIGH: if ((*(PIO_0_DATA_REG) & 2) == 0) { ir_state->state = IR_SUBSTATE_READ_BIT_LOW; // fall through! } else break; // PIO 1 is low, current time = t1, if (t1-t0) > 1.75ms // scan_code |= (1 << bit_position) // decrement bit position, if bit_posiion < 0, go to state 1, // else go to state 13 case IR_SUBSTATE_READ_BIT_LOW: t1 = *(TIMER0_VAL_REG); t = ir_state->t0 - t1; if (t < 0) t = ir_state->t0 + (ir_state->timer_load - t1);// XXX why this hack? we have to try to ignore spurious interrupts?//// if ((t < TS(10000)) && (t > TS(6000)))// break; if (t < TS(4500)) break; // XXX if (t > TS(10000)) ir_state->scan_code |= (1 << ir_state->bit_position);#ifdef DEBUG_REMOTE /* for debugging */ tt[ir_state->bit_position] = t;#endif ir_state->bit_position--; if (ir_state->bit_position < 0) { ir_state->state = IR_STATE_WAIT_FOR_COMMAND_START; // program PIO 1 to signal on the next *falling* edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; fip_receive_scancode(ir_state->scan_code);#ifdef DEBUG_REMOTE /* for debugging */ if (ir_state->scan_code != DEBUG_REMOTE) { for (t1=0; t1<32; t1++) DPRINTF ("(%02d: %d)\r\n", (int)t1, (int)tt[t1]); DPRINTF ("scancode = 0x%08lx\n", (unsigned long)ir_state->scan_code); }#endif return 1; // scancode has been received } else { ir_state->t0 = *(TIMER0_VAL_REG); // program PIO 1 to signal on the next *falling* edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO; // set the next state to be IR_SUBSTATE_READ_BIT_LOW // and *not* IR_SUBSTATE_READ_BIT_START because the // next time an interrupt will come is when PIO 1 is // low again ir_state->state = IR_SUBSTATE_READ_BIT_LOW; } break; case IR_STATE_ERROR_RECOVERY: ir_state->error_recovery--; if (ir_state->error_recovery <= 0) ir_state->state = IR_STATE_WAIT_FOR_COMMAND_START; break; default: // error!!! break; } return 0;}void ir_init(){ unsigned long dw; unsigned long unit; unsigned long pll_reg; unsigned long pll_mult, pll_div, pll_D; unsigned long clock; ir_state.state = 1; ir_state.timer_load = *(TIMER0_LOAD_REG); dw = (*TIMER0_CNTL_REG) & 0x0F; unit = 1000*2*1<<dw; pll_reg = *QUASAR_DRAM_PLLCONTROL_REG; pll_mult = (pll_reg & 0xFF) >> 2; pll_div = (pll_reg >> 8 ) & 0x3; pll_D = (pll_reg & 0x2); clock = ((JASPER_EXT_CLOCK / unit) * (pll_mult+2))/(pll_div + 2); if(pll_D) clock = clock / 2; // here we got sysclock in kHz ir_state.timer_scale = clock; DPRINTF("ir_init: scale = %d\n",ir_state.timer_scale); // program PIO_0, bit IR_PIO, as input *(PIO_0_DIR_REG) = 0x00010000 << IR_PIO; // program PIO_0, bit IR_PIO, interrupt to signal on falling edge *(PIO_0_POL_REG) = 0x00010001 << IR_PIO ; // enable PIO_0, bit IR_PIO, interrupt *(PIO_0_INT_ENABLE_REG) = 0x00010001 << IR_PIO;}#endif /* !FIP_NO_INTERRUPT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -