infrared_transmit.c 3.8 KB

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