Skip to content

Commit 1f0730d

Browse files
committed
Refactor in progress. Many items not working.
1 parent 508d20a commit 1f0730d

25 files changed

+523
-656
lines changed

application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ App(
88
"gui",
99
"dialogs",
1010
],
11-
stack_size=4 * 1024,
11+
stack_size=8 * 1024,
1212
order=20,
1313
)

dtmf_dolphin.c

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,12 @@ static void dtmf_dolphin_app_tick_event_callback(void* context) {
1919
furi_assert(context);
2020
DTMFDolphinApp* app = context;
2121

22-
// Needed to handle queueing to ISR and prioritization of audio
23-
if (app->player.playing) {
24-
dtmf_dolphin_player_handle_tick();
25-
} else {
26-
scene_manager_handle_tick_event(app->scene_manager);
27-
}
22+
// dtmf_dolphin_audio_handle_tick();
23+
scene_manager_handle_tick_event(app->scene_manager);
2824
}
2925

3026
static DTMFDolphinApp* app_alloc() {
3127
DTMFDolphinApp* app = malloc(sizeof(DTMFDolphinApp));
32-
app->player.half_samples = 4 * 1024;
33-
app->player.sample_count = 8 * 1024;
34-
app->player.sample_buffer = malloc(sizeof(uint16_t) * app->player.sample_count);
35-
app->player.buffer_buffer = malloc(sizeof(uint8_t) * app->player.sample_count);
36-
app->player.wf1_period = 0;
37-
app->player.wf2_period = 0;
38-
app->player.wf1_freq = 0;
39-
app->player.wf2_freq = 0;
40-
app->player.wf1_pos = 0;
41-
app->player.wf2_pos = 0;
42-
app->player.queue = furi_message_queue_alloc(10, sizeof(DTMFDolphinEvent));
43-
app->player.volume = 2.0f;
44-
app->player.playing = false;
4528

4629
app->gui = furi_record_open(RECORD_GUI);
4730
app->view_dispatcher = view_dispatcher_alloc();
@@ -70,22 +53,6 @@ static DTMFDolphinApp* app_alloc() {
7053
DTMFDolphinViewDialer,
7154
dtmf_dolphin_dialer_get_view(app->dtmf_dolphin_dialer));
7255

73-
app->dtmf_dolphin_bluebox = dtmf_dolphin_bluebox_alloc();
74-
view_dispatcher_add_view(
75-
app->view_dispatcher,
76-
DTMFDolphinViewBluebox,
77-
dtmf_dolphin_bluebox_get_view(app->dtmf_dolphin_bluebox));
78-
79-
app->dtmf_dolphin_play = widget_alloc();
80-
view_dispatcher_add_view(
81-
app->view_dispatcher,
82-
DTMFDolphinViewPlay,
83-
widget_get_view(app->dtmf_dolphin_play));
84-
85-
// app->dialer_button_panel = button_panel_alloc();
86-
// app->bluebox_button_panel = button_panel_alloc();
87-
// app->redbox_button_panel = button_panel_alloc();
88-
8956
app->notification = furi_record_open(RECORD_NOTIFICATION);
9057
notification_message(app->notification, &sequence_display_backlight_enforce_on);
9158

@@ -97,21 +64,15 @@ static DTMFDolphinApp* app_alloc() {
9764
static void app_free(DTMFDolphinApp* app) {
9865
furi_assert(app);
9966
view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewMainMenu);
100-
view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewBluebox);
10167
view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewDialer);
102-
view_dispatcher_remove_view(app->view_dispatcher, DTMFDolphinViewPlay);
10368
variable_item_list_free(app->main_menu_list);
10469

105-
dtmf_dolphin_bluebox_free(app->dtmf_dolphin_bluebox);
10670
dtmf_dolphin_dialer_free(app->dtmf_dolphin_dialer);
107-
widget_free(app->dtmf_dolphin_play);
71+
// widget_free(app->dtmf_dolphin_play);
10872

10973
view_dispatcher_free(app->view_dispatcher);
11074
scene_manager_free(app->scene_manager);
11175

