Просмотр исходного кода

Merge pull request #9 from xMasterX/redbox_ca_fix

Add Redbox (CA) to menu, apply ./fbt format
Aria Burrell 3 лет назад
Родитель
Сommit
837ce097b8

+ 2 - 2
dtmf_dolphin.c

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

+ 49 - 43
dtmf_dolphin_audio.c

@@ -1,11 +1,11 @@
 #include "dtmf_dolphin_audio.h"
 
-DTMFDolphinAudio *current_player;
+DTMFDolphinAudio* current_player;
 
 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);
 
         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) {
-    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;
     }
 }
 
 DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
-    DTMFDolphinOsc *osc = malloc(sizeof(DTMFDolphinOsc));
+    DTMFDolphinOsc* osc = malloc(sizeof(DTMFDolphinOsc));
     osc->cached_freq = 0;
     osc->offset = 0;
     osc->period = 0;
@@ -36,7 +36,7 @@ DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
 }
 
 DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() {
-    DTMFDolphinPulseFilter *pf = malloc(sizeof(DTMFDolphinPulseFilter));
+    DTMFDolphinPulseFilter* pf = malloc(sizeof(DTMFDolphinPulseFilter));
     pf->duration = 0;
     pf->period = 0;
     pf->offset = 0;
@@ -45,7 +45,7 @@ DTMFDolphinPulseFilter* dtmf_dolphin_pulse_filter_alloc() {
 }
 
 DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
-    DTMFDolphinAudio *player = malloc(sizeof(DTMFDolphinAudio));
+    DTMFDolphinAudio* player = malloc(sizeof(DTMFDolphinAudio));
     player->buffer_length = SAMPLE_BUFFER_LENGTH;
     player->half_buffer_length = SAMPLE_BUFFER_LENGTH / 2;
     player->sample_buffer = malloc(sizeof(uint16_t) * player->buffer_length);
@@ -61,56 +61,58 @@ DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
 }
 
 size_t calc_waveform_period(float freq) {
-    if (!freq) {
+    if(!freq) {
         return 0;
     }
     // DMA Rate calculation, thanks to Dr_Zlo
-    float dma_rate = CPU_CLOCK_FREQ \
-        / 2 \
-        / DTMF_DOLPHIN_HAL_DMA_PRESCALER \
-        / (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
+    float dma_rate = CPU_CLOCK_FREQ / 2 / DTMF_DOLPHIN_HAL_DMA_PRESCALER /
+                     (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
 
     // Using a constant scaling modifier, which likely represents
     // 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) {
-    if (osc->lookup_table != NULL) {
+    if(osc->lookup_table != NULL) {
         free(osc->lookup_table);
     }
     osc->offset = 0;
     osc->cached_freq = freq;
     osc->period = calc_waveform_period(freq);
-    if (!osc->period) {
+    if(!osc->period) {
         osc->lookup_table = NULL;
         return;
     }
     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;
     }
 }
 
-void filter_generate_lookup_table(DTMFDolphinPulseFilter* pf, uint16_t pulses, uint16_t pulse_ms, uint16_t gap_ms) {
-    if (pf->lookup_table != NULL) {
+void filter_generate_lookup_table(
+    DTMFDolphinPulseFilter* pf,
+    uint16_t pulses,
+    uint16_t pulse_ms,
+    uint16_t gap_ms) {
+    if(pf->lookup_table != NULL) {
         free(pf->lookup_table);
     }
     pf->offset = 0;
 
-    uint16_t gap_period = calc_waveform_period(1000 / (float) gap_ms);
-    uint16_t pulse_period = calc_waveform_period(1000 / (float) pulse_ms);
+    uint16_t gap_period = calc_waveform_period(1000 / (float)gap_ms);
+    uint16_t pulse_period = calc_waveform_period(1000 / (float)pulse_ms);
     pf->period = pulse_period + gap_period;
 
-    if (!pf->period) {
+    if(!pf->period) {
         pf->lookup_table = NULL;
         return;
     }
     pf->duration = pf->period * pulses;
     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;
     }
 }
@@ -118,7 +120,7 @@ void filter_generate_lookup_table(DTMFDolphinPulseFilter* pf, uint16_t pulses, u
 float sample_frame(DTMFDolphinOsc* osc) {
     float frame = 0.0;
 
-    if (osc->period) {
+    if(osc->period) {
         frame = osc->lookup_table[osc->offset];
         osc->offset = (osc->offset + 1) % osc->period;
     }
@@ -129,8 +131,8 @@ float sample_frame(DTMFDolphinOsc* osc) {
 bool sample_filter(DTMFDolphinPulseFilter* pf) {
     bool frame = true;
 
-    if (pf->duration) {
-        if (pf->offset < pf->duration) {
+    if(pf->duration) {
+        if(pf->offset < pf->duration) {
             frame = pf->lookup_table[pf->offset];
             pf->offset = pf->offset + 1;
         } else {
@@ -142,14 +144,14 @@ bool sample_filter(DTMFDolphinPulseFilter* pf) {
 }
 
 void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) {
-    if (osc->lookup_table != NULL) {
+    if(osc->lookup_table != NULL) {
         free(osc->lookup_table);
     }
     free(osc);
 }
 
 void dtmf_dolphin_filter_free(DTMFDolphinPulseFilter* pf) {
-    if (pf->lookup_table != NULL) {
+    if(pf->lookup_table != NULL) {
         free(pf->lookup_table);
     }
     free(pf);
@@ -165,22 +167,19 @@ void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) {
     current_player = NULL;
 }
 
-
 bool generate_waveform(DTMFDolphinAudio* player, uint16_t 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;
-        if (player->osc2->period) {
-            data = \
-                (sample_frame(player->osc1) / 2) + \
-                (sample_frame(player->osc2) / 2);
+        if(player->osc2->period) {
+            data = (sample_frame(player->osc1) / 2) + (sample_frame(player->osc2) / 2);
         } else {
             data = (sample_frame(player->osc1));
         }
         data *= sample_filter(player->filter) ? player->volume : 0.0;
-        data *= UINT8_MAX / 2;  // scale -128..127
-        data += UINT8_MAX / 2;  // to unsigned
+        data *= UINT8_MAX / 2; // scale -128..127
+        data += UINT8_MAX / 2; // to unsigned
 
         if(data < 0) {
             data = 0;
@@ -196,8 +195,13 @@ bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) {
     return true;
 }
 
-bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, uint16_t pulse_ms, uint16_t gap_ms) {
-    if (current_player != NULL && current_player->playing) {
+bool dtmf_dolphin_audio_play_tones(
+    float freq1,
+    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
         return false;
     }
@@ -213,7 +217,8 @@ bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, ui
     dtmf_dolphin_speaker_init();
     dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length);
 
-    furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
+    furi_hal_interrupt_set_isr(
+        FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
 
     dtmf_dolphin_dma_start();
     dtmf_dolphin_speaker_start();
@@ -222,11 +227,12 @@ bool dtmf_dolphin_audio_play_tones(float freq1, float freq2, uint16_t pulses, ui
 }
 
 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.
         return false;
     }
-    while(current_player->filter->offset > 0 && current_player->filter->offset < current_player->filter->duration) {
+    while(current_player->filter->offset > 0 &&
+          current_player->filter->offset < current_player->filter->duration) {
         // run remaining ticks if needed to complete filter sequence
         dtmf_dolphin_audio_handle_tick();
     }
@@ -236,20 +242,20 @@ bool dtmf_dolphin_audio_stop_tones() {
     furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
 
     dtmf_dolphin_audio_free(current_player);
-   
+
     return true;
 }
 
 bool dtmf_dolphin_audio_handle_tick() {
     bool handled = false;
 
-    if (current_player) {
+    if(current_player) {
         DTMFDolphinCustomEvent event;
         if(furi_message_queue_get(current_player->queue, &event, 250) == FuriStatusOk) {
             if(event.type == DTMFDolphinEventDMAHalfTransfer) {
                 generate_waveform(current_player, 0);
                 handled = true;
-            } else if (event.type == DTMFDolphinEventDMAFullTransfer) {
+            } else if(event.type == DTMFDolphinEventDMAFullTransfer) {
                 generate_waveform(current_player, current_player->half_buffer_length);
                 handled = true;
             }

+ 12 - 7
dtmf_dolphin_audio.h

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

+ 56 - 59
dtmf_dolphin_data.c

@@ -7,13 +7,13 @@ typedef struct {
 } DTMFDolphinTonePos;
 
 typedef struct {
-    const char *name;
+    const char* name;
     const float frequency_1;
     const float frequency_2;
     const DTMFDolphinTonePos pos;
-    const uint16_t pulses;         // for Redbox
-    const uint16_t pulse_ms;       // for Redbox
-    const uint16_t gap_duration;   // for Redbox
+    const uint16_t pulses; // for Redbox
+    const uint16_t pulse_ms; // for Redbox
+    const uint16_t gap_duration; // for Redbox
 } DTMFDolphinTones;
 
 typedef struct {
@@ -44,52 +44,48 @@ DTMFDolphinSceneData DTMFDolphinSceneDataDialer = {
         {"0", 941.0, 1336.0, {3, 1, 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},
-    }
-};
+    }};
 
 DTMFDolphinSceneData DTMFDolphinSceneDataBluebox = {
     .name = "Bluebox",
     .block = DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX,
     .tone_count = 13,
     .tones = {
-        {"1",      700.0,  900.0, {0, 0, 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},
-        {"4",      700.0, 1300.0, {1, 0, 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},
-        {"7",      700.0, 1500.0, {2, 0, 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},
-        {"0",     1300.0, 1500.0, {3, 1, 1}, 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},
-        {"2600",  2600.0,    0.0, {3, 2, 3}, 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},
+        {"3", 900.0, 1100.0, {0, 2, 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},
+        {"6", 1100.0, 1300.0, {1, 2, 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},
+        {"9", 1100.0, 1500.0, {2, 2, 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},
+        {"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0},
+        {"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0},
+    }};
 
 DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUS = {
     .name = "Redbox (US)",
     .block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US,
     .tone_count = 4,
     .tones = {
-        {"Nickel",  1700.0, 2200.0, {0, 0, 5}, 1, 66, 0},
-        {"Dime",    1700.0, 2200.0, {1, 0, 5}, 2, 66, 66},
+        {"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0},
+        {"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66},
         {"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},
-    }
-};
+        {"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 = {
     .name = "Redbox (UK)",
@@ -98,28 +94,25 @@ DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = {
     .tones = {
         {"10p", 1000.0, 0.0, {0, 0, 5}, 1, 200, 0},
         {"50p", 1000.0, 0.0, {1, 0, 5}, 1, 350, 0},
-    }
-};
+    }};
 
 DTMFDolphinSceneData DTMFDolphinSceneDataMisc = {
     .name = "Misc",
     .block = DTMF_DOLPHIN_TONE_BLOCK_MISC,
     .tone_count = 3,
     .tones = {
-        {"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 11", 700.0, 1700.0, {0, 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},
-    }
-};
+    }};
 
 DTMFDolphinToneSection current_section;
-DTMFDolphinSceneData *current_scene_data;
+DTMFDolphinSceneData* current_scene_data;
 
 void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) {
     current_section = section;
 
-    switch (current_section)
-    {
+    switch(current_section) {
     case DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX:
         current_scene_data = &DTMFDolphinSceneDataBluebox;
         break;
@@ -128,7 +121,7 @@ void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) {
         break;
     case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA:
         current_scene_data = &DTMFDolphinSceneDataRedboxCA;
-	break;
+        break;
     case DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK:
         current_scene_data = &DTMFDolphinSceneDataRedboxUK;
         break;
@@ -145,14 +138,14 @@ DTMFDolphinToneSection dtmf_dolphin_data_get_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;
 }
 
-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++) {
+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++) {
         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;
             freq2[0] = tones.frequency_2;
             return true;
@@ -161,10 +154,15 @@ bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t
     return false;
 }
 
-bool dtmf_dolphin_data_get_filter_data(uint16_t *pulses, 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++) {
+bool dtmf_dolphin_data_get_filter_data(
+    uint16_t* pulses,
+    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];
-        if (tones.pos.row == row && tones.pos.col == col) {
+        if(tones.pos.row == row && tones.pos.col == col) {
             pulses[0] = tones.pulses;
             pulse_ms[0] = tones.pulse_ms;
             gap_ms[0] = tones.gap_duration;
@@ -175,9 +173,9 @@ bool dtmf_dolphin_data_get_filter_data(uint16_t *pulses, uint16_t *pulse_ms, uin
 }
 
 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];
-        if (tones.pos.row == row && tones.pos.col == col) {
+        if(tones.pos.row == row && tones.pos.col == col) {
             return tones.name;
         }
     }
@@ -185,7 +183,7 @@ const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) {
 }
 
 const char* dtmf_dolphin_data_get_current_section_name() {
-    if (current_scene_data) {
+    if(current_scene_data) {
         return current_scene_data->name;
     }
     return NULL;
@@ -195,27 +193,26 @@ void dtmf_dolphin_tone_get_max_pos(uint8_t* max_rows, uint8_t* max_cols, uint8_t
     max_rows[0] = 0;
     max_cols[0] = 0;
     max_span[0] = 0;
-    uint8_t tmp_rowspan[5] = { 0, 0, 0, 0, 0 };
-    for (size_t i = 0; i < current_scene_data->tone_count; i++) {
+    uint8_t tmp_rowspan[5] = {0, 0, 0, 0, 0};
+    for(size_t i = 0; i < current_scene_data->tone_count; 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;
         }
-        if (tones.pos.col > max_cols[0]) {
+        if(tones.pos.col > max_cols[0]) {
             max_cols[0] = tones.pos.col;
         }
         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_cols[0]++;
 }
 
 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];
-        if (tones.pos.row == row && tones.pos.col == col) {
+        if(tones.pos.row == row && tones.pos.col == col) {
             return tones.pos.span;
         }
     }

+ 8 - 2
dtmf_dolphin_data.h

@@ -10,6 +10,7 @@ typedef enum {
     DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX,
     DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US,
     DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK,
+    DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA,
     DTMF_DOLPHIN_TONE_BLOCK_MISC,
 } DTMFDolphinToneSection;
 
@@ -17,9 +18,14 @@ void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection 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(uint16_t *pulses, uint16_t *pulse_ms, uint16_t *gap_ms, uint8_t row, uint8_t col);
+bool dtmf_dolphin_data_get_filter_data(
+    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);
 

+ 1 - 0
dtmf_dolphin_event.h

@@ -8,6 +8,7 @@ typedef enum {
     DTMFDolphinEventStartBluebox,
     DTMFDolphinEventStartRedboxUS,
     DTMFDolphinEventStartRedboxUK,
+    DTMFDolphinEventStartRedboxCA,
     DTMFDolphinEventStartMisc,
     DTMFDolphinEventPlayTones,
     DTMFDolphinEventStopTones,

+ 2 - 5
dtmf_dolphin_i.h

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

+ 6 - 5
scenes/dtmf_dolphin_scene_dialer.c

@@ -2,23 +2,24 @@
 // #include "../dtmf_dolphin_data.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;
     DTMFDolphinScene scene_id = DTMFDolphinSceneDialer;
     enum DTMFDolphinSceneState state = scene_manager_get_scene_state(app->scene_manager, scene_id);
 
-    switch (state)
-    {
+    switch(state) {
     case DTMFDolphinSceneStateBluebox:
         dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX);
-        break;    
+        break;
     case DTMFDolphinSceneStateRedboxUS:
         dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US);
         break;
     case DTMFDolphinSceneStateRedboxUK:
         dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_UK);
         break;
+    case DTMFDolphinSceneStateRedboxCA:
+        dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_CA);
+        break;
     case DTMFDolphinSceneStateMisc:
         dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_MISC);
         break;

+ 13 - 16
scenes/dtmf_dolphin_scene_start.c

@@ -3,8 +3,7 @@
 static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uint32_t index) {
     DTMFDolphinApp* app = context;
     uint8_t cust_event = 255;
-    switch (index)
-    {
+    switch(index) {
     case 0:
         cust_event = DTMFDolphinEventStartDialer;
         break;
@@ -18,16 +17,16 @@ static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uin
         cust_event = DTMFDolphinEventStartRedboxUK;
         break;
     case 4:
+        cust_event = DTMFDolphinEventStartRedboxCA;
+        break;
+    case 5:
         cust_event = DTMFDolphinEventStartMisc;
         break;
     default:
         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) {
@@ -36,23 +35,19 @@ void dtmf_dolphin_scene_start_on_enter(void* context) {
 
     // VariableItem* item;
     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, "Bluebox", 0, NULL, context);
     variable_item_list_add(var_item_list, "Redbox (US)", 0, NULL, context);
     variable_item_list_add(var_item_list, "Redbox (UK)", 0, NULL, context);
+    variable_item_list_add(var_item_list, "Redbox (CA)", 0, NULL, context);
     variable_item_list_add(var_item_list, "Misc", 0, NULL, context);
 
     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) {
@@ -63,8 +58,7 @@ bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
     if(event.type == SceneManagerEventTypeCustom) {
         uint8_t sc_state;
 
-        switch (event.event)
-        {
+        switch(event.event) {
         case DTMFDolphinEventStartDialer:
             sc_state = DTMFDolphinSceneStateDialer;
             break;
@@ -77,6 +71,9 @@ bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
         case DTMFDolphinEventStartRedboxUK:
             sc_state = DTMFDolphinSceneStateRedboxUK;
             break;
+        case DTMFDolphinEventStartRedboxCA:
+            sc_state = DTMFDolphinSceneStateRedboxCA;
+            break;
         case DTMFDolphinEventStartMisc:
             sc_state = DTMFDolphinSceneStateMisc;
             break;

+ 1 - 1
views/dtmf_dolphin_common.h

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

+ 70 - 72
views/dtmf_dolphin_dialer.c

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

+ 4 - 1
views/dtmf_dolphin_dialer.h

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