Explorar el Código

fix bugs, empty inst view, 32-bit timer for tracker engine, fixed clicks on stop/play

LTVA1 hace 3 años
padre
commit
8614f244c3

+ 2 - 0
README.md

@@ -1,2 +1,4 @@
 # flizzer_tracker
  A Flipper Zero chiptune tracker.
+
+CURRENT STATE: proof of concept. Works only on custom build of the firmware (tiny font not supported yet), you can't edit instruments; effects, vibrato and PWM are not implemented, as well as a lot of other things (saving/loading module, song loop points, instrument klystrack-like program, instrument editor, instrument/song name editing etc.)

+ 11 - 2
flizzer_tracker.c

@@ -3,6 +3,7 @@
 #include "input_event.h"
 #include "util.h"
 #include "view/pattern_editor.h"
+#include "view/instrument_editor.h"
 
 #define FLIZZER_TRACKER_FOLDER "/ext/flizzer_tracker"
 
@@ -58,6 +59,13 @@ static void draw_callback(Canvas *canvas, void *ctx)
             break;
         }
 
+        case INST_EDITOR_VIEW:
+        {
+            draw_instrument_view(canvas, tracker);
+            draw_instrument_program_view(canvas, tracker);
+            break;
+        }
+
         default:
             break;
     }
@@ -133,8 +141,7 @@ int32_t flizzer_tracker_app(void *p)
     view_dispatcher_add_view(tracker->view_dispatcher, 0, tracker->tracker_view->view);
     view_dispatcher_attach_to_gui(tracker->view_dispatcher, tracker->gui, ViewDispatcherTypeFullscreen);
 
-    with_view_model(
-        tracker->tracker_view->view, TrackerViewModel * model, { model->tracker = tracker; }, true);
+    with_view_model(tracker->tracker_view->view, TrackerViewModel * model, { model->tracker = tracker; }, true);
 
     view_dispatcher_switch_to_view(tracker->view_dispatcher, 0);
 
@@ -205,11 +212,13 @@ int32_t flizzer_tracker_app(void *p)
     tracker->song.instrument[0]->adsr.d = 0x9;
     tracker->song.instrument[0]->adsr.volume = 0x80;
     tracker->song.instrument[0]->waveform = SE_WAVEFORM_TRIANGLE;
+    tracker->song.instrument[0]->sound_engine_flags |= SE_ENABLE_KEYDOWN_SYNC;
 
     tracker->song.instrument[1]->adsr.a = 0x0;
     tracker->song.instrument[1]->adsr.d = 0x3;
     tracker->song.instrument[1]->adsr.volume = 0x18;
     tracker->song.instrument[1]->waveform = SE_WAVEFORM_NOISE;
+    tracker->song.instrument[1]->sound_engine_flags |= SE_ENABLE_KEYDOWN_SYNC;
 
     tracker->tracker_engine.playing = false;
     play();

+ 28 - 13
flizzer_tracker_hal.c

@@ -28,9 +28,9 @@ void sound_engine_dma_isr(void *ctx)
 
 void tracker_engine_timer_isr(void *ctx)
 {
-    if (LL_TIM_IsActiveFlag_UPDATE(TIM1))
+    if (LL_TIM_IsActiveFlag_UPDATE(TRACKER_ENGINE_TIMER))
     {
-        LL_TIM_ClearFlag_UPDATE(TIM1);
+        LL_TIM_ClearFlag_UPDATE(TRACKER_ENGINE_TIMER);
     }
 
     TrackerEngine *tracker_engine = (TrackerEngine *)ctx;
@@ -63,6 +63,9 @@ void sound_engine_PWM_timer_init(bool external_audio_output) // external audio o
         bool unu = furi_hal_speaker_acquire(1000);
         UNUSED(unu);
     }
+
+    LL_TIM_EnableAllOutputs(SPEAKER_PWM_TIMER);
+    LL_TIM_EnableCounter(SPEAKER_PWM_TIMER);
 }
 
 void sound_engine_timer_init(uint32_t sample_rate) // external audio on pin PA6
@@ -70,7 +73,7 @@ void sound_engine_timer_init(uint32_t sample_rate) // external audio on pin PA6
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
 