112-
furi_message_queue_free(app->player.queue);
113-
free(app->player.sample_buffer);
114-
11576
// button_panel_free(app->dialer_button_panel);
11677
// button_panel_free(app->bluebox_button_panel);
11778
// button_panel_free(app->redbox_button_panel);
@@ -126,8 +87,6 @@ static void app_free(DTMFDolphinApp* app) {
12687
int32_t dtmf_dolphin_app(void *p) {
12788
UNUSED(p);
12889
DTMFDolphinApp* app = app_alloc();
129-
130-
dtmf_dolphin_player_init(&(app->player));
13190

13291
view_dispatcher_run(app->view_dispatcher);
13392

dtmf_dolphin_audio.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#include "dtmf_dolphin_audio.h"
2+
3+
DTMFDolphinAudio *current_player;
4+
5+
static void dtmf_dolphin_audio_dma_isr(void* ctx) {
6+
FuriMessageQueue *event_queue = ctx;
7+
8+
if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
9+
LL_DMA_ClearFlag_HT1(DMA1);
10+
11+
DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer};
12+
furi_message_queue_put(event_queue, &event, 0);
13+
}
14+
15+
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
16+
LL_DMA_ClearFlag_TC1(DMA1);
17+
18+
DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAFullTransfer};
19+
furi_message_queue_put(event_queue, &event, 0);
20+
}
21+
}
22+
23+
void dtmf_dolphin_audio_clear_samples(DTMFDolphinAudio* player) {
24+
for (size_t i = 0; i < player->buffer_length; i++) {
25+
player->sample_buffer[i] = 0;
26+
}
27+
}
28+
29+
DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
30+
DTMFDolphinOsc *osc = { 0 };
31+
osc->cached_freq = 0;
32+
osc->offset = 0;
33+
osc->period = 0;
34+
return osc;
35+
}
36+
37+
DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
38+
DTMFDolphinAudio player;
39+
player.buffer_length = SAMPLE_BUFFER_LENGTH;
40+
player.half_buffer_length = SAMPLE_BUFFER_LENGTH / 2;
41+
player.buffer_buffer = malloc(sizeof(uint8_t) * player.buffer_length);
42+
player.sample_buffer = malloc(sizeof(uint16_t) * player.buffer_length);
43+
player.osc1 = dtmf_dolphin_osc_alloc();
44+
player.osc2 = dtmf_dolphin_osc_alloc();
45+
player.playing = false;
46+
player.volume = 2.0f;
47+
player.queue = furi_message_queue_alloc(10, sizeof(DTMFDolphinCustomEvent));
48+
dtmf_dolphin_audio_clear_samples(&player);
49+
50+
return false;
51+
}
52+
53+
size_t calc_waveform_period(float freq) {
54+
if (!freq) {
55+
return 0;
56+
}
57+
// DMA Rate constant, thanks to Dr_Zlo
58+
float dma_rate = CPU_CLOCK_FREQ \
59+
/ 2 \
60+
/ DTMF_DOLPHIN_HAL_DMA_PRESCALER \
61+
/ (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
62+
63+
return (uint16_t) (dma_rate / freq);
64+
}
65+
66+
float sample_frame(DTMFDolphinOsc* osc, float freq) {
67+
float frame = 0.0;
68+
69+
if (freq != osc->cached_freq || !osc->period) {
70+
osc->cached_freq = freq;
71+
osc->period = calc_waveform_period(freq);
72+
osc->offset = 0;
73+
}
74+
if (osc->period) {
75+
frame = tanhf(sin(osc->offset * PERIOD_2_PI / osc->period) + 1);
76+
osc->offset = (osc->offset + 1) % osc->period;
77+
}
78+
79+
return frame;
80+
}
81+
82+
void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) {
83+
furi_message_queue_free(player->queue);
84+
dtmf_dolphin_osc_free(player->osc1);
85+
dtmf_dolphin_osc_free(player->osc2);
86+
free(player->buffer_buffer);
87+
free(player->sample_buffer);
88+
}
89+
90+
void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) {
91+
UNUSED(osc);
92+
// Nothing to free now, but keeping this here in case I reimplement caching
93+
}
94+
95+
bool generate_waveform(DTMFDolphinAudio* player, float freq1, float freq2, uint16_t buffer_index) {
96+
uint16_t* sample_buffer_start = &player->sample_buffer[buffer_index];
97+
98+
for (size_t i = 0; i < player->half_buffer_length; i++) {
99+
float data = (sample_frame(player->osc1, freq1) / 2) + (sample_frame(player->osc2, freq2) / 2);
100+
data *= player->volume;
101+
data *= UINT8_MAX / 2; // scale -128..127
102+
data += UINT8_MAX / 2; // to unsigned
103+
104+
if(data < 0) {
105+
data = 0;
106+
}
107+
108+
if(data > 255) {
109+
data = 255;
110+
}
111+
112+
player->buffer_buffer[i] = data;
113+
sample_buffer_start[i] = data;
114+
}
115+
116+
return true;
117+
}
118+
119+
bool dtmf_dolphin_audio_play_tones(float freq1, float freq2) {
120+
current_player = dtmf_dolphin_audio_alloc();
121+
122+
generate_waveform(current_player, freq1, freq2, 0);
123+
generate_waveform(current_player, freq1, freq2, current_player->half_buffer_length);
124+
125+
dtmf_dolphin_speaker_init();
126+
dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length);
127+
128+
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
129+
130+
dtmf_dolphin_dma_start();
131+
dtmf_dolphin_speaker_start();
132+
133+
return true;
134+
}
135+
136+
bool dtmf_dolphin_audio_stop_tones() {
137+
current_player->playing = false;
138+
139+
dtmf_dolphin_speaker_stop();
140+
dtmf_dolphin_dma_stop();
141+
142+
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
143+
144+
dtmf_dolphin_audio_free(current_player);
145+
146+
return true;
147+
}
148+
149+
bool dtmf_dolphin_audio_handle_tick() {
150+
DTMFDolphinCustomEvent event;
151+
152+
if(furi_message_queue_get(current_player->queue, &event, FuriWaitForever) == FuriStatusOk) {
153+
if(event.type == DTMFDolphinEventDMAHalfTransfer) {
154+
generate_waveform(
155+
current_player,
156+
(double) current_player->osc1->cached_freq,
157+
(double) current_player->osc2->cached_freq,
158+
0);
159+
return true;
160+
} else if (event.type == DTMFDolphinEventDMAFullTransfer) {
161+
generate_waveform(
162+
current_player,
163+
(double) current_player->osc1->cached_freq,
164+
(double) current_player->osc2->cached_freq,
165+
current_player->half_buffer_length);
166+
return true;
167+
}
168+
}
169+
return false;
170+
}

