dtmf_dolphin_player.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "dtmf_dolphin_player.h"
  2. #define DTMF_DOLPHIN_SAMPLE_RATE (8000)
  3. typedef struct {
  4. DTMFDolphinEvent type;
  5. } DTMFDolphinPlayerEvent;
  6. // Keep this here for accessibility in local scope event without context
  7. DTMFDolphinPlayer* player;
  8. void dtmf_dolphin_dma_isr(void* ctx) {
  9. FuriMessageQueue *event_queue = ctx;
  10. if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
  11. LL_DMA_ClearFlag_HT1(DMA1);
  12. DTMFDolphinPlayerEvent event = {.type = DTMFDolphinPlayerEventHalfTransfer};
  13. furi_message_queue_put(event_queue, &event, 0);
  14. }
  15. if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
  16. LL_DMA_ClearFlag_TC1(DMA1);
  17. DTMFDolphinPlayerEvent event = {.type = DTMFDolphinPlayerEventFullTransfer};
  18. furi_message_queue_put(event_queue, &event, 0);
  19. }
  20. }
  21. bool dtmf_dolphin_player_init(void* context) {
  22. player = context;
  23. return false;
  24. }
  25. void dtmf_dolphin_player_clear_samples() {
  26. for (size_t i = 0; i < player->sample_count; i++) {
  27. player->sample_buffer[i] = 0;
  28. }
  29. }
  30. bool dtmf_dolphin_player_generate_waveform(size_t index) {
  31. uint16_t* sample_buffer_start = &player->sample_buffer[index];
  32. if (!player->wf1_freq)
  33. return false;
  34. // Generate basic sine wave sample to fill sample_count
  35. for (size_t i = 0; i < player->half_samples; i++) {
  36. // float data = sin(i * PERIOD_2_PI / player->wf1_period) + 1;
  37. float data = sin(player->wf1_pos * PERIOD_2_PI / player->wf1_period) + 1;
  38. player->wf1_pos = (player->wf1_pos + 1) % player->wf1_period;
  39. data *= player->volume;
  40. // Downmix second tone with the first
  41. if (player->wf2_freq) {
  42. data /= 2;
  43. float data_2 = sin(player->wf2_pos * PERIOD_2_PI / player->wf2_period) + 1;
  44. player->wf2_pos = (player->wf2_pos + 1) % player->wf2_period;
  45. data_2 *= player->volume / 2;
  46. data += data_2;
  47. }
  48. data = tanhf(data);
  49. data *= UINT8_MAX / 2; // scale -128..127
  50. data += UINT8_MAX / 2; // to unsigned
  51. if(data < 0) {
  52. data = 0;
  53. }
  54. if(data > 255) {
  55. data = 255;
  56. }
  57. player->buffer_buffer[i] = data;
  58. sample_buffer_start[i] = data;
  59. }
  60. return true;
  61. }
  62. bool dtmf_dolphin_player_play_tones(float *freq) {
  63. player->wf1_pos = 0;
  64. player->wf2_pos = 0;
  65. player->wf1_freq = 0;
  66. player->wf2_freq = 0;
  67. player->wf1_period = 0;
  68. player->wf2_period = 0;
  69. if (freq[0]) {
  70. player->wf1_freq = freq[0];
  71. player->wf1_period = player->sample_count / freq[0] * 4;
  72. }
  73. if (freq[1]) {
  74. player->wf2_freq = freq[1];
  75. player->wf2_period = player->sample_count / freq[1] * 4;
  76. }
  77. dtmf_dolphin_player_clear_samples();
  78. dtmf_dolphin_player_generate_waveform(0);
  79. dtmf_dolphin_player_generate_waveform(player->half_samples);
  80. dtmf_dolphin_speaker_init();
  81. dtmf_dolphin_dma_init((uint32_t)player->sample_buffer, player->sample_count);
  82. furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_dma_isr, player->queue);
  83. dtmf_dolphin_dma_start();
  84. dtmf_dolphin_speaker_start();
  85. player->playing = true;
  86. return true;
  87. }
  88. bool dtmf_dolphin_player_stop_tones() {
  89. player->playing = false;
  90. dtmf_dolphin_speaker_stop();
  91. dtmf_dolphin_dma_stop();
  92. furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
  93. return true;
  94. }
  95. bool dtmf_dolphin_player_handle_tick() {
  96. DTMFDolphinPlayerEvent event;
  97. if(furi_message_queue_get(player->queue, &event, FuriWaitForever) == FuriStatusOk) {
  98. if (player->playing) {
  99. if(event.type == DTMFDolphinPlayerEventHalfTransfer) {
  100. dtmf_dolphin_player_generate_waveform(0);
  101. // uint16_t* sample_buffer_start = &player->sample_buffer[0];
  102. // for (size_t i = 0; i < player->half_samples; i++) {
  103. // sample_buffer_start[i] = player->buffer_buffer[i];
  104. // }
  105. return true;
  106. } else if (event.type == DTMFDolphinPlayerEventFullTransfer) {
  107. dtmf_dolphin_player_generate_waveform(player->half_samples);
  108. // uint16_t* sample_buffer_start = &player->sample_buffer[player->half_samples];
  109. // for (size_t i = 0; i < player->half_samples; i++) {
  110. // sample_buffer_start[i] = player->buffer_buffer[i];
  111. // }
  112. return true;
  113. }
  114. } else {
  115. return true;
  116. }
  117. }
  118. return false;
  119. }