-    TIM_InitStruct.Prescaler = 0;
+    TIM_InitStruct.Prescaler = 0; 
     TIM_InitStruct.Autoreload = TIMER_BASE_CLOCK / sample_rate; // to support various sample rates
     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
     LL_TIM_Init(SAMPLE_RATE_TIMER, &TIM_InitStruct);
@@ -78,6 +81,8 @@ void sound_engine_timer_init(uint32_t sample_rate) // external audio on pin PA6
     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
     TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
     LL_TIM_OC_Init(SAMPLE_RATE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
+
+    LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER);
 }
 
 void tracker_engine_timer_init(uint8_t rate) // 0-255 hz
@@ -85,8 +90,8 @@ void tracker_engine_timer_init(uint8_t rate) // 0-255 hz
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
 
-    TIM_InitStruct.Prescaler = 976 - 1;                          // so with highest autoreload you get 1 Hz
-    TIM_InitStruct.Autoreload = (TIMER_BASE_CLOCK / 976) / rate; // to support various rates
+    TIM_InitStruct.Prescaler = 0; //using 32-bit timer
+    TIM_InitStruct.Autoreload = (uint32_t)TIMER_BASE_CLOCK / (uint32_t)rate; // to support various tracker engine rates
     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
     LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
 
@@ -97,6 +102,16 @@ void tracker_engine_timer_init(uint8_t rate) // 0-255 hz
     LL_TIM_EnableIT_UPDATE(TRACKER_ENGINE_TIMER);
 }
 
+void tracker_engine_set_rate(uint8_t rate)
+{
+    LL_TIM_InitTypeDef TIM_InitStruct = {0};
+
+    TIM_InitStruct.Prescaler = 0; //using 32-bit timer
+    TIM_InitStruct.Autoreload = (uint32_t)TIMER_BASE_CLOCK / (uint32_t)rate; // to support various tracker engine rates
+    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
+    LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
+}
+
 void tracker_engine_init_hardware(uint8_t rate)
 {
     tracker_engine_timer_init(rate);
@@ -109,7 +124,7 @@ void sound_engine_dma_init(uint32_t address, uint32_t size)
     LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
     LL_DMA_SetDataLength(DMA_INSTANCE, size);
 
-    LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM2_UP);
+    LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM1_UP);
     LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
     LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH);
     LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR);
@@ -142,24 +157,24 @@ void sound_engine_dma_stop()
 
 void sound_engine_start()
 {
-    LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER);
     LL_TIM_EnableCounter(SAMPLE_RATE_TIMER);
 
-    LL_TIM_EnableAllOutputs(SPEAKER_PWM_TIMER);
-    LL_TIM_EnableCounter(SPEAKER_PWM_TIMER);
-
     sound_engine_dma_start();
 }
 
 void sound_engine_stop()
 {
-    LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER);
     LL_TIM_DisableCounter(SAMPLE_RATE_TIMER);
 
+    sound_engine_dma_stop();
+}
+
+void sound_engine_deinit_timer()
+{
+    LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER);
     LL_TIM_DisableAllOutputs(SPEAKER_PWM_TIMER);
-    LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
 
-    sound_engine_dma_stop();
+    LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
 }
 
 void tracker_engine_start()

+ 4 - 2
flizzer_tracker_hal.h

@@ -12,8 +12,8 @@
 #include <furi_hal_resources.h>
 
 #define SPEAKER_PWM_TIMER TIM16
-#define SAMPLE_RATE_TIMER TIM2
-#define TRACKER_ENGINE_TIMER TIM1
+#define SAMPLE_RATE_TIMER TIM1
+#define TRACKER_ENGINE_TIMER TIM2
 
 #define SPEAKER_PWM_TIMER_CHANNEL LL_TIM_CHANNEL_CH1
 
@@ -25,9 +25,11 @@ void sound_engine_dma_isr(void *ctx);
 void tracker_engine_timer_isr(void *ctx);
 void sound_engine_init_hardware(uint32_t sample_rate, bool external_audio_output, uint16_t *audio_buffer, uint32_t audio_buffer_size);
 void tracker_engine_init_hardware(uint8_t rate);
+void tracker_engine_set_rate(uint8_t rate);
 void sound_engine_start();
 void sound_engine_stop();
 void stop();
 void play();
 void tracker_engine_stop();
+void sound_engine_deinit_timer();
 void tracker_engine_start();

BIN
images/checkbox_checked.png


BIN
images/checkbox_empty.png


