dtmf update

This commit is contained in:
RogueMaster
2022-11-17 23:47:07 -05:00
parent fa78b04b41
commit 579d9d188d
14 changed files with 224 additions and 212 deletions

View File

@@ -1,7 +1,4 @@
![Image](assets/dialer.jpg)
![Image](pics/dialer.jpg)
[Original Link](https://github.com/litui/dtmf_dolphin)
## DTMF Dolphin ## DTMF Dolphin

View File

@@ -1,5 +1,5 @@
App( App(
appid="DTMF_Dolphin", appid="dtmf_dolphin",
name="DTMF Dolphin", name="DTMF Dolphin",
apptype=FlipperAppType.EXTERNAL, apptype=FlipperAppType.EXTERNAL,
entry_point="dtmf_dolphin_app", entry_point="dtmf_dolphin_app",

View File

@@ -78,7 +78,7 @@ static void app_free(DTMFDolphinApp* app) {
free(app); free(app);
} }
int32_t dtmf_dolphin_app(void* p) { int32_t dtmf_dolphin_app(void *p) {
UNUSED(p); UNUSED(p);
DTMFDolphinApp* app = app_alloc(); DTMFDolphinApp* app = app_alloc();

View File

@@ -1,11 +1,11 @@
#include "dtmf_dolphin_audio.h" #include "dtmf_dolphin_audio.h"
DTMFDolphinAudio* current_player; DTMFDolphinAudio *current_player;
static void dtmf_dolphin_audio_dma_isr(void* ctx) { static void dtmf_dolphin_audio_dma_isr(void* ctx) {
FuriMessageQueue* event_queue = ctx; FuriMessageQueue *event_queue = ctx;
if(LL_DMA_IsActiveFlag_HT1(DMA1)) { if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
LL_DMA_ClearFlag_HT1(DMA1); LL_DMA_ClearFlag_HT1(DMA1);
DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer}; DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer};
@@ -21,13 +21,13 @@ static void dtmf_dolphin_audio_dma_isr(void* ctx) {
} }
void dtmf_dolphin_audio_clear_samples(DTMFDolphinAudio* player) { void dtmf_dolphin_audio_clear_samples(DTMFDolphinAudio* player) {
for(size_t i = 0; i < player->buffer_length; i++) { for (size_t i = 0; i < player->buffer_length; i++) {
player->sample_buffer[i] = 0; player->sample_buffer[i] = 0;
} }
} }
DTMFDolphinOsc* dtmf_dolphin_osc_alloc() { DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
DTMFDolphinOsc* osc = malloc(sizeof(DTMFDolphinOsc)); DTMFDolphinOsc *osc = malloc(sizeof(DTMFDolphinOsc));
osc->cached_freq = 0; osc->cached_freq = 0;
osc->offset = 0; osc->offset = 0;
osc->period = 0; osc->period = 0;
@@ -36,7 +36,7 @@ DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
} }
DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() { DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() {
DTMFDolphinPulseFilter* pf = malloc(sizeof(DTMFDolphinPulseFilter)); DTMFDolphinPulseFilter *pf = malloc(sizeof(DTMFDolphinPulseFilter));
pf->duration = 0; pf->duration = 0;
pf->period = 0; pf->period = 0;
pf->offset = 0; pf->offset = 0;
@@ -45,7 +45,7 @@ DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() {
} }
DTMFDolphinAudio* dtmf_dolphin_audio_alloc() { DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
DTMFDolphinAudio* player = malloc(sizeof(DTMFDolphinAudio)); DTMFDolphinAudio *player = malloc(sizeof(DTMFDolphinAudio));
player->buffer_length = SAMPLE_BUFFER_LENGTH; player->buffer_length = SAMPLE_BUFFER_LENGTH;
player->half_buffer_length = SAMPLE_BUFFER_LENGTH / 2; player->half_buffer_length = SAMPLE_BUFFER_LENGTH / 2;
player->sample_buffer = malloc(sizeof(uint16_t) * player->buffer_length); player->sample_buffer = malloc(sizeof(uint16_t) * player->buffer_length);
@@ -61,58 +61,56 @@ DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
} }
size_t calc_waveform_period(float freq) { size_t calc_waveform_period(float freq) {
if(!freq) { if (!freq) {
return 0; return 0;
} }
// DMA Rate calculation, thanks to Dr_Zlo // DMA Rate calculation, thanks to Dr_Zlo
float dma_rate = CPU_CLOCK_FREQ / 2 / DTMF_DOLPHIN_HAL_DMA_PRESCALER / float dma_rate = CPU_CLOCK_FREQ \
(DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1); / 2 \
/ DTMF_DOLPHIN_HAL_DMA_PRESCALER \
/ (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
// Using a constant scaling modifier, which likely represents // Using a constant scaling modifier, which likely represents
// the combined system overhead and isr latency. // the combined system overhead and isr latency.
return (uint16_t)dma_rate * 2 / freq * 0.801923; return (uint16_t) dma_rate * 2 / freq * 0.801923;
} }
void osc_generate_lookup_table(DTMFDolphinOsc* osc, float freq) { void osc_generate_lookup_table(DTMFDolphinOsc* osc, float freq) {
if(osc->lookup_table != NULL) { if (osc->lookup_table != NULL) {
free(osc->lookup_table); free(osc->lookup_table);
} }
osc->offset = 0; osc->offset = 0;
osc->cached_freq = freq; osc->cached_freq = freq;
osc->period = calc_waveform_period(freq); osc->period = calc_waveform_period(freq);
if(!osc->period) { if (!osc->period) {
osc->lookup_table = NULL; osc->lookup_table = NULL;
return; return;
} }
osc->lookup_table = malloc(sizeof(float) * osc->period); osc->lookup_table = malloc(sizeof(float) * osc->period);
for(size_t i = 0; i < osc->period; i++) { for (size_t i = 0; i < osc->period; i++) {
osc->lookup_table[i] = sin(i * PERIOD_2_PI / osc->period) + 1; osc->lookup_table[i] = sin(i * PERIOD_2_PI / osc->period) + 1;
} }
} }
void filter_generate_lookup_table( void filter_generate_lookup_table(DTMFDolphinPulseFilter* pf, uint16_t pulses, uint16_t pulse_ms, uint16_t gap_ms) {
DTMFDolphinPulseFilter* pf, if (pf->lookup_table != NULL) {
uint16_t pulses,
uint16_t pulse_ms,
uint16_t gap_ms) {
if(pf->lookup_table != NULL) {
free(pf->lookup_table); free(pf->lookup_table);
} }
pf->offset = 0; pf->offset = 0;
uint16_t gap_period = calc_waveform_period(1000 / (float)gap_ms); uint16_t gap_period = calc_waveform_period(1000 / (float) gap_ms);
uint16_t pulse_period = calc_waveform_period(1000 / (float)pulse_ms); uint16_t pulse_period = calc_waveform_period(1000 / (float) pulse_ms);
pf->period = pulse_period + gap_period; pf->period = pulse_period + gap_period;
if(!pf->period) { if (!pf->period) {
pf->lookup_table = NULL; pf->lookup_table = NULL;
return; return;
} }
pf->duration = pf->period * pulses; pf->duration = pf->period * pulses;
pf->lookup_table = malloc(sizeof(bool) * pf->duration); pf->lookup_table = malloc(sizeof(bool) * pf->duration);
for(size_t i = 0; i < pf->duration; i++) { for (size_t i = 0; i < pf->duration; i++) {
pf->lookup_table[i] = i % pf->period < pulse_period; pf->lookup_table[i] = i % pf->period < pulse_period;
} }
} }
@@ -120,7 +118,7 @@ void filter_generate_lookup_table(
float sample_frame(DTMFDolphinOsc* osc) { float sample_frame(DTMFDolphinOsc* osc) {
float frame = 0.0; float frame = 0.0;
if(osc->period) { if (osc->period) {
frame = osc->lookup_table[osc->offset]; frame = osc->lookup_table[osc->offset];
osc->offset = (osc->offset + 1) % osc->period; osc->offset = (osc->offset + 1) % osc->period;
} }
@@ -131,8 +129,8 @@ float sample_frame(DTMFDolphinOsc* osc) {
bool sample_filter(DTMFDolphinPulseFilter* pf) { bool sample_filter(DTMFDolphinPulseFilter* pf) {
bool frame = true; bool frame = true;
if(pf->duration) { if (pf->duration) {
if(pf->offset < pf->duration) { if (pf->offset < pf->duration) {
frame = pf->lookup_table[pf->offset]; frame = pf->lookup_table[pf->offset];
pf->offset = pf->offset + 1; pf->offset = pf->offset + 1;
} else { } else {
@@ -144,14 +142,14 @@ bool sample_filter(DTMFDolphinPulseFilter* pf) {
} }
void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) { void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) {
if(osc->lookup_table != NULL) { if (osc->lookup_table != NULL) {
free(osc->lookup_table); free(osc->lookup_table);
} }
free(osc); free(osc);
} }
void dtmf_dolphin_filter_free(DTMFDolphinPulseFilter* pf) { void dtmf_dolphin_filter_free(DTMFDolphinPulseFilter* pf) {
if(pf->lookup_table != NULL) { if (pf->lookup_table != NULL) {
free(pf->lookup_table); free(pf->lookup_table);
} }
free(pf); free(pf);
@@ -167,19 +165,22 @@ void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) {
current_player = NULL; current_player = NULL;
} }
bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) { bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) {
uint16_t* sample_buffer_start = &player->sample_buffer[buffer_index]; uint16_t* sample_buffer_start = &player->sample_buffer[buffer_index];
for(size_t i = 0; i < player->half_buffer_length; i++) { for (size_t i = 0; i < player->half_buffer_length; i++) {
float data = 0; float data = 0;
if(player->osc2->period) { if (player->osc2->period) {
data = (sample_frame(player->osc1) / 2) + (sample_frame(player->osc2) / 2); data = \
(sample_frame(player->osc1) / 2) + \
(sample_frame(player->osc2) / 2);
} else { } else {
data = (sample_frame(player->osc1)); data = (sample_frame(player->osc1));
} }
data *= sample_filter(player->filter) ? player->volume : 0.0; data *= sample_filter(player->filter) ? player->volume : 0.0;
data *= UINT8_MAX / 2; // scale -128..127 data *= UINT8_MAX / 2; // scale -128..127
data += UINT8_MAX / 2; // to unsigned data += UINT8_MAX / 2; // to unsigned
if(data < 0) { if(data < 0) {
data = 0; data = 0;
@@ -195,13 +196,8 @@ bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) {
return true; return true;
} }
bool dtmf_dolphin_audio_play_tones( bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, uint16_t pulse_ms, uint16_t gap_ms) {
float freq1, if (current_player != NULL && current_player->playing) {
float freq2,
uint16_t pulses,
uint16_t pulse_ms,
uint16_t gap_ms) {
if(current_player != NULL && current_player->playing) {
// Cannot start playing while still playing something else // Cannot start playing while still playing something else
return false; return false;
} }
@@ -217,8 +213,7 @@ bool dtmf_dolphin_audio_play_tones(
dtmf_dolphin_speaker_init(); dtmf_dolphin_speaker_init();
dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length); dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length);
furi_hal_interrupt_set_isr( furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
dtmf_dolphin_dma_start(); dtmf_dolphin_dma_start();
dtmf_dolphin_speaker_start(); dtmf_dolphin_speaker_start();
@@ -227,12 +222,11 @@ bool dtmf_dolphin_audio_play_tones(
} }
bool dtmf_dolphin_audio_stop_tones() { bool dtmf_dolphin_audio_stop_tones() {
if(current_player != NULL && !current_player->playing) { if (current_player != NULL && !current_player->playing) {
// Can't stop a player that isn't playing. // Can't stop a player that isn't playing.
return false; return false;
} }
while(current_player->filter->offset > 0 && while(current_player->filter->offset > 0 && current_player->filter->offset < current_player->filter->duration) {
current_player->filter->offset < current_player->filter->duration) {
// run remaining ticks if needed to complete filter sequence // run remaining ticks if needed to complete filter sequence
dtmf_dolphin_audio_handle_tick(); dtmf_dolphin_audio_handle_tick();
} }
@@ -249,13 +243,13 @@ bool dtmf_dolphin_audio_stop_tones() {
bool dtmf_dolphin_audio_handle_tick() { bool dtmf_dolphin_audio_handle_tick() {
bool handled = false; bool handled = false;
if(current_player) { if (current_player) {
DTMFDolphinCustomEvent event; DTMFDolphinCustomEvent event;
if(furi_message_queue_get(current_player->queue, &event, 250) == FuriStatusOk) { if(furi_message_queue_get(current_player->queue, &event, 250) == FuriStatusOk) {
if(event.type == DTMFDolphinEventDMAHalfTransfer) { if(event.type == DTMFDolphinEventDMAHalfTransfer) {
generate_waveform(current_player, 0); generate_waveform(current_player, 0);
handled = true; handled = true;
} else if(event.type == DTMFDolphinEventDMAFullTransfer) { } else if (event.type == DTMFDolphinEventDMAFullTransfer) {
generate_waveform(current_player, current_player->half_buffer_length); generate_waveform(current_player, current_player->half_buffer_length);
handled = true; handled = true;
} }

View File

@@ -24,13 +24,13 @@ typedef struct {
typedef struct { typedef struct {
size_t buffer_length; size_t buffer_length;
size_t half_buffer_length; size_t half_buffer_length;
uint8_t* buffer_buffer; uint8_t *buffer_buffer;
uint16_t* sample_buffer; uint16_t *sample_buffer;
float volume; float volume;
FuriMessageQueue* queue; FuriMessageQueue *queue;
DTMFDolphinOsc* osc1; DTMFDolphinOsc *osc1;
DTMFDolphinOsc* osc2; DTMFDolphinOsc *osc2;
DTMFDolphinPulseFilter* filter; DTMFDolphinPulseFilter *filter;
bool playing; bool playing;
} DTMFDolphinAudio; } DTMFDolphinAudio;
@@ -42,12 +42,7 @@ void dtmf_dolphin_audio_free(DTMFDolphinAudio* player);
void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc); void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc);
bool dtmf_dolphin_audio_play_tones( bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, uint16_t pulse_ms, uint16_t gap_ms);
float freq1,
float freq2,
uint16_t pulses,
uint16_t pulse_ms,
uint16_t gap_ms);
bool dtmf_dolphin_audio_stop_tones(); bool dtmf_dolphin_audio_stop_tones();

View File

@@ -7,13 +7,13 @@ typedef struct {
} DTMFDolphinTonePos; } DTMFDolphinTonePos;
typedef struct { typedef struct {
const char* name; const char *name;
const float frequency_1; const float frequency_1;
const float frequency_2; const float frequency_2;
const DTMFDolphinTonePos pos; const DTMFDolphinTonePos pos;
const uint16_t pulses; // for Redbox const uint16_t pulses; // for Redbox
const uint16_t pulse_ms; // for Redbox const uint16_t pulse_ms; // for Redbox
const uint16_t gap_duration; // for Redbox const uint16_t gap_duration; // for Redbox
} DTMFDolphinTones; } DTMFDolphinTones;
typedef struct { typedef struct {
@@ -44,38 +44,52 @@ DTMFDolphinSceneData DTMFDolphinSceneDataDialer = {
{"0", 941.0, 1336.0, {3, 1, 1}, 0, 0, 0}, {"0", 941.0, 1336.0, {3, 1, 1}, 0, 0, 0},
{"#", 941.0, 1477.0, {3, 2, 1}, 0, 0, 0}, {"#", 941.0, 1477.0, {3, 2, 1}, 0, 0, 0},
{"D", 941.0, 1633.0, {3, 3, 1}, 0, 0, 0}, {"D", 941.0, 1633.0, {3, 3, 1}, 0, 0, 0},
}}; }
};
DTMFDolphinSceneData DTMFDolphinSceneDataBluebox = { DTMFDolphinSceneData DTMFDolphinSceneDataBluebox = {
.name = "Bluebox", .name = "Bluebox",
.block = DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX, .block = DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX,
.tone_count = 13, .tone_count = 13,
.tones = { .tones = {
{"1", 700.0, 900.0, {0, 0, 1}, 0, 0, 0}, {"1", 700.0, 900.0, {0, 0, 1}, 0, 0, 0},
{"2", 700.0, 1100.0, {0, 1, 1}, 0, 0, 0}, {"2", 700.0, 1100.0, {0, 1, 1}, 0, 0, 0},
{"3", 900.0, 1100.0, {0, 2, 1}, 0, 0, 0}, {"3", 900.0, 1100.0, {0, 2, 1}, 0, 0, 0},
{"4", 700.0, 1300.0, {1, 0, 1}, 0, 0, 0}, {"4", 700.0, 1300.0, {1, 0, 1}, 0, 0, 0},
{"5", 900.0, 1300.0, {1, 1, 1}, 0, 0, 0}, {"5", 900.0, 1300.0, {1, 1, 1}, 0, 0, 0},
{"6", 1100.0, 1300.0, {1, 2, 1}, 0, 0, 0}, {"6", 1100.0, 1300.0, {1, 2, 1}, 0, 0, 0},
{"7", 700.0, 1500.0, {2, 0, 1}, 0, 0, 0}, {"7", 700.0, 1500.0, {2, 0, 1}, 0, 0, 0},
{"8", 900.0, 1500.0, {2, 1, 1}, 0, 0, 0}, {"8", 900.0, 1500.0, {2, 1, 1}, 0, 0, 0},
{"9", 1100.0, 1500.0, {2, 2, 1}, 0, 0, 0}, {"9", 1100.0, 1500.0, {2, 2, 1}, 0, 0, 0},
{"0", 1300.0, 1500.0, {3, 1, 1}, 0, 0, 0}, {"0", 1300.0, 1500.0, {3, 1, 1}, 0, 0, 0},
{"KP", 1100.0, 1700.0, {0, 3, 2}, 0, 0, 0}, {"KP", 1100.0, 1700.0, {0, 3, 2}, 0, 0, 0},
{"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0}, {"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0},
{"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0}, {"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0},
}}; }
};
DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUS = { DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUS = {
.name = "Redbox (US)", .name = "Redbox (US)",
.block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US, .block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US,
.tone_count = 4, .tone_count = 4,
.tones = { .tones = {
{"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0}, {"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0},
{"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66}, {"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66},
{"Quarter", 1700.0, 2200.0, {2, 0, 5}, 5, 33, 33}, {"Quarter", 1700.0, 2200.0, {2, 0, 5}, 5, 33, 33},
{"Dollar", 1700.0, 2200.0, {3, 0, 5}, 1, 650, 0}, {"Dollar", 1700.0, 2200.0, {3, 0, 5}, 1, 650, 0},
}}; }
};
DTMFDolphinSceneData DTMFDolphinSceneDataRedboxCA = {
.name = "Redbox (CA)",
.block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA,
.tone_count = 3,
.tones = {
{"Nickel", 2200.0, 0.0, {0, 0, 5}, 1, 66, 0},
{"Dime", 2200.0, 0.0, {1, 0, 5}, 2, 66, 66},
{"Quarter", 2200.0, 0.0, {2, 0, 5}, 5, 33, 33},
}
};
DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = { DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = {
.name = "Redbox (UK)", .name = "Redbox (UK)",
@@ -84,31 +98,37 @@ DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = {
.tones = { .tones = {
{"10p", 1000.0, 0.0, {0, 0, 5}, 1, 200, 0}, {"10p", 1000.0, 0.0, {0, 0, 5}, 1, 200, 0},
{"50p", 1000.0, 0.0, {1, 0, 5}, 1, 350, 0}, {"50p", 1000.0, 0.0, {1, 0, 5}, 1, 350, 0},
}}; }
};
DTMFDolphinSceneData DTMFDolphinSceneDataMisc = { DTMFDolphinSceneData DTMFDolphinSceneDataMisc = {
.name = "Misc", .name = "Misc",
.block = DTMF_DOLPHIN_TONE_BLOCK_MISC, .block = DTMF_DOLPHIN_TONE_BLOCK_MISC,
.tone_count = 3, .tone_count = 3,
.tones = { .tones = {
{"CCITT 11", 700.0, 1700.0, {0, 0, 5}, 0, 0, 0}, {"CCITT 11", 700.0, 1700.0, {0, 0, 5}, 0, 0, 0},
{"CCITT 12", 900.0, 1700.0, {1, 0, 5}, 0, 0, 0}, {"CCITT 12", 900.0, 1700.0, {1, 0, 5}, 0, 0, 0},
{"CCITT KP2", 1300.0, 1700.0, {2, 0, 5}, 0, 0, 0}, {"CCITT KP2", 1300.0, 1700.0, {2, 0, 5}, 0, 0, 0},
}}; }
};
DTMFDolphinToneSection current_section; DTMFDolphinToneSection current_section;
DTMFDolphinSceneData* current_scene_data; DTMFDolphinSceneData *current_scene_data;
void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) { void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) {
current_section = section; current_section = section;
switch(current_section) { switch (current_section)
{
case DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX: case DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX:
current_scene_data = &DTMFDolphinSceneDataBluebox; current_scene_data = &DTMFDolphinSceneDataBluebox;
break; break;
case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US: case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US:
current_scene_data = &DTMFDolphinSceneDataRedboxUS; current_scene_data = &DTMFDolphinSceneDataRedboxUS;
break; break;
case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA:
current_scene_data = &DTMFDolphinSceneDataRedboxCA;
break;
case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK: case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK:
current_scene_data = &DTMFDolphinSceneDataRedboxUK; current_scene_data = &DTMFDolphinSceneDataRedboxUK;
break; break;
@@ -125,14 +145,14 @@ DTMFDolphinToneSection dtmf_dolphin_data_get_current_section() {
return current_section; return current_section;
} }
DTMFDolphinSceneData* dtmf_dolphin_data_get_current_scene_data() { DTMFDolphinSceneData *dtmf_dolphin_data_get_current_scene_data() {
return current_scene_data; return current_scene_data;
} }
bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col) { bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t row, uint8_t col) {
for(size_t i = 0; i < current_scene_data->tone_count; i++) { for (size_t i = 0; i < current_scene_data->tone_count; i++) {
DTMFDolphinTones tones = current_scene_data->tones[i]; DTMFDolphinTones tones = current_scene_data->tones[i];
if(tones.pos.row == row && tones.pos.col == col) { if (tones.pos.row == row && tones.pos.col == col) {
freq1[0] = tones.frequency_1; freq1[0] = tones.frequency_1;
freq2[0] = tones.frequency_2; freq2[0] = tones.frequency_2;
return true; return true;
@@ -141,15 +161,10 @@ bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t
return false; return false;
} }
bool dtmf_dolphin_data_get_filter_data( bool dtmf_dolphin_data_get_filter_data(uint16_t *pulses, uint16_t *pulse_ms, uint16_t *gap_ms, uint8_t row, uint8_t col) {
uint16_t* pulses, for (size_t i = 0; i < current_scene_data->tone_count; i++) {
uint16_t* pulse_ms,
uint16_t* gap_ms,
uint8_t row,
uint8_t col) {
for(size_t i = 0; i < current_scene_data->tone_count; i++) {
DTMFDolphinTones tones = current_scene_data->tones[i]; DTMFDolphinTones tones = current_scene_data->tones[i];
if(tones.pos.row == row && tones.pos.col == col) { if (tones.pos.row == row && tones.pos.col == col) {
pulses[0] = tones.pulses; pulses[0] = tones.pulses;
pulse_ms[0] = tones.pulse_ms; pulse_ms[0] = tones.pulse_ms;
gap_ms[0] = tones.gap_duration; gap_ms[0] = tones.gap_duration;
@@ -160,9 +175,9 @@ bool dtmf_dolphin_data_get_filter_data(
} }
const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) { const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) {
for(size_t i = 0; i < current_scene_data->tone_count; i++) { for (size_t i = 0; i < current_scene_data->tone_count; i++) {
DTMFDolphinTones tones = current_scene_data->tones[i]; DTMFDolphinTones tones = current_scene_data->tones[i];
if(tones.pos.row == row && tones.pos.col == col) { if (tones.pos.row == row && tones.pos.col == col) {
return tones.name; return tones.name;
} }
} }
@@ -170,7 +185,7 @@ const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) {
} }
const char* dtmf_dolphin_data_get_current_section_name() { const char* dtmf_dolphin_data_get_current_section_name() {
if(current_scene_data) { if (current_scene_data) {
return current_scene_data->name; return current_scene_data->name;
} }
return NULL; return NULL;
@@ -180,26 +195,27 @@ void dtmf_dolphin_tone_get_max_pos(uint8_t* max_rows, uint8_t* max_cols, uint8_t
max_rows[0] = 0; max_rows[0] = 0;
max_cols[0] = 0; max_cols[0] = 0;
max_span[0] = 0; max_span[0] = 0;
uint8_t tmp_rowspan[5] = {0, 0, 0, 0, 0}; uint8_t tmp_rowspan[5] = { 0, 0, 0, 0, 0 };
for(size_t i = 0; i < current_scene_data->tone_count; i++) { for (size_t i = 0; i < current_scene_data->tone_count; i++) {
DTMFDolphinTones tones = current_scene_data->tones[i]; DTMFDolphinTones tones = current_scene_data->tones[i];
if(tones.pos.row > max_rows[0]) { if (tones.pos.row > max_rows[0]) {
max_rows[0] = tones.pos.row; max_rows[0] = tones.pos.row;
} }
if(tones.pos.col > max_cols[0]) { if (tones.pos.col > max_cols[0]) {
max_cols[0] = tones.pos.col; max_cols[0] = tones.pos.col;
} }
tmp_rowspan[tones.pos.row] += tones.pos.span; tmp_rowspan[tones.pos.row] += tones.pos.span;
if(tmp_rowspan[tones.pos.row] > max_span[0]) max_span[0] = tmp_rowspan[tones.pos.row]; if (tmp_rowspan[tones.pos.row] > max_span[0])
max_span[0] = tmp_rowspan[tones.pos.row];
} }
max_rows[0]++; max_rows[0]++;
max_cols[0]++; max_cols[0]++;
} }
uint8_t dtmf_dolphin_get_tone_span(uint8_t row, uint8_t col) { uint8_t dtmf_dolphin_get_tone_span(uint8_t row, uint8_t col) {
for(size_t i = 0; i < current_scene_data->tone_count; i++) { for (size_t i = 0; i < current_scene_data->tone_count; i++) {
DTMFDolphinTones tones = current_scene_data->tones[i]; DTMFDolphinTones tones = current_scene_data->tones[i];
if(tones.pos.row == row && tones.pos.col == col) { if (tones.pos.row == row && tones.pos.col == col) {
return tones.pos.span; return tones.pos.span;
} }
} }

View File

@@ -17,14 +17,9 @@ void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section);
DTMFDolphinToneSection dtmf_dolphin_data_get_current_section(); DTMFDolphinToneSection dtmf_dolphin_data_get_current_section();
bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col); bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t row, uint8_t col);
bool dtmf_dolphin_data_get_filter_data( bool dtmf_dolphin_data_get_filter_data(uint16_t *pulses, uint16_t *pulse_ms, uint16_t *gap_ms, uint8_t row, uint8_t col);
uint16_t* pulses,
uint16_t* pulse_ms,
uint16_t* gap_ms,
uint8_t row,
uint8_t col);
const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col); const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col);

View File

@@ -17,6 +17,7 @@
#define TAG "DTMFDolphin" #define TAG "DTMFDolphin"
enum DTMFDolphinSceneState { enum DTMFDolphinSceneState {
DTMFDolphinSceneStateDialer, DTMFDolphinSceneStateDialer,
DTMFDolphinSceneStateBluebox, DTMFDolphinSceneStateBluebox,
@@ -38,4 +39,7 @@ typedef struct {
NotificationApp* notification; NotificationApp* notification;
} DTMFDolphinApp; } DTMFDolphinApp;
typedef enum { DTMFDolphinViewMainMenu, DTMFDolphinViewDialer } DTMFDolphinView; typedef enum {
DTMFDolphinViewMainMenu,
DTMFDolphinViewDialer
} DTMFDolphinView;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

View File

@@ -2,12 +2,14 @@
// #include "../dtmf_dolphin_data.h" // #include "../dtmf_dolphin_data.h"
// #include "../dtmf_dolphin_audio.h" // #include "../dtmf_dolphin_audio.h"
void dtmf_dolphin_scene_dialer_on_enter(void* context) {
void dtmf_dolphin_scene_dialer_on_enter(void *context) {
DTMFDolphinApp* app = context; DTMFDolphinApp* app = context;
DTMFDolphinScene scene_id = DTMFDolphinSceneDialer; DTMFDolphinScene scene_id = DTMFDolphinSceneDialer;
enum DTMFDolphinSceneState state = scene_manager_get_scene_state(app->scene_manager, scene_id); enum DTMFDolphinSceneState state = scene_manager_get_scene_state(app->scene_manager, scene_id);
switch(state) { switch (state)
{
case DTMFDolphinSceneStateBluebox: case DTMFDolphinSceneStateBluebox:
dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX); dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX);
break; break;

View File

@@ -3,7 +3,8 @@
static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uint32_t index) { static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uint32_t index) {
DTMFDolphinApp* app = context; DTMFDolphinApp* app = context;
uint8_t cust_event = 255; uint8_t cust_event = 255;
switch(index) { switch (index)
{
case 0: case 0:
cust_event = DTMFDolphinEventStartDialer; cust_event = DTMFDolphinEventStartDialer;
break; break;
@@ -23,7 +24,10 @@ static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uin
return; return;
} }
view_dispatcher_send_custom_event(app->view_dispatcher, cust_event); view_dispatcher_send_custom_event(
app->view_dispatcher,
cust_event
);
} }
void dtmf_dolphin_scene_start_on_enter(void* context) { void dtmf_dolphin_scene_start_on_enter(void* context) {
@@ -32,7 +36,9 @@ void dtmf_dolphin_scene_start_on_enter(void* context) {
// VariableItem* item; // VariableItem* item;
variable_item_list_set_enter_callback( variable_item_list_set_enter_callback(
var_item_list, dtmf_dolphin_scene_start_main_menu_enter_callback, app); var_item_list,
dtmf_dolphin_scene_start_main_menu_enter_callback,
app);
variable_item_list_add(var_item_list, "Dialer", 0, NULL, context); variable_item_list_add(var_item_list, "Dialer", 0, NULL, context);
variable_item_list_add(var_item_list, "Bluebox", 0, NULL, context); variable_item_list_add(var_item_list, "Bluebox", 0, NULL, context);
@@ -41,9 +47,12 @@ void dtmf_dolphin_scene_start_on_enter(void* context) {
variable_item_list_add(var_item_list, "Misc", 0, NULL, context); variable_item_list_add(var_item_list, "Misc", 0, NULL, context);
variable_item_list_set_selected_item( variable_item_list_set_selected_item(
var_item_list, scene_manager_get_scene_state(app->scene_manager, DTMFDolphinSceneStart)); var_item_list,
scene_manager_get_scene_state(app->scene_manager, DTMFDolphinSceneStart));
view_dispatcher_switch_to_view(app->view_dispatcher, DTMFDolphinViewMainMenu); view_dispatcher_switch_to_view(
app->view_dispatcher,
DTMFDolphinViewMainMenu);
} }
bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) { bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
@@ -54,7 +63,8 @@ bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
uint8_t sc_state; uint8_t sc_state;
switch(event.event) { switch (event.event)
{
case DTMFDolphinEventStartDialer: case DTMFDolphinEventStartDialer:
sc_state = DTMFDolphinSceneStateDialer; sc_state = DTMFDolphinSceneStateDialer;
break; break;

View File

@@ -7,4 +7,4 @@
#define DTMF_DOLPHIN_NUMPAD_Y 14 #define DTMF_DOLPHIN_NUMPAD_Y 14
#define DTMF_DOLPHIN_BUTTON_WIDTH 13 #define DTMF_DOLPHIN_BUTTON_WIDTH 13
#define DTMF_DOLPHIN_BUTTON_HEIGHT 13 #define DTMF_DOLPHIN_BUTTON_HEIGHT 13
#define DTMF_DOLPHIN_BUTTON_PADDING 1 // all sides #define DTMF_DOLPHIN_BUTTON_PADDING 1 // all sides

View File

@@ -24,55 +24,53 @@ static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_diale
static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer); static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer);
static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer); static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer);
static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer); static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer);
static bool static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event);
dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event);
void draw_button(Canvas* canvas, uint8_t row, uint8_t col, bool invert) { void draw_button(Canvas* canvas, uint8_t row, uint8_t col, bool invert) {
uint8_t left = DTMF_DOLPHIN_NUMPAD_X + // ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
(col * DTMF_DOLPHIN_BUTTON_WIDTH); uint8_t left = DTMF_DOLPHIN_NUMPAD_X + \
// (col * DTMF_DOLPHIN_BUTTON_PADDING); // ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + // ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) + (col * DTMF_DOLPHIN_BUTTON_WIDTH);
(row * DTMF_DOLPHIN_BUTTON_HEIGHT); // (col * DTMF_DOLPHIN_BUTTON_PADDING);
// (row * DTMF_DOLPHIN_BUTTON_PADDING); uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + \
// ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
(row * DTMF_DOLPHIN_BUTTON_HEIGHT);
// (row * DTMF_DOLPHIN_BUTTON_PADDING);
uint8_t span = dtmf_dolphin_get_tone_span(row, col); uint8_t span = dtmf_dolphin_get_tone_span(row, col);
if(span == 0) { if (span == 0) {
return; return;
} }
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
if(invert) if (invert)
canvas_draw_rbox( canvas_draw_rbox(canvas, left, top,
canvas,
left,
top,
(DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2), (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2), DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
2); 2);
else else
canvas_draw_rframe( canvas_draw_rframe(canvas, left, top,
canvas,
left,
top,
(DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2), (DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2), DTMF_DOLPHIN_BUTTON_HEIGHT- (DTMF_DOLPHIN_BUTTON_PADDING * 2),
2); 2);
if(invert) canvas_invert_color(canvas); if (invert)
canvas_invert_color(canvas);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
// canvas_set_color(canvas, invert ? ColorWhite : ColorBlack); // canvas_set_color(canvas, invert ? ColorWhite : ColorBlack);
canvas_draw_str_aligned( canvas_draw_str_aligned(canvas,
canvas, left - 1 + (int) ((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2),
left - 1 + (int)((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2), top + (int) (DTMF_DOLPHIN_BUTTON_HEIGHT / 2),
top + (int)(DTMF_DOLPHIN_BUTTON_HEIGHT / 2),
AlignCenter, AlignCenter,
AlignCenter, AlignCenter,
dtmf_dolphin_data_get_tone_name(row, col)); dtmf_dolphin_data_get_tone_name(row, col));
if(invert) canvas_invert_color(canvas); if (invert)
canvas_invert_color(canvas);
} }
void draw_dialer(Canvas* canvas, void* _model) { void draw_dialer(Canvas* canvas, void* _model) {
@@ -84,9 +82,9 @@ void draw_dialer(Canvas* canvas, void* _model) {
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
for(int r = 0; r < max_rows; r++) { for (int r = 0; r < max_rows; r++) {
for(int c = 0; c < max_cols; c++) { for (int c = 0; c < max_cols; c++) {
if(model->row == r && model->col == c) if (model->row == r && model->col == c)
draw_button(canvas, r, c, true); draw_button(canvas, r, c, true);
else else
draw_button(canvas, r, c, false); draw_button(canvas, r, c, false);
@@ -94,15 +92,14 @@ void draw_dialer(Canvas* canvas, void* _model) {
} }
} }
void update_frequencies(DTMFDolphinDialerModel* model) { void update_frequencies(DTMFDolphinDialerModel *model) {
dtmf_dolphin_data_get_tone_frequencies(&model->freq1, &model->freq2, model->row, model->col); dtmf_dolphin_data_get_tone_frequencies(&model->freq1, &model->freq2, model->row, model->col);
dtmf_dolphin_data_get_filter_data( dtmf_dolphin_data_get_filter_data(&model->pulses, &model->pulse_ms, &model->gap_ms, model->row, model->col);
&model->pulses, &model->pulse_ms, &model->gap_ms, model->row, model->col);
} }
static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) { static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
DTMFDolphinDialerModel* model = _model; DTMFDolphinDialerModel* model = _model;
if(model->playing) { if (model->playing) {
// Leverage the prioritized draw callback to handle // Leverage the prioritized draw callback to handle
// the DMA so that it doesn't skip. // the DMA so that it doesn't skip.
dtmf_dolphin_audio_handle_tick(); dtmf_dolphin_audio_handle_tick();
@@ -125,41 +122,46 @@ static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
elements_multiline_text(canvas, 2, 10, dtmf_dolphin_data_get_current_section_name()); elements_multiline_text(canvas, 2, 10, dtmf_dolphin_data_get_current_section_name());
canvas_draw_line( canvas_draw_line(canvas,
canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, 0,
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, canvas_height(canvas));
0,
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1,
canvas_height(canvas));
elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 10, "Detail"); elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 10, "Detail");
canvas_draw_line( canvas_draw_line(canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3);
canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3);
// elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Dialer Mode"); // elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Dialer Mode");
draw_dialer(canvas, model); draw_dialer(canvas, model);
FuriString* output = furi_string_alloc(); FuriString *output = furi_string_alloc();
if(model->freq1 && model->freq2) { if (model->freq1 && model->freq2) {
furi_string_cat_printf( furi_string_cat_printf(
output, output,
"Dual Tone\nF1: %u Hz\nF2: %u Hz\n", "Dual Tone\nF1: %u Hz\nF2: %u Hz\n",
(unsigned int)model->freq1, (unsigned int) model->freq1,
(unsigned int)model->freq2); (unsigned int) model->freq2);
} else if(model->freq1) { } else if (model->freq1) {
furi_string_cat_printf(output, "Single Tone\nF: %u Hz\n", (unsigned int)model->freq1); furi_string_cat_printf(
output,
"Single Tone\nF: %u Hz\n",
(unsigned int) model->freq1);
} }
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
if(model->pulse_ms) { if (model->pulse_ms) {
furi_string_cat_printf(output, "P: %u * %u ms\n", model->pulses, model->pulse_ms); furi_string_cat_printf(
output,
"P: %u * %u ms\n",
model->pulses,
model->pulse_ms);
} }
if(model->gap_ms) { if (model->gap_ms) {
furi_string_cat_printf(output, "Gaps: %u ms\n", model->gap_ms); furi_string_cat_printf(
output,
"Gaps: %u ms\n",
model->gap_ms);
} }
elements_multiline_text( elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, furi_string_get_cstr(output));
canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, furi_string_get_cstr(output));
furi_string_free(output); furi_string_free(output);
} }
@@ -194,11 +196,11 @@ static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_diale
{ {
uint8_t span = 0; uint8_t span = 0;
uint8_t cursor = model->row; uint8_t cursor = model->row;
while(span == 0 && cursor > 0) { while (span == 0 && cursor > 0) {
cursor--; cursor--;
span = dtmf_dolphin_get_tone_span(cursor, model->col); span = dtmf_dolphin_get_tone_span(cursor, model->col);
} }
if(span != 0) { if (span != 0) {
model->row = cursor; model->row = cursor;
} }
}, },
@@ -222,7 +224,7 @@ static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dia
cursor++; cursor++;
span = dtmf_dolphin_get_tone_span(cursor, model->col); span = dtmf_dolphin_get_tone_span(cursor, model->col);
} }
if(span != 0) { if (span != 0) {
model->row = cursor; model->row = cursor;
} }
}, },
@@ -237,11 +239,11 @@ static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dia
{ {
uint8_t span = 0; uint8_t span = 0;
uint8_t cursor = model->col; uint8_t cursor = model->col;
while(span == 0 && cursor > 0) { while (span == 0 && cursor > 0) {
cursor--; cursor--;
span = dtmf_dolphin_get_tone_span(model->row, cursor); span = dtmf_dolphin_get_tone_span(model->row, cursor);
} }
if(span != 0) { if (span != 0) {
model->col = cursor; model->col = cursor;
} }
}, },
@@ -265,7 +267,7 @@ static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_di
cursor++; cursor++;
span = dtmf_dolphin_get_tone_span(model->row, cursor); span = dtmf_dolphin_get_tone_span(model->row, cursor);
} }
if(span != 0) { if (span != 0) {
model->col = cursor; model->col = cursor;
} }
}, },
@@ -273,18 +275,16 @@ static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_di
return true; return true;
} }
static bool static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) {
dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) {
bool consumed = false; bool consumed = false;
with_view_model( with_view_model(
dtmf_dolphin_dialer->view, dtmf_dolphin_dialer->view,
DTMFDolphinDialerModel * model, DTMFDolphinDialerModel * model,
{ {
if(event->type == InputTypePress) { if (event->type == InputTypePress) {
model->playing = dtmf_dolphin_audio_play_tones( model->playing = dtmf_dolphin_audio_play_tones(model->freq1, model->freq2, model->pulses, model->pulse_ms, model->gap_ms);
model->freq1, model->freq2, model->pulses, model->pulse_ms, model->gap_ms); } else if (event->type == InputTypeRelease) {
} else if(event->type == InputTypeRelease) {
model->playing = !dtmf_dolphin_audio_stop_tones(); model->playing = !dtmf_dolphin_audio_stop_tones();
} }
}, },
@@ -308,15 +308,15 @@ static void dtmf_dolphin_dialer_enter_callback(void* context) {
model->freq2 = 0.0; model->freq2 = 0.0;
model->playing = false; model->playing = false;
}, },
true); true
);
} }
DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() { DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() {
DTMFDolphinDialer* dtmf_dolphin_dialer = malloc(sizeof(DTMFDolphinDialer)); DTMFDolphinDialer* dtmf_dolphin_dialer = malloc(sizeof(DTMFDolphinDialer));
dtmf_dolphin_dialer->view = view_alloc(); dtmf_dolphin_dialer->view = view_alloc();
view_allocate_model( view_allocate_model(dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel));
dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel));
with_view_model( with_view_model(
dtmf_dolphin_dialer->view, dtmf_dolphin_dialer->view,
@@ -329,7 +329,8 @@ DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() {
model->freq2 = 0.0; model->freq2 = 0.0;
model->playing = false; model->playing = false;
}, },
true); true
);
view_set_context(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer); view_set_context(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer);
view_set_draw_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_draw_callback); view_set_draw_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_draw_callback);
@@ -348,3 +349,4 @@ View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer) {
furi_assert(dtmf_dolphin_dialer); furi_assert(dtmf_dolphin_dialer);
return dtmf_dolphin_dialer->view; return dtmf_dolphin_dialer->view;
} }

View File

@@ -12,7 +12,4 @@ void dtmf_dolphin_dialer_free(DTMFDolphinDialer* dtmf_dolphin_dialer);
View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer); View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer);
void dtmf_dolphin_dialer_set_ok_callback( void dtmf_dolphin_dialer_set_ok_callback(DTMFDolphinDialer* dtmf_dolphin_dialer, DTMFDolphinDialerOkCallback callback, void* context);
DTMFDolphinDialer* dtmf_dolphin_dialer,
DTMFDolphinDialerOkCallback callback,
void* context);