dtmf_dolphin_audio.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
// #include "dtmf_dolphin_i.h"
3+
#include "dtmf_dolphin_event.h"
4+
#include "dtmf_dolphin_hal.h"
5+
6+
#define SAMPLE_BUFFER_LENGTH 8192
7+
#define PERIOD_2_PI 6.2832
8+
#define CPU_CLOCK_FREQ 64000000
9+
10+
typedef struct {
11+
float cached_freq;
12+
size_t period;
13+
size_t buffer_length;
14+
float* sample_buffer;
15+
uint16_t offset;
16+
} DTMFDolphinOsc;
17+
18+
typedef struct {
19+
size_t buffer_length;
20+
size_t half_buffer_length;
21+
uint8_t *buffer_buffer;
22+
uint16_t *sample_buffer;
23+
float volume;
24+
bool playing;
25+
FuriMessageQueue *queue;
26+
DTMFDolphinOsc *osc1;
27+
DTMFDolphinOsc *osc2;
28+
} DTMFDolphinAudio;
29+
30+
DTMFDolphinOsc* dtmf_dolphin_osc_alloc();
31+
32+
DTMFDolphinAudio* dtmf_dolphin_audio_alloc();
33+
34+
void dtmf_dolphin_audio_free(DTMFDolphinAudio* player);
35+
36+
void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc);
37+
38+
bool dtmf_dolphin_audio_play_tones(float freq1, float freq2);
39+
40+
bool dtmf_dolphin_audio_stop_tones();
41+
42+
bool dtmf_dolphin_audio_handle_tick();

0 commit comments

Comments
 (0)