irda.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "flipper.h"
  2. #include "flipper_v2.h"
  3. #include "irda_nec.h"
  4. #include "irda_protocols.h"
  5. typedef enum {
  6. EventTypeTick,
  7. EventTypeKey,
  8. } EventType;
  9. typedef struct {
  10. union {
  11. InputEvent input;
  12. } value;
  13. EventType type;
  14. } Event;
  15. typedef struct {
  16. uint8_t mode_id;
  17. uint16_t carrier_freq;
  18. uint8_t carrier_duty_cycle_id;
  19. uint8_t nec_packet_id;
  20. } State;
  21. typedef void (*ModeInput)(Event*, State*);
  22. typedef void (*ModeRender)(CanvasApi*, State*);
  23. void input_carrier(Event* event, State* state);
  24. void render_carrier(CanvasApi* canvas, State* state);
  25. void input_nec(Event* event, State* state);
  26. void render_nec(CanvasApi* canvas, State* state);
  27. typedef struct {
  28. ModeRender render;
  29. ModeInput input;
  30. } Mode;
  31. typedef struct {
  32. uint8_t addr;
  33. uint8_t data;
  34. } NecPacket;
  35. const Mode modes[] = {
  36. {.render = render_carrier, .input = input_carrier},
  37. {.render = render_nec, .input = input_nec},
  38. };
  39. const NecPacket packets[] = {
  40. {.addr = 0xF7, .data = 0x59},
  41. {.addr = 0xFF, .data = 0x01},
  42. {.addr = 0xFF, .data = 0x10},
  43. {.addr = 0xFF, .data = 0x15},
  44. {.addr = 0xFF, .data = 0x25},
  45. {.addr = 0xFF, .data = 0xF0},
  46. };
  47. const float duty_cycles[] = {0.1, 0.25, 0.333, 0.5, 1.0};
  48. void render_carrier(CanvasApi* canvas, State* state) {
  49. canvas->set_font(canvas, FontSecondary);
  50. canvas->draw_str(canvas, 2, 25, "carrier mode >");
  51. canvas->draw_str(canvas, 2, 37, "? /\\ freq | \\/ duty cycle");
  52. {
  53. char buf[24];
  54. sprintf(buf, "frequency: %d Hz", state->carrier_freq);
  55. canvas->draw_str(canvas, 2, 50, buf);
  56. sprintf(
  57. buf,
  58. "duty cycle: %d/1000",
  59. (uint32_t)(duty_cycles[state->carrier_duty_cycle_id] * 1000));
  60. canvas->draw_str(canvas, 2, 62, buf);
  61. }
  62. }
  63. void render_nec(CanvasApi* canvas, State* state) {
  64. canvas->set_font(canvas, FontSecondary);
  65. canvas->draw_str(canvas, 2, 25, "< nec protocol mode");
  66. canvas->draw_str(canvas, 2, 37, "? /\\ \\/ packet");
  67. {
  68. char buf[24];
  69. sprintf(
  70. buf,
  71. "packet: %02X %02X",
  72. packets[state->nec_packet_id].addr,
  73. packets[state->nec_packet_id].data);
  74. canvas->draw_str(canvas, 2, 50, buf);
  75. }
  76. }
  77. void input_carrier(Event* event, State* state) {
  78. if(event->value.input.input == InputOk) {
  79. if(event->value.input.state) {
  80. pwm_set(
  81. duty_cycles[state->carrier_duty_cycle_id],
  82. state->carrier_freq,
  83. &htim2,
  84. TIM_CHANNEL_4);
  85. } else {
  86. pwm_stop(&htim2, TIM_CHANNEL_4);
  87. }
  88. }
  89. if(event->value.input.state && event->value.input.input == InputUp) {
  90. if(state->carrier_freq < 45000) {
  91. state->carrier_freq += 1000;
  92. } else {
  93. state->carrier_freq = 33000;
  94. }
  95. }
  96. if(event->value.input.state && event->value.input.input == InputDown) {
  97. uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
  98. if(state->carrier_duty_cycle_id < (duty_cycles_count - 1)) {
  99. state->carrier_duty_cycle_id++;
  100. } else {
  101. state->carrier_duty_cycle_id = 0;
  102. }
  103. }
  104. }
  105. void input_nec(Event* event, State* state) {
  106. if(event->value.input.input == InputOk) {
  107. if(event->value.input.state) {
  108. vTaskSuspendAll();
  109. ir_nec_send(packets[state->nec_packet_id].addr, packets[state->nec_packet_id].data);
  110. xTaskResumeAll();
  111. }
  112. }
  113. if(event->value.input.state && event->value.input.input == InputUp) {
  114. uint8_t packets_count = sizeof(packets) / sizeof(packets[0]);
  115. if(state->nec_packet_id < (packets_count - 1)) {
  116. state->nec_packet_id++;
  117. } else {
  118. state->nec_packet_id = 0;
  119. }
  120. }
  121. if(event->value.input.state && event->value.input.input == InputDown) {
  122. uint8_t packets_count = sizeof(packets) / sizeof(packets[0]);
  123. if(state->nec_packet_id > 0) {
  124. state->nec_packet_id--;
  125. } else {
  126. state->nec_packet_id = packets_count - 1;
  127. }
  128. }
  129. }
  130. static void render_callback(CanvasApi* canvas, void* ctx) {
  131. State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
  132. canvas->clear(canvas);
  133. canvas->set_color(canvas, ColorBlack);
  134. canvas->set_font(canvas, FontPrimary);
  135. canvas->draw_str(canvas, 2, 12, "irda test");
  136. modes[state->mode_id].render(canvas, state);
  137. release_mutex((ValueMutex*)ctx, state);
  138. }
  139. static void input_callback(InputEvent* input_event, void* ctx) {
  140. osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
  141. Event event;
  142. event.type = EventTypeKey;
  143. event.value.input = *input_event;
  144. osMessageQueuePut(event_queue, &event, 0, 0);
  145. }
  146. void irda(void* p) {
  147. osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(Event), NULL);
  148. State _state;
  149. uint8_t mode_count = sizeof(modes) / sizeof(modes[0]);
  150. uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]);
  151. _state.carrier_duty_cycle_id = duty_cycles_count - 2;
  152. _state.carrier_freq = 36000;
  153. _state.mode_id = 0;
  154. _state.nec_packet_id = 0;
  155. ValueMutex state_mutex;
  156. if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
  157. printf("cannot create mutex\n");
  158. furiac_exit(NULL);
  159. }
  160. Widget* widget = widget_alloc();
  161. widget_draw_callback_set(widget, render_callback, &state_mutex);
  162. widget_input_callback_set(widget, input_callback, event_queue);
  163. // Open GUI and register widget
  164. GuiApi* gui = (GuiApi*)furi_open("gui");
  165. if(gui == NULL) {
  166. printf("gui is not available\n");
  167. furiac_exit(NULL);
  168. }
  169. gui->add_widget(gui, widget, WidgetLayerFullscreen);
  170. Event event;
  171. while(1) {
  172. osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, osWaitForever);
  173. State* state = (State*)acquire_mutex_block(&state_mutex);
  174. if(event_status == osOK) {
  175. if(event.type == EventTypeKey) {
  176. // press events
  177. if(event.value.input.state && event.value.input.input == InputBack) {
  178. printf("[irda] bye!\n");
  179. // TODO remove all widgets create by app
  180. widget_enabled_set(widget, false);
  181. furiac_exit(NULL);
  182. }
  183. if(event.value.input.state && event.value.input.input == InputLeft) {
  184. if(state->mode_id > 0) {
  185. state->mode_id--;
  186. }
  187. }
  188. if(event.value.input.state && event.value.input.input == InputRight) {
  189. if(state->mode_id < (mode_count - 1)) {
  190. state->mode_id++;
  191. }
  192. }
  193. modes[state->mode_id].input(&event, state);
  194. }
  195. } else {
  196. // event timeout
  197. }
  198. release_mutex(&state_mutex, state);
  199. widget_update(widget);
  200. }
  201. }