| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- #include "dtmf_dolphin_player.h"
- #define DTMF_DOLPHIN_SAMPLE_RATE (8000)
- typedef struct {
- DTMFDolphinEvent type;
- } DTMFDolphinPlayerEvent;
- // Keep this here for accessibility in local scope event without context
- DTMFDolphinPlayer* player;
- void dtmf_dolphin_dma_isr(void* ctx) {
- FuriMessageQueue *event_queue = ctx;
- if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
- LL_DMA_ClearFlag_HT1(DMA1);
- DTMFDolphinPlayerEvent event = {.type = DTMFDolphinPlayerEventHalfTransfer};
- furi_message_queue_put(event_queue, &event, 0);
- }
- if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
- LL_DMA_ClearFlag_TC1(DMA1);
- DTMFDolphinPlayerEvent event = {.type = DTMFDolphinPlayerEventFullTransfer};
- furi_message_queue_put(event_queue, &event, 0);
- }
- }
- bool dtmf_dolphin_player_init(void* context) {
- player = context;
- return false;
- }
- void dtmf_dolphin_player_clear_samples() {
- for (size_t i = 0; i < player->sample_count; i++) {
- player->sample_buffer[i] = 0;
- }
- }
- bool dtmf_dolphin_player_generate_waveform(size_t index) {
- uint16_t* sample_buffer_start = &player->sample_buffer[index];
- if (!player->wf1_freq)
- return false;
- // Generate basic sine wave sample to fill sample_count
- for (size_t i = 0; i < player->half_samples; i++) {
- // float data = sin(i * PERIOD_2_PI / player->wf1_period) + 1;
- float data = sin(player->wf1_pos * PERIOD_2_PI / player->wf1_period) + 1;
- player->wf1_pos = (player->wf1_pos + 1) % player->wf1_period;
- data *= player->volume;
- // Downmix second tone with the first
- if (player->wf2_freq) {
- data /= 2;
- float data_2 = sin(player->wf2_pos * PERIOD_2_PI / player->wf2_period) + 1;
- player->wf2_pos = (player->wf2_pos + 1) % player->wf2_period;
- data_2 *= player->volume / 2;
- data += data_2;
- }
- data = tanhf(data);
- data *= UINT8_MAX / 2; // scale -128..127
- data += UINT8_MAX / 2; // to unsigned
- if(data < 0) {
- data = 0;
- }
- if(data > 255) {
- data = 255;
- }
- player->buffer_buffer[i] = data;
- sample_buffer_start[i] = data;
- }
- return true;
- }
- bool dtmf_dolphin_player_play_tones(float *freq) {
- player->wf1_pos = 0;
- player->wf2_pos = 0;
- player->wf1_freq = 0;
- player->wf2_freq = 0;
- player->wf1_period = 0;
- player->wf2_period = 0;
- if (freq[0]) {
- player->wf1_freq = freq[0];
- player->wf1_period = player->sample_count / freq[0] * 4;
- }
- if (freq[1]) {
- player->wf2_freq = freq[1];
- player->wf2_period = player->sample_count / freq[1] * 4;
- }
- dtmf_dolphin_player_clear_samples();
- dtmf_dolphin_player_generate_waveform(0);
- dtmf_dolphin_player_generate_waveform(player->half_samples);
- dtmf_dolphin_speaker_init();
- dtmf_dolphin_dma_init((uint32_t)player->sample_buffer, player->sample_count);
- furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_dma_isr, player->queue);
- dtmf_dolphin_dma_start();
- dtmf_dolphin_speaker_start();
- player->playing = true;
- return true;
- }
- bool dtmf_dolphin_player_stop_tones() {
- player->playing = false;
- dtmf_dolphin_speaker_stop();
- dtmf_dolphin_dma_stop();
- furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
-
- return true;
- }
- bool dtmf_dolphin_player_handle_tick() {
- DTMFDolphinPlayerEvent event;
- if(furi_message_queue_get(player->queue, &event, FuriWaitForever) == FuriStatusOk) {
- if (player->playing) {
- if(event.type == DTMFDolphinPlayerEventHalfTransfer) {
- dtmf_dolphin_player_generate_waveform(0);
- // uint16_t* sample_buffer_start = &player->sample_buffer[0];
- // for (size_t i = 0; i < player->half_samples; i++) {
- // sample_buffer_start[i] = player->buffer_buffer[i];
- // }
- return true;
- } else if (event.type == DTMFDolphinPlayerEventFullTransfer) {
- dtmf_dolphin_player_generate_waveform(player->half_samples);
- // uint16_t* sample_buffer_start = &player->sample_buffer[player->half_samples];
- // for (size_t i = 0; i < player->half_samples; i++) {
- // sample_buffer_start[i] = player->buffer_buffer[i];
- // }
- return true;
- }
- } else {
- return true;
- }
- }
- return false;
- }
|