infrared_transmit.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "infrared.h"
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stddef.h>
  5. #include <furi.h>
  6. #include <furi_hal_infrared.h>
  7. #include <furi_hal_delay.h>
  8. static uint32_t infrared_tx_number_of_transmissions = 0;
  9. static uint32_t infrared_tx_raw_timings_index = 0;
  10. static uint32_t infrared_tx_raw_timings_number = 0;
  11. static uint32_t infrared_tx_raw_start_from_mark = 0;
  12. static bool infrared_tx_raw_add_silence = false;
  13. FuriHalInfraredTxGetDataState
  14. infrared_get_raw_data_callback(void* context, uint32_t* duration, bool* level) {
  15. furi_assert(duration);
  16. furi_assert(level);
  17. furi_assert(context);
  18. FuriHalInfraredTxGetDataState state = FuriHalInfraredTxGetDataStateOk;
  19. const uint32_t* timings = context;
  20. if(infrared_tx_raw_add_silence && (infrared_tx_raw_timings_index == 0)) {
  21. infrared_tx_raw_add_silence = false;
  22. *level = false;
  23. *duration = INFRARED_RAW_TX_TIMING_DELAY_US;
  24. } else {
  25. *level = infrared_tx_raw_start_from_mark ^ (infrared_tx_raw_timings_index % 2);
  26. *duration = timings[infrared_tx_raw_timings_index++];
  27. }
  28. if(infrared_tx_raw_timings_number == infrared_tx_raw_timings_index) {
  29. state = FuriHalInfraredTxGetDataStateLastDone;
  30. }
  31. return state;
  32. }
  33. void infrared_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. infrared_tx_raw_start_from_mark = start_from_mark;
  41. infrared_tx_raw_timings_index = 0;
  42. infrared_tx_raw_timings_number = timings_cnt;
  43. infrared_tx_raw_add_silence = start_from_mark;
  44. furi_hal_infrared_async_tx_set_data_isr_callback(
  45. infrared_get_raw_data_callback, (void*)timings);
  46. furi_hal_infrared_async_tx_start(frequency, duty_cycle);
  47. furi_hal_infrared_async_tx_wait_termination();
  48. furi_assert(!furi_hal_infrared_is_busy());
  49. }
  50. void infrared_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark) {
  51. infrared_send_raw_ext(
  52. timings,
  53. timings_cnt,
  54. start_from_mark,
  55. INFRARED_COMMON_CARRIER_FREQUENCY,
  56. INFRARED_COMMON_DUTY_CYCLE);
  57. }
  58. FuriHalInfraredTxGetDataState
  59. infrared_get_data_callback(void* context, uint32_t* duration, bool* level) {
  60. FuriHalInfraredTxGetDataState state = FuriHalInfraredTxGetDataStateLastDone;
  61. InfraredEncoderHandler* handler = context;
  62. InfraredStatus status = InfraredStatusError;
  63. if(infrared_tx_number_of_transmissions > 0) {
  64. status = infrared_encode(handler, duration, level);
  65. }
  66. if(status == InfraredStatusError) {
  67. state = FuriHalInfraredTxGetDataStateLastDone;
  68. *duration = 0;
  69. *level = 0;
  70. } else if(status == InfraredStatusOk) {
  71. state = FuriHalInfraredTxGetDataStateOk;
  72. } else if(status == InfraredStatusDone) {
  73. state = FuriHalInfraredTxGetDataStateDone;
  74. if(--infrared_tx_number_of_transmissions == 0) {
  75. state = FuriHalInfraredTxGetDataStateLastDone;
  76. }
  77. } else {
  78. furi_crash(NULL);
  79. }
  80. return state;
  81. }
  82. void infrared_send(const InfraredMessage* message, int times) {
  83. furi_assert(message);
  84. furi_assert(times);
  85. furi_assert(infrared_is_protocol_valid(message->protocol));
  86. InfraredEncoderHandler* handler = infrared_alloc_encoder();
  87. infrared_reset_encoder(handler, message);
  88. infrared_tx_number_of_transmissions = times;
  89. uint32_t frequency = infrared_get_protocol_frequency(message->protocol);
  90. float duty_cycle = infrared_get_protocol_duty_cycle(message->protocol);
  91. furi_hal_infrared_async_tx_set_data_isr_callback(infrared_get_data_callback, handler);
  92. furi_hal_infrared_async_tx_start(frequency, duty_cycle);
  93. furi_hal_infrared_async_tx_wait_termination();
  94. infrared_free_encoder(handler);
  95. furi_assert(!furi_hal_infrared_is_busy());
  96. }