DIGILIGHT
ir_remote.c
См. документацию.
1 
11 #include <avr/io.h>
12 #include "avr_helper.h"
13 #include <avr/interrupt.h>
14 #include <avr/eeprom.h>
15 #include "ir_remote.h"
16 
21 static uint32_t _code; // принимаемый код ДУ
22 static volatile uint8_t _cnt; // счетчик принятых бит
23 static volatile uint8_t _code_done; // флаг окончания приёма
24 
25 #define IR_LOG0 0x600
26 #define IR_DONE (0x3000)
27 
31 static inline void start_ir_capture(void){
32  // обнуление
33  _code = 0;
34  _code_done = 0;
35  _cnt = 0;
36  // настройка захвата
37  TCCR1B |= _BV(ICES1); // rising edge wait
38  TIFR = _BV(ICF1); // clear interrupt flag
39 }
40 
41 INIT(7){
42  DDR(IR_CAP_PORT) &= ~IR_CAP_PIN;
43  PORT(IR_CAP_PORT) |= IR_CAP_PIN;
44 
45  start_ir_capture();
46  TIMSK |= _BV(TICIE1) | _BV(OCIE1B); // enable capture interrupt
47  TCCR1B |= TIMER_CLK_DIV_8; // 0.5 uS
48 }
49 
50 ISR(TIMER1_COMPB_vect){
51  _code_done = 1;
52  TIMSK &= ~_BV(OCIE1B);
53 }
54 
55 static volatile uint16_t bit;
56 
60 ISR(TIMER1_CAPT_vect){
61  static uint16_t icr;
62 
63  // захват
64  if(bit_is_set(TCCR1B, ICES1)){
65  icr = ICR1;
66  OCR1B = TCNT1 + IR_DONE;
67  // если ждали нарастающего фронта, то надо измерить длительность высокого уровня
68  TCCR1B &= ~_BV(ICES1); // falling edge wait
69  TIFR = _BV(ICF1); // clear interrupt flag
70  return;
71  }
72  // сохранение принятого бита
73  icr = (ICR1-icr) < 0 ? 0x10000 - ICR1 + icr : ICR1 - icr;
74  _code <<= 1;
75  if(icr > IR_LOG0){
76  _code |= 1;
77  } else {
78  }
79  _cnt++;
80 
81  icr = ICR1;
82  // ожидание начала следующего
83  TCCR1B |= _BV(ICES1); // falling edge wait
84  TIFR = _BV(ICF1); // clear interrupt flag
85  TIMSK |= _BV(OCIE1B);
86 }
87 
88 #define DIV 100
89 
94 static uint32_t get_ir_code1(void){
95  static uint32_t result;
96 
97  // пока код не принят, возвращаем ноль
98  if(!_code_done) return 0;
99 
100  // если принято мало бит, не запоминаем принятый код,
101  // считая, что это символ автоповтора
102  if(_cnt >= 2){
103  result = _code;
104  }
105  // снова запускаем прием
106  TIMSK &= ~_BV(TICIE1); // disable capture interrupt
107  start_ir_capture();
108  TIMSK |= _BV(TICIE1); // enable capture interrupt
109 
110  // возвращаем запомненный код
111  return result;
112 }
113 
114 uint32_t get_ir_code(void){
115  static uint32_t code;
116  static uint8_t div;
117 
118  uint32_t cd = get_ir_code1();
119  if(cd == 0){
120  return 0;
121  } else {
122  if(cd != code){
123  code = cd;
124  div = 10;
125  return code;
126  } else {
127  div--;
128  if(div == 0){
129  div = 1;
130  return code;
131  } else {
132  return 0;
133  }
134  }
135  }
136 }
137 
138 static EEMEM e_cmd_t e_cmd[TOTAL_STORED_IR_CMD];
139 
140 control_cmd_t get_ir_command(void){
141  uint32_t ir = get_ir_code();
142  e_cmd_t ecmd;
143 
144  if(ir != 0) {
145  for(uint8_t i=0; i < TOTAL_STORED_IR_CMD; i++){
146  eeprom_read_block(&ecmd, &e_cmd[i], sizeof(e_cmd_t));
147  if(ir == ecmd.ir){
148  return ecmd.cmd;
149  }
150  }
151  }
152 
153  return CMD_NONE;
154 }
155 
156 uint32_t get_ir_cmd_code(control_cmd_t cmd){
157  e_cmd_t ecmd;
158 
159  if(cmd != CMD_NONE){
160  for(uint8_t i=0; i < TOTAL_STORED_IR_CMD; i++){
161  eeprom_read_block(&ecmd, &e_cmd[i], sizeof(e_cmd_t));
162  if(cmd == ecmd.cmd){
163  return ecmd.ir;
164  }
165  }
166  }
167  return IR_NO_CMD;
168 }
169 
170 void set_ir_cmd_code(control_cmd_t cmd, uint32_t code){
171  e_cmd_t ecmd;
172 
173  for(uint8_t i=0; i < TOTAL_STORED_IR_CMD; i++){
174  eeprom_read_block(&ecmd, &e_cmd[i], sizeof(e_cmd_t));
175  if(cmd == ecmd.cmd){
176  ecmd.cmd = cmd;
177  ecmd.ir = code;
178  eeprom_update_block(&ecmd, &e_cmd[i], sizeof(e_cmd_t));
179  return;
180  }
181  }
182 }
183 
184 void init_ir_cmd_code(uint8_t id, control_cmd_t cmd, uint32_t code){
185  if(id < TOTAL_STORED_IR_CMD){
186  e_cmd_t ecmd;
187  ecmd.cmd = cmd;
188  ecmd.ir = code;
189  eeprom_update_block(&ecmd, &e_cmd[id], sizeof(e_cmd_t));
190  }
191 }
192 
Структура для хранения кодов команд
Definition: ir_remote.h:16
void set_ir_cmd_code(control_cmd_t cmd, uint32_t code)
назначение команде IR-кода
Definition: ir_remote.c:170
#define TOTAL_STORED_IR_CMD
Количество сохраняемых команд в EEPROM.
Definition: ir_remote.h:24
#define IR_CAP_PIN
Пин захвата IR-команд (ICP)
Definition: hardware.h:86
uint32_t ir
код пульта
Definition: ir_remote.h:18
#define IR_CAP_PORT
Символ порта захвата IR-команд
Definition: hardware.h:84
uint32_t get_ir_code(void)
получение кода ДУ
Definition: ir_remote.c:114
#define IR_NO_CMD
Заглушка "нет команды".
Definition: ir_remote.h:22
описания модуля дистанционного управления
uint32_t get_ir_cmd_code(control_cmd_t cmd)
получение IR-кода команды
Definition: ir_remote.c:156
ISR(TIMER1_CAPT_vect)
Definition: ir_remote.c:60
control_cmd_t cmd
команда управления
Definition: ir_remote.h:17
control_cmd_t get_ir_command(void)
поиск запрограммированной команды
Definition: ir_remote.c:140