digital_signal.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. #include "digital_signal.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #include <furi_hal_resources.h>
  5. #include <math.h>
  6. #include <stm32wbxx_ll_dma.h>
  7. #include <stm32wbxx_ll_tim.h>
  8. /* must be on bank B */
  9. #define DEBUG_OUTPUT gpio_ext_pb3
  10. struct ReloadBuffer {
  11. uint32_t* buffer; /* DMA ringbuffer */
  12. uint32_t size; /* maximum entry count of the ring buffer */
  13. uint32_t write_pos; /* current buffer write index */
  14. uint32_t read_pos; /* current buffer read index */
  15. bool dma_active;
  16. };
  17. struct DigitalSequence {
  18. uint8_t signals_size;
  19. bool bake;
  20. uint32_t sequence_used;
  21. uint32_t sequence_size;
  22. DigitalSignal** signals;
  23. uint8_t* sequence;
  24. const GpioPin* gpio;
  25. uint32_t send_time;
  26. bool send_time_active;
  27. LL_DMA_InitTypeDef dma_config_gpio;
  28. LL_DMA_InitTypeDef dma_config_timer;
  29. uint32_t* gpio_buff;
  30. struct ReloadBuffer* dma_buffer;
  31. };
  32. struct DigitalSignalInternals {
  33. uint64_t factor;
  34. uint32_t reload_reg_entries;
  35. uint32_t reload_reg_remainder;
  36. uint32_t gpio_buff[2];
  37. const GpioPin* gpio;
  38. LL_DMA_InitTypeDef dma_config_gpio;
  39. LL_DMA_InitTypeDef dma_config_timer;
  40. };
  41. #define TAG "DigitalSignal"
  42. #define F_TIM (64000000.0)
  43. #define T_TIM 1562 /* 15.625 ns *100 */
  44. #define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */
  45. /* maximum entry count of the sequence dma ring buffer */
  46. #define SEQUENCE_DMA_RINGBUFFER_SIZE 32
  47. /* maximum number of DigitalSignals in a sequence */
  48. #define SEQUENCE_SIGNALS_SIZE 32
  49. /*
  50. * if sequence size runs out from the initial value passed to digital_sequence_alloc
  51. * the size will be increased by this amount and reallocated
  52. */
  53. #define SEQUENCE_SIZE_REALLOCATE_INCREMENT 256
  54. DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
  55. DigitalSignal* signal = malloc(sizeof(DigitalSignal));
  56. signal->start_level = true;
  57. signal->edges_max_cnt = max_edges_cnt;
  58. signal->edge_timings = malloc(signal->edges_max_cnt * sizeof(uint32_t));
  59. signal->edge_cnt = 0;
  60. signal->reload_reg_buff = malloc(signal->edges_max_cnt * sizeof(uint32_t));
  61. signal->internals = malloc(sizeof(DigitalSignalInternals));
  62. DigitalSignalInternals* internals = signal->internals;
  63. internals->factor = 1024 * 1024;
  64. internals->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  65. internals->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
  66. internals->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  67. internals->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  68. internals->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
  69. internals->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
  70. internals->dma_config_gpio.NbData = 2;
  71. internals->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  72. internals->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
  73. internals->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
  74. internals->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  75. internals->dma_config_timer.Mode = LL_DMA_MODE_NORMAL;
  76. internals->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  77. internals->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  78. internals->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
  79. internals->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
  80. internals->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  81. internals->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH;
  82. return signal;
  83. }
  84. void digital_signal_free(DigitalSignal* signal) {
  85. furi_assert(signal);
  86. free(signal->edge_timings);
  87. free(signal->reload_reg_buff);
  88. free(signal->internals);
  89. free(signal);
  90. }
  91. bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b) {
  92. furi_assert(signal_a);
  93. furi_assert(signal_b);
  94. if(signal_a->edges_max_cnt < signal_a->edge_cnt + signal_b->edge_cnt) {
  95. return false;
  96. }
  97. /* in case there are no edges in our target signal, the signal to append makes the rules */
  98. if(!signal_a->edge_cnt) {
  99. signal_a->start_level = signal_b->start_level;
  100. }
  101. bool end_level = signal_a->start_level;
  102. if(signal_a->edge_cnt) {
  103. end_level = signal_a->start_level ^ !(signal_a->edge_cnt % 2);
  104. }
  105. uint8_t start_copy = 0;
  106. if(end_level == signal_b->start_level) {
  107. if(signal_a->edge_cnt) {
  108. signal_a->edge_timings[signal_a->edge_cnt - 1] += signal_b->edge_timings[0];
  109. start_copy += 1;
  110. } else {
  111. signal_a->edge_timings[signal_a->edge_cnt] += signal_b->edge_timings[0];
  112. }
  113. }
  114. for(size_t i = 0; i < signal_b->edge_cnt - start_copy; i++) {
  115. signal_a->edge_timings[signal_a->edge_cnt + i] = signal_b->edge_timings[start_copy + i];
  116. }
  117. signal_a->edge_cnt += signal_b->edge_cnt - start_copy;
  118. return true;
  119. }
  120. bool digital_signal_get_start_level(DigitalSignal* signal) {
  121. furi_assert(signal);
  122. return signal->start_level;
  123. }
  124. uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal) {
  125. furi_assert(signal);
  126. return signal->edge_cnt;
  127. }
  128. void digital_signal_add(DigitalSignal* signal, uint32_t ticks) {
  129. furi_assert(signal);
  130. furi_assert(signal->edge_cnt < signal->edges_max_cnt);
  131. signal->edge_timings[signal->edge_cnt++] = ticks;
  132. }
  133. void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level) {
  134. furi_assert(signal);
  135. furi_assert(signal->edge_cnt < signal->edges_max_cnt);
  136. /* virgin signal? add it as the only level */
  137. if(signal->edge_cnt == 0) {
  138. signal->start_level = level;
  139. signal->edge_timings[signal->edge_cnt++] = ticks;
  140. } else {
  141. bool end_level = signal->start_level ^ !(signal->edge_cnt % 2);
  142. if(level != end_level) {
  143. signal->edge_timings[signal->edge_cnt++] = ticks;
  144. } else {
  145. signal->edge_timings[signal->edge_cnt - 1] += ticks;
  146. }
  147. }
  148. }
  149. uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) {
  150. furi_assert(signal);
  151. furi_assert(edge_num < signal->edge_cnt);
  152. return signal->edge_timings[edge_num];
  153. }
  154. void digital_signal_prepare_arr(DigitalSignal* signal) {
  155. furi_assert(signal);
  156. DigitalSignalInternals* internals = signal->internals;
  157. /* set up signal polarities */
  158. if(internals->gpio) {
  159. uint32_t bit_set = internals->gpio->pin;
  160. uint32_t bit_reset = internals->gpio->pin << 16;
  161. #ifdef DEBUG_OUTPUT
  162. bit_set |= DEBUG_OUTPUT.pin;
  163. bit_reset |= DEBUG_OUTPUT.pin << 16;
  164. #endif
  165. if(signal->start_level) {
  166. internals->gpio_buff[0] = bit_set;
  167. internals->gpio_buff[1] = bit_reset;
  168. } else {
  169. internals->gpio_buff[0] = bit_reset;
  170. internals->gpio_buff[1] = bit_set;
  171. }
  172. }
  173. /* set up edge timings */
  174. internals->reload_reg_entries = 0;
  175. for(size_t pos = 0; pos < signal->edge_cnt; pos++) {
  176. uint32_t edge_scaled = (internals->factor * signal->edge_timings[pos]) / (1024 * 1024);
  177. uint32_t pulse_duration = edge_scaled + internals->reload_reg_remainder;
  178. if(pulse_duration < 10 || pulse_duration > 10000000) {
  179. FURI_LOG_D(
  180. TAG,
  181. "[prepare] pulse_duration out of range: %lu = %lu * %llu",
  182. pulse_duration,
  183. signal->edge_timings[pos],
  184. internals->factor);
  185. pulse_duration = 100;
  186. }
  187. uint32_t pulse_ticks = (pulse_duration + T_TIM_DIV2) / T_TIM;
  188. internals->reload_reg_remainder = pulse_duration - (pulse_ticks * T_TIM);
  189. if(pulse_ticks > 1) {
  190. signal->reload_reg_buff[internals->reload_reg_entries++] = pulse_ticks - 1;
  191. }
  192. }
  193. }
  194. static void digital_signal_stop_dma() {
  195. LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
  196. LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
  197. LL_DMA_ClearFlag_TC1(DMA1);
  198. LL_DMA_ClearFlag_TC2(DMA1);
  199. }
  200. static void digital_signal_stop_timer() {
  201. LL_TIM_DisableCounter(TIM2);
  202. LL_TIM_DisableUpdateEvent(TIM2);
  203. LL_TIM_DisableDMAReq_UPDATE(TIM2);
  204. }
  205. static void digital_signal_setup_timer() {
  206. digital_signal_stop_timer();
  207. LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
  208. LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
  209. LL_TIM_SetPrescaler(TIM2, 0);
  210. LL_TIM_SetAutoReload(TIM2, 0xFFFFFFFF);
  211. LL_TIM_SetCounter(TIM2, 0);
  212. }
  213. static void digital_signal_start_timer() {
  214. LL_TIM_EnableCounter(TIM2);
  215. LL_TIM_EnableUpdateEvent(TIM2);
  216. LL_TIM_EnableDMAReq_UPDATE(TIM2);
  217. LL_TIM_GenerateEvent_UPDATE(TIM2);
  218. }
  219. static bool digital_signal_setup_dma(DigitalSignal* signal) {
  220. furi_assert(signal);
  221. DigitalSignalInternals* internals = signal->internals;
  222. if(!signal->internals->reload_reg_entries) {
  223. return false;
  224. }
  225. digital_signal_stop_dma();
  226. internals->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)internals->gpio_buff;
  227. internals->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (internals->gpio->port->BSRR);
  228. internals->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff;
  229. internals->dma_config_timer.NbData = signal->internals->reload_reg_entries;
  230. /* set up DMA channel 1 and 2 for GPIO and timer copy operations */
  231. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &internals->dma_config_gpio);
  232. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &internals->dma_config_timer);
  233. /* enable both DMA channels */
  234. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
  235. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
  236. return true;
  237. }
  238. void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) {
  239. furi_assert(signal);
  240. if(!signal->edge_cnt) {
  241. return;
  242. }
  243. /* Configure gpio as output */
  244. signal->internals->gpio = gpio;
  245. furi_hal_gpio_init(
  246. signal->internals->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
  247. digital_signal_prepare_arr(signal);
  248. digital_signal_setup_dma(signal);
  249. digital_signal_setup_timer();
  250. digital_signal_start_timer();
  251. while(!LL_DMA_IsActiveFlag_TC2(DMA1)) {
  252. }
  253. digital_signal_stop_timer();
  254. digital_signal_stop_dma();
  255. }
  256. static void digital_sequence_alloc_signals(DigitalSequence* sequence, uint32_t size) {
  257. sequence->signals_size = size;
  258. sequence->signals = malloc(sequence->signals_size * sizeof(DigitalSignal*));
  259. }
  260. static void digital_sequence_alloc_sequence(DigitalSequence* sequence, uint32_t size) {
  261. sequence->sequence_used = 0;
  262. sequence->sequence_size = size;
  263. sequence->sequence = malloc(sequence->sequence_size);
  264. sequence->send_time = 0;
  265. sequence->send_time_active = false;
  266. }
  267. DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) {
  268. furi_assert(gpio);
  269. DigitalSequence* sequence = malloc(sizeof(DigitalSequence));
  270. sequence->gpio = gpio;
  271. sequence->bake = false;
  272. sequence->dma_buffer = malloc(sizeof(struct ReloadBuffer));
  273. sequence->dma_buffer->size = SEQUENCE_DMA_RINGBUFFER_SIZE;
  274. sequence->dma_buffer->buffer = malloc(sequence->dma_buffer->size * sizeof(uint32_t));
  275. sequence->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  276. sequence->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
  277. sequence->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  278. sequence->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  279. sequence->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
  280. sequence->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
  281. sequence->dma_config_gpio.NbData = 2;
  282. sequence->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  283. sequence->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
  284. sequence->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
  285. sequence->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR;
  286. sequence->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
  287. sequence->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
  288. sequence->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
  289. sequence->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
  290. sequence->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
  291. sequence->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)sequence->dma_buffer->buffer;
  292. sequence->dma_config_timer.NbData = sequence->dma_buffer->size;
  293. sequence->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
  294. sequence->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH;
  295. digital_sequence_alloc_signals(sequence, SEQUENCE_SIGNALS_SIZE);
  296. digital_sequence_alloc_sequence(sequence, size);
  297. return sequence;
  298. }
  299. void digital_sequence_free(DigitalSequence* sequence) {
  300. furi_assert(sequence);
  301. free(sequence->signals);
  302. free(sequence->sequence);
  303. free(sequence->dma_buffer->buffer);
  304. free(sequence->dma_buffer);
  305. free(sequence);
  306. }
  307. void digital_sequence_set_signal(
  308. DigitalSequence* sequence,
  309. uint8_t signal_index,
  310. DigitalSignal* signal) {
  311. furi_assert(sequence);
  312. furi_assert(signal);
  313. furi_assert(signal_index < sequence->signals_size);
  314. sequence->signals[signal_index] = signal;
  315. signal->internals->gpio = sequence->gpio;
  316. signal->internals->reload_reg_remainder = 0;
  317. digital_signal_prepare_arr(signal);
  318. }
  319. void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time) {
  320. furi_assert(sequence);
  321. sequence->send_time = send_time;
  322. sequence->send_time_active = true;
  323. }
  324. void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) {
  325. furi_assert(sequence);
  326. furi_assert(signal_index < sequence->signals_size);
  327. if(sequence->sequence_used >= sequence->sequence_size) {
  328. sequence->sequence_size += SEQUENCE_SIZE_REALLOCATE_INCREMENT;
  329. sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); //-V701
  330. furi_assert(sequence->sequence);
  331. }
  332. sequence->sequence[sequence->sequence_used++] = signal_index;
  333. }
  334. static bool digital_sequence_setup_dma(DigitalSequence* sequence) {
  335. furi_assert(sequence);
  336. digital_signal_stop_dma();
  337. sequence->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)sequence->gpio_buff;
  338. sequence->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (sequence->gpio->port->BSRR);
  339. /* set up DMA channel 1 and 2 for GPIO and timer copy operations */
  340. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &sequence->dma_config_gpio);
  341. LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &sequence->dma_config_timer);
  342. /* enable both DMA channels */
  343. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
  344. LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
  345. return true;
  346. }
  347. static DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) {
  348. furi_assert(sequence);
  349. uint32_t edges = 0;
  350. for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
  351. uint8_t signal_index = sequence->sequence[pos];
  352. DigitalSignal* sig = sequence->signals[signal_index];
  353. edges += sig->edge_cnt;
  354. }
  355. DigitalSignal* ret = digital_signal_alloc(edges);
  356. for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
  357. uint8_t signal_index = sequence->sequence[pos];
  358. DigitalSignal* sig = sequence->signals[signal_index];
  359. digital_signal_append(ret, sig);
  360. }
  361. return ret;
  362. }
  363. static void digital_sequence_update_pos(DigitalSequence* sequence) {
  364. struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
  365. dma_buffer->read_pos = dma_buffer->size - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
  366. }
  367. static const uint32_t wait_ms = 10;
  368. static const uint32_t wait_ticks = wait_ms * 1000 * 64;
  369. static void digital_sequence_finish(DigitalSequence* sequence) {
  370. struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
  371. if(dma_buffer->dma_active) {
  372. uint32_t prev_timer = DWT->CYCCNT;
  373. uint32_t end_pos = (dma_buffer->write_pos + 1) % dma_buffer->size;
  374. do {
  375. uint32_t last_pos = dma_buffer->read_pos;
  376. digital_sequence_update_pos(sequence);
  377. /* we are finished, when the DMA transferred the 0xFFFFFFFF-timer which is the current write_pos */
  378. if(dma_buffer->read_pos == end_pos) {
  379. break;
  380. }
  381. if(last_pos != dma_buffer->read_pos) { //-V547
  382. prev_timer = DWT->CYCCNT;
  383. }
  384. if(DWT->CYCCNT - prev_timer > wait_ticks) {
  385. FURI_LOG_D(
  386. TAG,
  387. "[SEQ] hung %lu ms in finish (ARR 0x%08lx, read %lu, write %lu)",
  388. wait_ms,
  389. TIM2->ARR,
  390. dma_buffer->read_pos,
  391. dma_buffer->write_pos);
  392. break;
  393. }
  394. } while(1);
  395. }
  396. digital_signal_stop_timer();
  397. digital_signal_stop_dma();
  398. }
  399. static void digital_sequence_queue_pulse(DigitalSequence* sequence, uint32_t length) {
  400. struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
  401. if(dma_buffer->dma_active) {
  402. uint32_t prev_timer = DWT->CYCCNT;
  403. uint32_t end_pos = (dma_buffer->write_pos + 1) % dma_buffer->size;
  404. do {
  405. uint32_t last_pos = dma_buffer->read_pos;
  406. digital_sequence_update_pos(sequence);
  407. if(dma_buffer->read_pos != end_pos) {
  408. break;
  409. }
  410. if(last_pos != dma_buffer->read_pos) { //-V547
  411. prev_timer = DWT->CYCCNT;
  412. }
  413. if(DWT->CYCCNT - prev_timer > wait_ticks) {
  414. FURI_LOG_D(
  415. TAG,
  416. "[SEQ] hung %lu ms in queue (ARR 0x%08lx, read %lu, write %lu)",
  417. wait_ms,
  418. TIM2->ARR,
  419. dma_buffer->read_pos,
  420. dma_buffer->write_pos);
  421. break;
  422. }
  423. } while(1);
  424. }
  425. dma_buffer->buffer[dma_buffer->write_pos] = length;
  426. dma_buffer->write_pos = (dma_buffer->write_pos + 1) % dma_buffer->size;
  427. dma_buffer->buffer[dma_buffer->write_pos] = 0xFFFFFFFF;
  428. }
  429. bool digital_sequence_send(DigitalSequence* sequence) {
  430. furi_assert(sequence);
  431. struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
  432. furi_hal_gpio_init(sequence->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
  433. #ifdef DEBUG_OUTPUT
  434. furi_hal_gpio_init(&DEBUG_OUTPUT, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
  435. #endif
  436. if(sequence->bake) {
  437. DigitalSignal* sig = digital_sequence_bake(sequence);
  438. digital_signal_send(sig, sequence->gpio);
  439. digital_signal_free(sig);
  440. return true;
  441. }
  442. int32_t remainder = 0;
  443. bool traded_first = false;
  444. FURI_CRITICAL_ENTER();
  445. dma_buffer->dma_active = false;
  446. dma_buffer->buffer[0] = 0xFFFFFFFF;
  447. dma_buffer->read_pos = 0;
  448. dma_buffer->write_pos = 0;
  449. for(uint32_t seq_pos = 0; seq_pos < sequence->sequence_used; seq_pos++) {
  450. uint8_t signal_index = sequence->sequence[seq_pos];
  451. DigitalSignal* sig = sequence->signals[signal_index];
  452. bool last_signal = ((seq_pos + 1) == sequence->sequence_used);
  453. /* all signals are prepared and we can re-use the GPIO buffer from the fist signal */
  454. if(seq_pos == 0) {
  455. sequence->gpio_buff = sig->internals->gpio_buff;
  456. }
  457. for(uint32_t pulse_pos = 0; pulse_pos < sig->internals->reload_reg_entries; pulse_pos++) {
  458. if(traded_first) {
  459. traded_first = false;
  460. continue;
  461. }
  462. uint32_t pulse_length = 0;
  463. bool last_pulse = ((pulse_pos + 1) == sig->internals->reload_reg_entries);
  464. pulse_length = sig->reload_reg_buff[pulse_pos];
  465. /* when we are too late more than half a tick, make the first edge temporarily longer */
  466. if(remainder >= T_TIM_DIV2) {
  467. remainder -= T_TIM;
  468. pulse_length += 1;
  469. }
  470. remainder += sig->internals->reload_reg_remainder;
  471. /* last pulse in that signal and have a next signal? */
  472. if(last_pulse) {
  473. if((seq_pos + 1) < sequence->sequence_used) {
  474. DigitalSignal* sig_next = sequence->signals[sequence->sequence[seq_pos + 1]];
  475. /* when a signal ends with the same level as the next signal begins, let the fist signal generate the whole pulse */
  476. /* beware, we do not want the level after the last edge, but the last level before that edge */
  477. bool end_level = sig->start_level ^ ((sig->edge_cnt % 2) == 0);
  478. /* take from the next, add it to the current if they have the same level */
  479. if(end_level == sig_next->start_level) {
  480. pulse_length += sig_next->reload_reg_buff[0];
  481. traded_first = true;
  482. }
  483. }
  484. }
  485. digital_sequence_queue_pulse(sequence, pulse_length);
  486. /* start transmission when buffer was filled enough */
  487. bool start_send = sequence->dma_buffer->write_pos >= (sequence->dma_buffer->size - 4);
  488. /* or it was the last pulse */
  489. if(last_pulse && last_signal) {
  490. start_send = true;
  491. }
  492. /* start transmission */
  493. if(start_send && !dma_buffer->dma_active) {
  494. digital_sequence_setup_dma(sequence);
  495. digital_signal_setup_timer();
  496. /* if the send time is specified, wait till the core timer passed beyond that time */
  497. if(sequence->send_time_active) {
  498. sequence->send_time_active = false;
  499. while(sequence->send_time - DWT->CYCCNT < 0x80000000) {
  500. }
  501. }
  502. digital_signal_start_timer();
  503. dma_buffer->dma_active = true;
  504. }
  505. }
  506. }
  507. /* wait until last dma transaction was finished */
  508. digital_sequence_finish(sequence);
  509. FURI_CRITICAL_EXIT();
  510. return true;
  511. }
  512. void digital_sequence_clear(DigitalSequence* sequence) {
  513. furi_assert(sequence);
  514. sequence->sequence_used = 0;
  515. }
  516. void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor) {
  517. for(uint32_t sig_pos = 0; sig_pos < sequence->signals_size; sig_pos++) {
  518. DigitalSignal* signal = sequence->signals[sig_pos];
  519. if(signal) {
  520. signal->internals->factor = (uint32_t)(1024 * 1024 * factor);
  521. digital_signal_prepare_arr(signal);
  522. }
  523. }
  524. }