irda_transmit.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "irda.h"
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stddef.h>
  5. #include <furi.h>
  6. #include <furi_hal_irda.h>
  7. #include <furi_hal_delay.h>
  8. static uint32_t irda_tx_number_of_transmissions = 0;
  9. static uint32_t irda_tx_raw_timings_index = 0;
  10. static uint32_t irda_tx_raw_timings_number = 0;
  11. static uint32_t irda_tx_raw_start_from_mark = 0;
  12. static bool irda_tx_raw_add_silence = false;
  13. FuriHalIrdaTxGetDataState
  14. irda_get_raw_data_callback(void* context, uint32_t* duration, bool* level) {
  15. furi_assert(duration);
  16. furi_assert(level);
  17. furi_assert(context);
  18. FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateOk;
  19. const uint32_t* timings = context;
  20. if(irda_tx_raw_add_silence && (irda_tx_raw_timings_index == 0)) {
  21. irda_tx_raw_add_silence = false;
  22. *level = false;
  23. *duration = IRDA_RAW_TX_TIMING_DELAY_US;
  24. } else {
  25. *level = irda_tx_raw_start_from_mark ^ (irda_tx_raw_timings_index % 2);
  26. *duration = timings[irda_tx_raw_timings_index++];
  27. }
  28. if(irda_tx_raw_timings_number == irda_tx_raw_timings_index) {
  29. state = FuriHalIrdaTxGetDataStateLastDone;
  30. }
  31. return state;
  32. }
  33. void irda_send_raw_ext(
  34. const uint32_t timings[],
  35. uint32_t timings_cnt,
  36. bool start_from_mark,
  37. uint32_t frequency,
  38. float duty_cycle) {
  39. furi_assert(timings);
  40. irda_tx_raw_start_from_mark = start_from_mark;
  41. irda_tx_raw_timings_index = 0;
  42. irda_tx_raw_timings_number = timings_cnt;
  43. irda_tx_raw_add_silence = start_from_mark;
  44. furi_hal_irda_async_tx_set_data_isr_callback(irda_get_raw_data_callback, (void*)timings);
  45. furi_hal_irda_async_tx_start(frequency, duty_cycle);
  46. furi_hal_irda_async_tx_wait_termination();
  47. furi_assert(!furi_hal_irda_is_busy());
  48. }
  49. void irda_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark) {
  50. irda_send_raw_ext(
  51. timings,
  52. timings_cnt,
  53. start_from_mark,
  54. IRDA_COMMON_CARRIER_FREQUENCY,
  55. IRDA_COMMON_DUTY_CYCLE);
  56. }
  57. FuriHalIrdaTxGetDataState irda_get_data_callback(void* context, uint32_t* duration, bool* level) {
  58. FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateLastDone;
  59. IrdaEncoderHandler* handler = context;
  60. IrdaStatus status = IrdaStatusError;
  61. if(irda_tx_number_of_transmissions > 0) {
  62. status = irda_encode(handler, duration, level);
  63. }
  64. if(status == IrdaStatusError) {
  65. state = FuriHalIrdaTxGetDataStateLastDone;
  66. *duration = 0;
  67. *level = 0;
  68. } else if(status == IrdaStatusOk) {
  69. state = FuriHalIrdaTxGetDataStateOk;
  70. } else if(status == IrdaStatusDone) {
  71. state = FuriHalIrdaTxGetDataStateDone;
  72. if(--irda_tx_number_of_transmissions == 0) {
  73. state = FuriHalIrdaTxGetDataStateLastDone;
  74. }
  75. } else {
  76. furi_crash(NULL);
  77. }
  78. return state;
  79. }
  80. void irda_send(const IrdaMessage* message, int times) {
  81. furi_assert(message);
  82. furi_assert(times);
  83. furi_assert(irda_is_protocol_valid(message->protocol));
  84. IrdaEncoderHandler* handler = irda_alloc_encoder();
  85. irda_reset_encoder(handler, message);
  86. irda_tx_number_of_transmissions = times;
  87. uint32_t frequency = irda_get_protocol_frequency(message->protocol);
  88. float duty_cycle = irda_get_protocol_duty_cycle(message->protocol);
  89. furi_hal_irda_async_tx_set_data_isr_callback(irda_get_data_callback, handler);
  90. furi_hal_irda_async_tx_start(frequency, duty_cycle);
  91. furi_hal_irda_async_tx_wait_termination();
  92. irda_free_encoder(handler);
  93. furi_assert(!furi_hal_irda_is_busy());
  94. }