flizzer_tracker_hal.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include "flizzer_tracker_hal.h"
  2. #include "flizzer_tracker.h"
  3. void sound_engine_dma_isr(void* ctx)
  4. {
  5. SoundEngine* sound_engine = (SoundEngine*)ctx;
  6. // half of transfer
  7. if(LL_DMA_IsActiveFlag_HT1(DMA1))
  8. {
  9. LL_DMA_ClearFlag_HT1(DMA1);
  10. // fill first half of buffer
  11. uint16_t* audio_buffer = sound_engine->audio_buffer;
  12. uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
  13. sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
  14. }
  15. // transfer complete
  16. if(LL_DMA_IsActiveFlag_TC1(DMA1))
  17. {
  18. LL_DMA_ClearFlag_TC1(DMA1);
  19. // fill second half of buffer
  20. uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
  21. uint16_t* audio_buffer = &sound_engine->audio_buffer[audio_buffer_length];
  22. sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
  23. }
  24. }
  25. void tracker_engine_timer_isr(void* ctx)
  26. {
  27. if(LL_TIM_IsActiveFlag_UPDATE(TIM1))
  28. {
  29. LL_TIM_ClearFlag_UPDATE(TIM1);
  30. }
  31. TrackerEngine* tracker_engine = (TrackerEngine*)ctx;
  32. tracker_engine_advance_tick(tracker_engine);
  33. }
  34. void sound_engine_PWM_timer_init(bool external_audio_output) //external audio on pin PA6
  35. {
  36. LL_TIM_InitTypeDef TIM_InitStruct = {0};
  37. LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
  38. TIM_InitStruct.Prescaler = 0;
  39. TIM_InitStruct.Autoreload = 1023; //10-bit PWM resolution at around 60 kHz PWM rate
  40. TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  41. LL_TIM_Init(SPEAKER_PWM_TIMER, &TIM_InitStruct);
  42. TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
  43. TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
  44. TIM_OC_InitStruct.CompareValue = 0;
  45. LL_TIM_OC_Init(SPEAKER_PWM_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
  46. if(external_audio_output)
  47. {
  48. furi_hal_gpio_init_ex(&gpio_ext_pa6, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
  49. }
  50. else
  51. {
  52. bool unu = furi_hal_speaker_acquire(1000);
  53. UNUSED(unu);
  54. }
  55. }
  56. void sound_engine_timer_init(uint32_t sample_rate) //external audio on pin PA6
  57. {
  58. LL_TIM_InitTypeDef TIM_InitStruct = {0};
  59. LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
  60. TIM_InitStruct.Prescaler = 0;
  61. TIM_InitStruct.Autoreload = TIMER_BASE_CLOCK / sample_rate; //to support various sample rates
  62. TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  63. LL_TIM_Init(SAMPLE_RATE_TIMER, &TIM_InitStruct);
  64. TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
  65. TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
  66. LL_TIM_OC_Init(SAMPLE_RATE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
  67. }
  68. void tracker_engine_timer_init(uint8_t rate) //0-255 hz
  69. {
  70. LL_TIM_InitTypeDef TIM_InitStruct = {0};
  71. LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
  72. TIM_InitStruct.Prescaler = 976 - 1; //so with highest autoreload you get 1 Hz
  73. TIM_InitStruct.Autoreload = (TIMER_BASE_CLOCK / 976) / rate; //to support various rates
  74. TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  75. LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
  76. TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
  77. TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
  78. LL_TIM_OC_Init(TRACKER_ENGINE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
  79. LL_TIM_EnableIT_UPDATE(TRACKER_ENGINE_TIMER);
  80. }
  81. void tracker_engine_init_hardware(uint8_t rate)
  82. {
  83. tracker_engine_timer_init(rate);
  84. }
  85. void sound_engine_dma_init(uint32_t address, uint32_t size)
  86. {
  87. uint32_t dma_dst = (uint32_t) & (SPEAKER_PWM_TIMER->CCR1);
  88. LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
  89. LL_DMA_SetDataLength(DMA_INSTANCE, size);
  90. LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM2_UP);
  91. LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
  92. LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH);
  93. LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR);
  94. LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT);
  95. LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT);
  96. LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD);
  97. LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD);
  98. LL_DMA_EnableIT_TC(DMA_INSTANCE);
  99. LL_DMA_EnableIT_HT(DMA_INSTANCE);
  100. }
  101. void sound_engine_init_hardware(uint32_t sample_rate, bool external_audio_output, uint16_t* audio_buffer, uint32_t audio_buffer_size)
  102. {
  103. sound_engine_dma_init((uint32_t)audio_buffer, audio_buffer_size);
  104. sound_engine_timer_init(sample_rate);
  105. sound_engine_PWM_timer_init(external_audio_output);
  106. }
  107. void sound_engine_dma_start()
  108. {
  109. LL_DMA_EnableChannel(DMA_INSTANCE);
  110. LL_TIM_EnableDMAReq_UPDATE(SAMPLE_RATE_TIMER);
  111. }
  112. void sound_engine_dma_stop()
  113. {
  114. LL_DMA_DisableChannel(DMA_INSTANCE);
  115. }
  116. void sound_engine_start()
  117. {
  118. LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER);
  119. LL_TIM_EnableCounter(SAMPLE_RATE_TIMER);
  120. LL_TIM_EnableAllOutputs(SPEAKER_PWM_TIMER);
  121. LL_TIM_EnableCounter(SPEAKER_PWM_TIMER);
  122. sound_engine_dma_start();
  123. }
  124. void sound_engine_stop()
  125. {
  126. LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER);
  127. LL_TIM_DisableCounter(SAMPLE_RATE_TIMER);
  128. LL_TIM_DisableAllOutputs(SPEAKER_PWM_TIMER);
  129. LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
  130. sound_engine_dma_stop();
  131. }
  132. void tracker_engine_start()
  133. {
  134. LL_TIM_EnableAllOutputs(TRACKER_ENGINE_TIMER);
  135. LL_TIM_EnableCounter(TRACKER_ENGINE_TIMER);
  136. }
  137. void tracker_engine_stop()
  138. {
  139. LL_TIM_DisableAllOutputs(TRACKER_ENGINE_TIMER);
  140. LL_TIM_DisableCounter(TRACKER_ENGINE_TIMER);
  141. }
  142. void play()
  143. {
  144. tracker_engine_start();
  145. sound_engine_start();
  146. }
  147. void stop()
  148. {
  149. sound_engine_stop();
  150. tracker_engine_stop();
  151. }