irda.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include "flipper.h"
  2. #include "flipper_v2.h"
  3. #include "irda_nec.h"
  4. #include "irda_samsung.h"
  5. #include "irda_protocols.h"
  6. #include "irda-decoder/irda-decoder.h"
  7. typedef enum {
  8. EventTypeTick,
  9. EventTypeKey,
  10. EventTypeRX,
  11. } EventType;
  12. typedef struct {
  13. bool edge;
  14. uint32_t lasted;
  15. } RXValue;
  16. typedef struct {
  17. union {
  18. InputEvent input;
  19. RXValue rx;
  20. } value;
  21. EventType type;
  22. } AppEvent;
  23. typedef struct {
  24. IrDAProtocolType protocol;
  25. uint32_t address;
  26. uint32_t command;
  27. } IrDAPacket;
  28. #define IRDA_PACKET_COUNT 8
  29. typedef struct {
  30. uint8_t mode_id;
  31. uint16_t carrier_freq;
  32. uint8_t carrier_duty_cycle_id;
  33. uint8_t packet_id;
  34. IrDAPacket packets[IRDA_PACKET_COUNT];
  35. } State;
  36. typedef void (*ModeInput)(AppEvent*, State*);
  37. typedef void (*ModeRender)(Canvas*, State*);
  38. void input_carrier(AppEvent* event, State* state);
  39. void render_carrier(Canvas* canvas, State* state);
  40. void input_packet(AppEvent* event, State* state);
  41. void render_packet(Canvas* canvas, State* state);
  42. typedef struct {
  43. ModeRender render;
  44. ModeInput input;
  45. } Mode;
  46. const Mode modes[] = {
  47. {.render = render_carrier, .input = input_carrier},
  48. {.render = render_packet, .input = input_packet},
  49. };
  50. const float duty_cycles[] = {0.1, 0.25, 0.333, 0.5, 1.0};
  51. void render_carrier(Canvas* canvas, State* state) {
  52. canvas_set_font(canvas, FontSecondary);
  53. canvas_draw_str(canvas, 2, 25, "carrier mode >");
  54. canvas_draw_str(canvas, 2, 37, "? /\\ freq | \\/ duty cycle");
  55. {
  56. char buf[24];
  57. sprintf(buf, "frequency: %u Hz", state->carrier_freq);
  58. canvas_draw_str(canvas, 2, 50, buf);
  59. sprintf(
  60. buf, "duty cycle: %d/1000", (int)(duty_cycles[state->carrier_duty_cycle_id] * 1000));
  61. canvas_draw_str(canvas, 2, 62, buf);
  62. }
  63. }
  64. void input_carrier(AppEvent* event, State* state) {
  65. if(event->value.input.input == InputOk) {
  66. if(event->value.input.state) {
  67. irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq);
  68. } else {
  69. irda_pwm_stop();
  70. }
  71. }
  72. if(event->value.input.state && event->value.input.input == InputUp) {
  73. if(state->carrier_freq < 45000) {
  74. state->carrier_freq += 1000;
  75. } else {
  76. state->carrier_freq = 33000;
  77. }
  78. }
  79. if(event->value.input.state && event->value.input.input == InputDown) {
  80. uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
  81. if(state->carrier_duty_cycle_id < (duty_cycles_count - 1)) {
  82. state->carrier_duty_cycle_id++;
  83. } else {
  84. state->carrier_duty_cycle_id = 0;
  85. }
  86. }
  87. }
  88. void render_packet(Canvas* canvas, State* state) {
  89. canvas_set_font(canvas, FontSecondary);
  90. canvas_draw_str(canvas, 2, 25, "< packet mode");
  91. canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet");
  92. {
  93. const char* protocol;
  94. switch(state->packets[state->packet_id].protocol) {
  95. case IRDA_NEC:
  96. protocol = "NEC";
  97. break;
  98. case IRDA_SAMSUNG:
  99. protocol = "SAMS";
  100. break;
  101. case IRDA_UNKNOWN:
  102. default:
  103. protocol = "UNK";
  104. break;
  105. }
  106. char buf[24];
  107. sprintf(
  108. buf,
  109. "P[%d]: %s 0x%X 0x%X",
  110. state->packet_id,
  111. protocol,
  112. state->packets[state->packet_id].address,
  113. state->packets[state->packet_id].command);
  114. canvas_draw_str(canvas, 2, 50, buf);
  115. }
  116. }
  117. void input_packet(AppEvent* event, State* state) {
  118. if(event->value.input.input == InputOk) {
  119. if(event->value.input.state) {
  120. vTaskSuspendAll();
  121. switch(state->packets[state->packet_id].protocol) {
  122. case IRDA_NEC:
  123. ir_nec_send(
  124. state->packets[state->packet_id].address,
  125. state->packets[state->packet_id].command);
  126. break;
  127. case IRDA_SAMSUNG:
  128. ir_samsung_send(
  129. state->packets[state->packet_id].address,
  130. state->packets[state->packet_id].command);
  131. break;
  132. default:
  133. break;
  134. }
  135. xTaskResumeAll();
  136. }
  137. }
  138. if(event->value.input.state && event->value.input.input == InputDown) {
  139. if(state->packet_id < (IRDA_PACKET_COUNT - 1)) {
  140. state->packet_id++;
  141. };
  142. }
  143. if(event->value.input.state && event->value.input.input == InputUp) {
  144. if(state->packet_id > 0) {
  145. state->packet_id--;
  146. };
  147. }
  148. }
  149. static void render_callback(Canvas* canvas, void* ctx) {
  150. State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
  151. if(state != NULL) {
  152. canvas_clear(canvas);
  153. canvas_set_color(canvas, ColorBlack);
  154. canvas_set_font(canvas, FontPrimary);
  155. canvas_draw_str(canvas, 2, 12, "irda test");
  156. modes[state->mode_id].render(canvas, state);
  157. release_mutex((ValueMutex*)ctx, state);
  158. }
  159. }
  160. static void input_callback(InputEvent* input_event, void* ctx) {
  161. osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
  162. AppEvent event;
  163. event.type = EventTypeKey;
  164. event.value.input = *input_event;
  165. osMessageQueuePut(event_queue, &event, 0, 0);
  166. }
  167. void irda_timer_capture_callback(void* htim, void* comp_ctx) {
  168. TIM_HandleTypeDef* _htim = (TIM_HandleTypeDef*)htim;
  169. osMessageQueueId_t event_queue = (osMessageQueueId_t)comp_ctx;
  170. if(_htim->Instance == TIM2) {
  171. AppEvent event;
  172. event.type = EventTypeRX;
  173. uint32_t channel;
  174. if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
  175. // falling event
  176. event.value.rx.edge = false;
  177. channel = TIM_CHANNEL_1;
  178. } else if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
  179. // rising event
  180. event.value.rx.edge = true;
  181. channel = TIM_CHANNEL_2;
  182. } else {
  183. // not our event
  184. return;
  185. }
  186. event.value.rx.lasted = HAL_TIM_ReadCapturedValue(_htim, channel);
  187. __HAL_TIM_SET_COUNTER(_htim, 0);
  188. osMessageQueuePut(event_queue, &event, 0, 0);
  189. }
  190. }
  191. void init_packet(
  192. State* state,
  193. uint8_t index,
  194. IrDAProtocolType protocol,
  195. uint32_t address,
  196. uint32_t command) {
  197. if(index >= IRDA_PACKET_COUNT) return;
  198. state->packets[index].protocol = protocol;
  199. state->packets[index].address = address;
  200. state->packets[index].command = command;
  201. }
  202. void irda(void* p) {
  203. osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL);
  204. State _state;
  205. uint8_t mode_count = sizeof(modes) / sizeof(modes[0]);
  206. uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
  207. _state.carrier_duty_cycle_id = duty_cycles_count - 2;
  208. _state.carrier_freq = 36000;
  209. _state.mode_id = 0;
  210. _state.packet_id = 0;
  211. for(uint8_t i = 0; i < IRDA_PACKET_COUNT; i++) {
  212. init_packet(&_state, i, IRDA_UNKNOWN, 0, 0);
  213. }
  214. init_packet(&_state, 0, IRDA_NEC, 0xFF00, 0x11);
  215. init_packet(&_state, 1, IRDA_NEC, 0xF708, 0x59);
  216. init_packet(&_state, 2, IRDA_NEC, 0xFF00, 0x10);
  217. init_packet(&_state, 3, IRDA_NEC, 0xFF00, 0x15);
  218. init_packet(&_state, 4, IRDA_NEC, 0xFF00, 0x25);
  219. init_packet(&_state, 5, IRDA_SAMSUNG, 0xE0E, 0xF30C);
  220. init_packet(&_state, 6, IRDA_SAMSUNG, 0xE0E, 0xF40D);
  221. init_packet(&_state, 7, IRDA_SAMSUNG, 0xE0E, 0xF50E);
  222. ValueMutex state_mutex;
  223. if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
  224. printf("cannot create mutex\n");
  225. furiac_exit(NULL);
  226. }
  227. Widget* widget = widget_alloc();
  228. widget_draw_callback_set(widget, render_callback, &state_mutex);
  229. widget_input_callback_set(widget, input_callback, event_queue);
  230. // Open GUI and register widget
  231. Gui* gui = (Gui*)furi_open("gui");
  232. if(gui == NULL) {
  233. printf("gui is not available\n");
  234. furiac_exit(NULL);
  235. }
  236. gui_add_widget(gui, widget, GuiLayerFullscreen);
  237. // Red LED
  238. // TODO open record
  239. const GpioPin* red_led_record = &led_gpio[0];
  240. const GpioPin* green_led_record = &led_gpio[1];
  241. // configure pin
  242. gpio_init(red_led_record, GpioModeOutputOpenDrain);
  243. gpio_init(green_led_record, GpioModeOutputOpenDrain);
  244. // setup irda rx timer
  245. tim_irda_rx_init();
  246. // add timer capture interrupt
  247. api_interrupt_add(irda_timer_capture_callback, InterruptTypeTimerCapture, event_queue);
  248. IrDADecoder* decoder = alloc_decoder();
  249. AppEvent event;
  250. while(1) {
  251. osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 500);
  252. State* state = (State*)acquire_mutex_block(&state_mutex);
  253. if(event_status == osOK) {
  254. if(event.type == EventTypeKey) {
  255. // press events
  256. if(event.value.input.state && event.value.input.input == InputBack) {
  257. // remove all widgets create by app
  258. widget_enabled_set(widget, false);
  259. gui_remove_widget(gui, widget);
  260. // free decoder
  261. free_decoder(decoder);
  262. // exit
  263. furiac_exit(NULL);
  264. }
  265. if(event.value.input.state && event.value.input.input == InputLeft) {
  266. if(state->mode_id > 0) {
  267. state->mode_id--;
  268. }
  269. }
  270. if(event.value.input.state && event.value.input.input == InputRight) {
  271. if(state->mode_id < (mode_count - 1)) {
  272. state->mode_id++;
  273. }
  274. }
  275. modes[state->mode_id].input(&event, state);
  276. } else if(event.type == EventTypeRX) {
  277. IrDADecoderOutputData out;
  278. const uint8_t out_data_length = 4;
  279. uint8_t out_data[out_data_length];
  280. out.data_length = out_data_length;
  281. out.data = out_data;
  282. gpio_write(red_led_record, event.value.rx.edge);
  283. bool decoded =
  284. process_decoder(decoder, event.value.rx.edge, &event.value.rx.lasted, 1, &out);
  285. if(decoded) {
  286. // save only if we in packet mode
  287. if(state->mode_id == 1) {
  288. if(out.protocol == IRDA_NEC) {
  289. printf("P=NEC ");
  290. printf("A=0x%02X%02X ", out_data[1], out_data[0]);
  291. printf("C=0x%02X ", out_data[2]);
  292. if(out.flags & IRDA_REPEAT) {
  293. printf("R");
  294. }
  295. printf("\r\n");
  296. state->packets[state->packet_id].protocol = IRDA_NEC;
  297. state->packets[state->packet_id].address = out_data[1] << 8 |
  298. out_data[0];
  299. state->packets[state->packet_id].command = out_data[2];
  300. } else {
  301. printf("Unknown protocol\r\n");
  302. }
  303. }
  304. // blink anyway
  305. gpio_write(green_led_record, false);
  306. delay(10);
  307. gpio_write(green_led_record, true);
  308. }
  309. }
  310. } else {
  311. // event timeout
  312. }
  313. release_mutex(&state_mutex, state);
  314. widget_update(widget);
  315. }
  316. }