BIN
images/unite_begin.png


BIN
images/unite_end.png


BIN
images/unite_mid.png


+ 7 - 0
input/instrument.c

@@ -0,0 +1,7 @@
+#include "instrument.h"
+
+void instrument_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
+{
+    UNUSED(tracker);
+    UNUSED(event);
+}

+ 12 - 0
input/instrument.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include <furi.h>
+#include <input/input.h>
+#include <stdio.h>
+
+#include "../flizzer_tracker.h"
+#include "../sound_engine/sound_engine_defs.h"
+#include "../tracker_engine/tracker_engine_defs.h"
+#include "../util.h"
+
+void instrument_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 7 - 0
input/instrument_program.c

@@ -0,0 +1,7 @@
+#include "instrument_program.h"
+
+void instrument_program_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
+{
+    UNUSED(tracker);
+    UNUSED(event);
+}

+ 12 - 0
input/instrument_program.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include <furi.h>
+#include <input/input.h>
+#include <stdio.h>
+
+#include "../flizzer_tracker.h"
+#include "../sound_engine/sound_engine_defs.h"
+#include "../tracker_engine/tracker_engine_defs.h"
+#include "../util.h"
+
+void instrument_program_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 20 - 0
input/pattern.c

@@ -20,6 +20,26 @@ void edit_note(FlizzerTrackerApp *tracker, TrackerSongPatternStep *step, int8_t
 {
     int16_t note = tracker_engine_get_note(step);
 
+    if(note == MUS_NOTE_RELEASE)
+    {
+        if(delta < 0)
+        {
+            set_note(step, MUS_NOTE_CUT);
+        }
+
+        return;
+    }
+
+    if(note == MUS_NOTE_CUT)
+    {
+        if(delta > 0)
+        {
+            set_note(step, MUS_NOTE_RELEASE);
+        }
+
+        return;
+    }
+
     if (note == MUS_NOTE_NONE)
     {
         note = tracker->current_note; // remember which note we entered earlier and use it as reference

+ 2 - 2
input/sequence.c

@@ -136,7 +136,7 @@ void sequence_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
         {
             tracker->tracker_engine.sequence_position++;
 
-            if (tracker->tracker_engine.sequence_position > tracker->tracker_engine.song->num_sequence_steps)
+            if (tracker->tracker_engine.sequence_position >= tracker->tracker_engine.song->num_sequence_steps)
             {
                 tracker->tracker_engine.sequence_position = 0;
             }
@@ -156,7 +156,7 @@ void sequence_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 
             if (temp_sequence_position < 0)
             {
-                tracker->tracker_engine.sequence_position = tracker->tracker_engine.song->num_sequence_steps;
+                tracker->tracker_engine.sequence_position = tracker->tracker_engine.song->num_sequence_steps - 1;
             }
 
             else

+ 50 - 4
input_event.c

@@ -12,6 +12,20 @@ void cycle_focus(FlizzerTrackerApp *tracker)
             {
                 tracker->focus = EDIT_PATTERN;
             }
+
+            break;
+        }
+
+        case INST_EDITOR_VIEW:
+        {
+            tracker->focus++;
+
+            if (tracker->focus > EDIT_PROGRAM)
+            {
+                tracker->focus = EDIT_INSTRUMENT;
+            }
+
+            break;
         }
 
         default:
@@ -19,14 +33,34 @@ void cycle_focus(FlizzerTrackerApp *tracker)
     }
 }
 
+void cycle_view(FlizzerTrackerApp *tracker)
+{
+    if (tracker->mode == PATTERN_VIEW)
+    {
+        tracker->mode = INST_EDITOR_VIEW;
+        tracker->focus = EDIT_INSTRUMENT;
+
+        return;
+    }
+
+    if (tracker->mode == INST_EDITOR_VIEW)
+    {
+        tracker->mode = PATTERN_VIEW;
+        tracker->focus = EDIT_PATTERN;
+
+        return;
+    }
+}
+
 void process_input_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 {
-    /*if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && event->period > 0 && event->period < 200)
+    if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && event->period > 0 && event->period < 300 && !(tracker->editing))
     {
-            cycle_focus(tracker);
-    }*/
+        cycle_view(tracker);
+        return;
+    }
 
-    if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && !(tracker->editing))
+    else if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && !(tracker->editing))
     {
         cycle_focus(tracker);
         return;
@@ -59,6 +93,18 @@ void process_input_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
             break;
         }
 
