irda_transmit.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 irda_get_raw_data_callback (void* context, uint32_t* duration, bool* level) {
  14. furi_assert(duration);
  15. furi_assert(level);
  16. furi_assert(context);
  17. FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateOk;
  18. const uint32_t* timings = context;
  19. if (irda_tx_raw_add_silence && (irda_tx_raw_timings_index == 0)) {
  20. irda_tx_raw_add_silence = false;
  21. *level = false;
  22. *duration = IRDA_RAW_TX_TIMING_DELAY_US;
  23. } else {
  24. *level = irda_tx_raw_start_from_mark ^ (irda_tx_raw_timings_index % 2);
  25. *duration = timings[irda_tx_raw_timings_index++];
  26. }
  27. if (irda_tx_raw_timings_number == irda_tx_raw_timings_index) {
  28. state = FuriHalIrdaTxGetDataStateLastDone;
  29. }
  30. return state;
  31. }
  32. void irda_send_raw_ext(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark, uint32_t frequency, float duty_cycle) {
  33. furi_assert(timings);
  34. irda_tx_raw_start_from_mark = start_from_mark;
  35. irda_tx_raw_timings_index = 0;
  36. irda_tx_raw_timings_number = timings_cnt;
  37. irda_tx_raw_add_silence = start_from_mark;
  38. furi_hal_irda_async_tx_set_data_isr_callback(irda_get_raw_data_callback, (void*) timings);
  39. furi_hal_irda_async_tx_start(frequency, duty_cycle);
  40. furi_hal_irda_async_tx_wait_termination();
  41. furi_assert(!furi_hal_irda_is_busy());
  42. }
  43. void irda_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark) {
  44. irda_send_raw_ext(timings, timings_cnt, start_from_mark, IRDA_COMMON_CARRIER_FREQUENCY, IRDA_COMMON_DUTY_CYCLE);
  45. }
  46. FuriHalIrdaTxGetDataState irda_get_data_callback (void* context, uint32_t* duration, bool* level) {
  47. FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateLastDone;
  48. IrdaEncoderHandler* handler = context;
  49. IrdaStatus status = IrdaStatusError;
  50. if (irda_tx_number_of_transmissions > 0) {
  51. status = irda_encode(handler, duration, level);
  52. }
  53. if (status == IrdaStatusError) {
  54. state = FuriHalIrdaTxGetDataStateLastDone;
  55. *duration = 0;
  56. *level = 0;
  57. } else if (status == IrdaStatusOk) {
  58. state = FuriHalIrdaTxGetDataStateOk;
  59. } else if (status == IrdaStatusDone) {
  60. state = FuriHalIrdaTxGetDataStateDone;
  61. if (--irda_tx_number_of_transmissions == 0) {
  62. state = FuriHalIrdaTxGetDataStateLastDone;
  63. }
  64. } else {
  65. furi_crash(NULL);
  66. }
  67. return state;
  68. }
  69. void irda_send(const IrdaMessage* message, int times) {
  70. furi_assert(message);
  71. furi_assert(times);
  72. furi_assert(irda_is_protocol_valid(message->protocol));
  73. IrdaEncoderHandler* handler = irda_alloc_encoder();
  74. irda_reset_encoder(handler, message);
  75. irda_tx_number_of_transmissions = times;
  76. uint32_t frequency = irda_get_protocol_frequency(message->protocol);
  77. float duty_cycle = irda_get_protocol_duty_cycle(message->protocol);
  78. furi_hal_irda_async_tx_set_data_isr_callback(irda_get_data_callback, handler);
  79. furi_hal_irda_async_tx_start(frequency, duty_cycle);
  80. furi_hal_irda_async_tx_wait_termination();
  81. irda_free_encoder(handler);
  82. furi_assert(!furi_hal_irda_is_busy());
  83. }