在 ir remote control NEC protocol 裏只是提到如何處理一個按鍵的處理。在實際應用上,常常會有遇到按著不放時,要重覆處理這個按鍵,或是按住某個按鍵多久才處理。現在我們就來討論這二個應用方法。
下面主要是用來做一個 buffer,免得 mcu 處理來不急,ir_put 都放在 interrupt 內使用,並沒有給一般常式使用;而 ir_get 只有 ir_process 會用到,但是 counter 跟 ir_put 共用到,所以加上中斷排除,免得發生同時修改的慘況。
#define IR_BUFFER_MAX 4
#define IR_BUFFER_MASK 3
static xdata unsigned char ir_buffer[IR_BUFFER_MAX];
static data unsigned char get_index, put_index, counter;
static unsigned char ir_debound, ir_key, ir_repeat_key, ir_long_key;
static unsigned char code ir_repeat[] = { IR_UP, IR_DOWN, IR_LEFT, IR_RIGHT };
#define IR_REPEAT_MAX (sizeof(ir_repeat)/sizeof(unsigned char))
static void ir_put(unsigned char value)
{
if (counter < IR_BUFFER_MAX) {
ir_buffer[put_index] = value;
counter++;
put_index++;
put_index &= IR_BUFFER_MASK;
}
}
static unsigned char ir_get(void)
{
unsigned char value;
value = ir_buffer[get_index];
ET0 = LOW;
counter --;
ET0 = HIGH;
get_index++;
get_index &= IR_BUFFER_MASK;
return value;
}
下面是在 interrupt 內會用到 ir_put 的片斷,只有二個地方;一個是輸入 repeat 訊號,一個是輸入按鍵訊號。
if (IS_IR_REPEAT(pulse)) {
if (ir_pos == 32)
ir_put(IR_REPEAT);
return;
}
if(ir_pos >= 32) {
ir_mode = 0;
stop_timer();
if ((ir_code[0] | ir_code[1]) != 0xef) return;
if ((ir_code[2] | ir_code[3]) != 0xff) return;
if (ir_code[0] == 0x40) ir_put(ir_code[2]);
}
下面是放在 main loop 裏的函數,ir_function 用來處理按鍵事件,而 ir_process 是用來計算處理 normal,repeat,long 按鍵的函數。
void ir_function(unsigned char key)
{
switch (key) {
default:
printf_tiny("ir recv: %x,%d,%d,%d\n\r", ir_key, get_index, put_index, counter);
}
}
void ir_process(void)
{
unsigned char key;
if (counter == 0) {
return;
}
key = ir_get();
switch (key) {
case IR_REPEAT:
if (ir_debound == 0) {
ir_debound++;
if (ir_key == IR_LONG_KEY) {
ir_long_key = IR_LONG_KEY;
break;
}
for (key=0; key IR_REPEAT_COUNT)
ir_function(ir_repeat_key);
else
ir_debound++;
}
else if (ir_long_key != IR_NONE) {
if (ir_debound < IR_LONG_COUNT) {
ir_debound++;
}
else if (ir_debound == IR_LONG_COUNT) {
ir_function(ir_long_key);
ir_debound++;
}
}
break;
default:
ir_debound = 0;
ir_long_key = IR_NONE;
ir_repeat_key = IR_NONE;
ir_key = key;
if (key != IR_LONG_KEY) ir_function(key);
}
}
謝謝你分享IR相關的知識~
請問ir_long_key 與 ir_repeat_key 的差異與用意是如何?