irda.c 4.7 KB

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