irda.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <stdbool.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <furi.h>
  5. #include "irda_i.h"
  6. struct IrdaHandler {
  7. void** ctx;
  8. };
  9. typedef struct {
  10. IrdaAlloc alloc;
  11. IrdaDecode decode;
  12. IrdaReset reset;
  13. IrdaFree free;
  14. } IrdaDecoders;
  15. typedef struct {
  16. IrdaEncode encode;
  17. } IrdaEncoders;
  18. typedef struct {
  19. IrdaProtocol protocol;
  20. const char* name;
  21. IrdaDecoders decoder;
  22. IrdaEncoders encoder;
  23. uint8_t address_length;
  24. uint8_t command_length;
  25. } IrdaProtocolImplementation;
  26. // TODO: replace with key-value, Now we refer by enum index, which is dangerous.
  27. static const IrdaProtocolImplementation irda_protocols[] = {
  28. // #0
  29. { .protocol = IrdaProtocolSamsung32,
  30. .name ="Samsung32",
  31. .decoder = {
  32. .alloc = irda_decoder_samsung32_alloc,
  33. .decode = irda_decoder_samsung32_decode,
  34. .reset = irda_decoder_samsung32_reset,
  35. .free = irda_decoder_samsung32_free},
  36. .encoder = {
  37. .encode = irda_encoder_samsung32_encode},
  38. .address_length = 2,
  39. .command_length = 2,
  40. },
  41. // #1
  42. { .protocol = IrdaProtocolNEC,
  43. .name = "NEC",
  44. .decoder = {
  45. .alloc = irda_decoder_nec_alloc,
  46. .decode = irda_decoder_nec_decode,
  47. .reset = irda_decoder_nec_reset,
  48. .free = irda_decoder_nec_free},
  49. .encoder = {
  50. .encode = irda_encoder_nec_encode},
  51. .address_length = 2,
  52. .command_length = 2,
  53. },
  54. // #2
  55. { .protocol = IrdaProtocolNECext,
  56. .name = "NECext",
  57. .decoder = {
  58. .alloc = irda_decoder_necext_alloc,
  59. .decode = irda_decoder_nec_decode,
  60. .reset = irda_decoder_nec_reset,
  61. .free = irda_decoder_nec_free},
  62. .encoder = {
  63. .encode = irda_encoder_necext_encode},
  64. .address_length = 4,
  65. .command_length = 2,
  66. },
  67. };
  68. const IrdaMessage* irda_decode(IrdaHandler* handler, bool level, uint32_t duration) {
  69. furi_assert(handler);
  70. IrdaMessage* message = NULL;
  71. IrdaMessage* result = NULL;
  72. for (int i = 0; i < COUNT_OF(irda_protocols); ++i) {
  73. message = irda_protocols[i].decoder.decode(handler->ctx[i], level, duration);
  74. if (!result && message) {
  75. message->protocol = irda_protocols[i].protocol;
  76. result = message;
  77. }
  78. }
  79. return result;
  80. }
  81. IrdaHandler* irda_alloc_decoder(void) {
  82. IrdaHandler* handler = furi_alloc(sizeof(IrdaHandler));
  83. handler->ctx = furi_alloc(sizeof(void*) * COUNT_OF(irda_protocols));
  84. for (int i = 0; i < COUNT_OF(irda_protocols); ++i) {
  85. handler->ctx[i] = irda_protocols[i].decoder.alloc();
  86. furi_check(handler->ctx[i]);
  87. }
  88. return handler;
  89. }
  90. void irda_free_decoder(IrdaHandler* handler) {
  91. furi_assert(handler);
  92. furi_assert(handler->ctx);
  93. for (int i = 0; i < COUNT_OF(irda_protocols); ++i) {
  94. irda_protocols[i].decoder.free(handler->ctx[i]);
  95. }
  96. free(handler->ctx);
  97. free(handler);
  98. }
  99. void irda_reset_decoder(IrdaHandler* handler) {
  100. for (int i = 0; i < COUNT_OF(irda_protocols); ++i) {
  101. irda_protocols[i].decoder.reset(handler->ctx[i]);
  102. }
  103. }
  104. void irda_send(const IrdaMessage* message, int times) {
  105. furi_assert(message);
  106. for (int i = 0; i < times; ++i) {
  107. osKernelLock();
  108. __disable_irq();
  109. irda_protocols[message->protocol].encoder.encode(message->address, message->command, !!i);
  110. __enable_irq();
  111. osKernelUnlock();
  112. }
  113. }
  114. const char* irda_get_protocol_name(IrdaProtocol protocol) {
  115. return irda_protocols[protocol].name;
  116. }
  117. uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) {
  118. return irda_protocols[protocol].address_length;
  119. }
  120. uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) {
  121. return irda_protocols[protocol].command_length;
  122. }