+        case EDIT_INSTRUMENT:
+        {
+            instrument_edit_event(tracker, event);
+            break;
+        }
+
+        case EDIT_PROGRAM:
+        {
+            instrument_program_edit_event(tracker, event);
+            break;
+        }
+
         default:
             break;
     }

+ 2 - 0
input_event.h

@@ -12,5 +12,7 @@
 #include "input/pattern.h"
 #include "input/sequence.h"
 #include "input/songinfo.h"
+#include "input/instrument.h"
+#include "input/instrument_program.h"
 
 void process_input_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 1 - 0
sound_engine/sound_engine.c

@@ -44,6 +44,7 @@ void sound_engine_deinit(SoundEngine *sound_engine)
 
     furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdDma1Ch1, 13, NULL, NULL);
     sound_engine_stop();
+    sound_engine_deinit_timer();
 }
 
 void sound_engine_set_channel_frequency(SoundEngine *sound_engine, SoundEngineChannel *channel, uint16_t note)

+ 1 - 1
sound_engine/sound_engine_adsr.c

@@ -61,5 +61,5 @@ int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine *eng, Soun
         }
     }
 
-    return (int32_t)((int64_t)input * (int64_t)adsr->envelope / (int64_t)MAX_ADSR * (int64_t)adsr->volume / (int64_t)MAX_ADSR_VOLUME);
+    return (int32_t)((int64_t)input * (int32_t)adsr->envelope / (int32_t)MAX_ADSR * (int32_t)adsr->volume / (int32_t)MAX_ADSR_VOLUME);
 }

+ 2 - 2
tracker_engine/tracker_engine.c

@@ -6,7 +6,7 @@
 
 void tracker_engine_init(TrackerEngine *tracker_engine, uint8_t rate, SoundEngine *sound_engine)
 {
-    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 14, tracker_engine_timer_isr, (void *)tracker_engine);
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTIM2, 14, tracker_engine_timer_isr, (void *)tracker_engine);
     tracker_engine_init_hardware(rate);
 
     tracker_engine->sound_engine = sound_engine;
@@ -41,7 +41,7 @@ void tracker_engine_deinit(TrackerEngine *tracker_engine, bool free_song)
 {
     tracker_engine_deinit_song(tracker_engine->song, free_song);
 
-    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 13, NULL, NULL);
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTIM2, 13, NULL, NULL);
     tracker_engine_stop();
 }
 

+ 2 - 0
util.c

@@ -41,6 +41,8 @@ void play_song(FlizzerTrackerApp *tracker, bool from_cursor)
         tracker->tracker_engine.pattern_position = 0;
     }
 
+    tracker_engine_set_rate(tracker->song.rate);
+
     play();
 }
 

+ 14 - 0
view/instrument_editor.c

@@ -0,0 +1,14 @@
+#include "instrument_editor.h"
+
+void draw_instrument_view(Canvas *canvas, FlizzerTrackerApp *tracker)
+{
+    canvas_draw_line(canvas, 0, 0, 10, 10);
+    UNUSED(canvas);
+    UNUSED(tracker);
+}
+
+void draw_instrument_program_view(Canvas *canvas, FlizzerTrackerApp *tracker)
+{
+    UNUSED(canvas);
+    UNUSED(tracker);
+}

+ 10 - 0
view/instrument_editor.h

@@ -0,0 +1,10 @@
+#pragma once
+
+#include "../flizzer_tracker.h"
+#include "../tracker_engine/tracker_engine_defs.h"
+
+#include <furi.h>
+#include <gui/gui.h>
+
+void draw_instrument_view(Canvas *canvas, FlizzerTrackerApp *tracker);
+void draw_instrument_program_view(Canvas *canvas, FlizzerTrackerApp *tracker);

+ 2 - 0
view/pattern_editor.c

@@ -27,11 +27,13 @@ char *notename(uint8_t note)
     if (note == MUS_NOTE_CUT)
     {
         snprintf(buffer, sizeof(buffer), "%s", "OFF");
+        return buffer;
     }
 
     if (note == MUS_NOTE_RELEASE)
     {
         snprintf(buffer, sizeof(buffer), "   ");
+        return buffer;
     }
 
     else