digital_signal.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "digital_signal.h"
  2. #include <furi.h>
  3. #include <stm32wbxx_ll_dma.h>
  4. #include <stm32wbxx_ll_tim.h>
  5. #include <math.h>
  6. #pragma GCC optimize("O3,unroll-loops,Ofast")
  7. #define F_TIM (64000000.0)
  8. #define T_TIM 1562 //15.625 ns *100
  9. #define T_TIM_DIV2 781 //15.625 ns / 2 *100
  10. DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
  11. DigitalSignal* signal = malloc(sizeof(DigitalSignal));
  12. signal->start_level = true;
  13. signal->edges_max_cnt = max_edges_cnt;
  14. signal->edge_timings = malloc(max_edges_cnt * sizeof(uint32_t));
  15. signal->reload_reg_buff = malloc(max_edges_cnt * sizeof(uint32_t));
  16. signal->edge_cnt = 0;
  17. return signal;
  18. }
  19. void digital_signal_free(DigitalSignal* signal) {
  20. furi_assert(signal);
  21. free(signal->edge_timings);
  22. free(signal->reload_reg_buff);
  23. free(signal);
  24. }
  25. bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b) {
  26. furi_assert(signal_a);
  27. furi_assert(signal_b);
  28. if(signal_a->edges_max_cnt < signal_a->edge_cnt + signal_b->edge_cnt) {
  29. return false;
  30. }
  31. bool end_level = signal_a->start_level;
  32. if(signal_a->edge_cnt) {
  33. end_level = signal_a->start_level ^ !(signal_a->edge_cnt % 2);
  34. }
  35. uint8_t start_copy = 0;
  36. if(end_level == signal_b->start_level) {
  37. if(signal_a->edge_cnt) {
  38. signal_a->edge_timings[signal_a->edge_cnt - 1] += signal_b->edge_timings[0];
  39. start_copy += 1;
  40. } else {
  41. signal_a->edge_timings[signal_a->edge_cnt] += signal_b->edge_timings[0];
  42. }
  43. }
  44. for(size_t i = 0; i < signal_b->edge_cnt - start_copy; i++) {
  45. signal_a->edge_timings[signal_a->edge_cnt + i] = signal_b->edge_timings[start_copy + i];
  46. }
  47. signal_a->edge_cnt += signal_b->edge_cnt - start_copy;
  48. return true;
  49. }
  50. bool digital_signal_get_start_level(DigitalSignal* signal) {
  51. furi_assert(signal);
  52. return signal->start_level;
  53. }
  54. uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal) {
  55. furi_assert(signal);
  56. return signal->edge_cnt;
  57. }
  58. uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) {
  59. furi_assert(signal);
  60. furi_assert(edge_num < signal->edge_cnt);
  61. return signal->edge_timings[edge_num];
  62. }
  63. void digital_signal_prepare_arr(DigitalSignal* signal) {
  64. uint32_t t_signal_rest = signal->edge_timings[0];
  65. uint32_t r_count_tick_arr = 0;
  66. uint32_t r_rest_div = 0;
  67. for(size_t i = 0; i < signal->edge_cnt - 1; i++) {
  68. r_count_tick_arr = t_signal_rest / T_TIM;
  69. r_rest_div = t_signal_rest % T_TIM;
  70. t_signal_rest = signal->edge_timings[i + 1] + r_rest_div;
  71. if(r_rest_div < T_TIM_DIV2) {
  72. signal->reload_reg_buff[i] = r_count_tick_arr - 1;
  73. } else {
  74. signal->reload_reg_buff[i] = r_count_tick_arr;
  75. t_signal_rest -= T_TIM;
  76. }
  77. }
  78. }
  79. void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) {
  80. furi_assert(signal);
  81. furi_assert(gpio);
  82. // Configure gpio as output
  83. furi_hal_gpio_init(gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
  84. // Init gpio buffer and DMA channel
  85. uint16_t gpio_reg = gpio->port->ODR;
  86. uint16_t gpio_buff[2];
  87. if(signal->start_level) {
  88. gpio_buff[0] = gpio_reg | gpio->pin;
  89. gpio_buff[1] = gpio_reg & ~(gpio->pin);
  90. } else {
  91. gpio_buff[0] = gpio_reg & ~(gpio->pin);
  92. gpio_buff[1] = gpio_reg | gpio->pin;
  93. }
  94. LL_DMA_InitTypeDef dma_config = {};
  95. dma_config.MemoryOrM2MDstAddress = (uint32_t)gpio_buff;
  96. dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->ODR);
  97. dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  98. dma_config.Mode = LL_DMA_MODE_CIRCULAR;
  99. dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  100. dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  101. dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
  102. dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
  103. dma_config.NbData = 2;
  104. dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  105. dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
  106. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config);
  107. LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 2);
  108. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
  109. // Init timer arr register buffer and DMA channel
  110. digital_signal_prepare_arr(signal);
  111. dma_config.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff;
  112. dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
  113. dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  114. dma_config.Mode = LL_DMA_MODE_NORMAL;
  115. dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  116. dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  117. dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
  118. dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
  119. dma_config.NbData = signal->edge_cnt - 2;
  120. dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  121. dma_config.Priority = LL_DMA_PRIORITY_HIGH;
  122. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
  123. LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, signal->edge_cnt - 2);
  124. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
  125. // Set up timer
  126. LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
  127. LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
  128. LL_TIM_SetPrescaler(TIM2, 0);
  129. LL_TIM_SetAutoReload(TIM2, 10);
  130. LL_TIM_SetCounter(TIM2, 0);
  131. LL_TIM_EnableUpdateEvent(TIM2);
  132. LL_TIM_EnableDMAReq_UPDATE(TIM2);
  133. // Start transactions
  134. LL_TIM_GenerateEvent_UPDATE(TIM2); // Do we really need it?
  135. LL_TIM_EnableCounter(TIM2);
  136. while(!LL_DMA_IsActiveFlag_TC2(DMA1))
  137. ;
  138. LL_DMA_ClearFlag_TC1(DMA1);
  139. LL_DMA_ClearFlag_TC2(DMA1);
  140. LL_TIM_DisableCounter(TIM2);
  141. LL_TIM_SetCounter(TIM2, 0);
  142. LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
  143. LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
  144. }