LTVA1 3 лет назад
Родитель
Сommit
762c8fb964

+ 185 - 183
flizzer_tracker.c

@@ -1,7 +1,7 @@
 #include "flizzer_tracker.h"
 #include "init_deinit.h"
-#include "util.h"
 #include "input_event.h"
+#include "util.h"
 #include "view/pattern_editor.h"
 
 #define FLIZZER_TRACKER_FOLDER "/ext/flizzer_tracker"
@@ -10,95 +10,96 @@
 
 /*
 Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1
-Copyright: 
+Copyright:
 Glyphs: 95/203
 BBX Build Mode: 0
 */
 const uint8_t u8g2_font_tom_thumb_4x6_tr[725] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_tr") =
-	"_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310"
-	"\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1"
-	"&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244"
-	"\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60"
-	"\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227"
-	"\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227"
-	"\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32"
-	"d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3"
-	"\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0"
-	"E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12"
-	"I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227"
-	"\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310"
-	"Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$"
-	"W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U"
-	"V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^"
-	"\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7"
-	"\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35"
-	"\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T"
-	"\1l\7\227\310\310\326\0m\7\223\310<R\0n\7\223\310\250d\5o\7\223\310U\252\2p\10\227"
-	"\307\250\244V\4q\10\227\307-\225d\0r\6\223\310\315\22s\10\223\310\215\70\22\0t\10\227\310\245"
-	"\25\243\0u\7\223\310$+\11v\10\223\310$\65R\2w\7\223\310\244q\4x\7\223\310\244\62\25"
-	"y\11\227\307$\225dJ\0z\7\223\310\254\221\6{\10\227\310\251\32D\1|\6\265\310(\1}\11"
-	"\227\310\310\14RR\0~\6\213\313\215\4\0\0\0\4\377\377\0";
-
-static void draw_callback(Canvas* canvas, void* ctx) 
+    "_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310"
+    "\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1"
+    "&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244"
+    "\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60"
+    "\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227"
+    "\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227"
+    "\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32"
+    "d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3"
+    "\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0"
+    "E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12"
+    "I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227"
+    "\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310"
+    "Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$"
+    "W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U"
+    "V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^"
+    "\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7"
+    "\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35"
+    "\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T"
+    "\1l\7\227\310\310\326\0m\7\223\310<R\0n\7\223\310\250d\5o\7\223\310U\252\2p\10\227"
+    "\307\250\244V\4q\10\227\307-\225d\0r\6\223\310\315\22s\10\223\310\215\70\22\0t\10\227\310\245"
+    "\25\243\0u\7\223\310$+\11v\10\223\310$\65R\2w\7\223\310\244q\4x\7\223\310\244\62\25"
+    "y\11\227\307$\225dJ\0z\7\223\310\254\221\6{\10\227\310\251\32D\1|\6\265\310(\1}\11"
+    "\227\310\310\14RR\0~\6\213\313\215\4\0\0\0\4\377\377\0";
+
+static void draw_callback(Canvas *canvas, void *ctx)
 {
-	TrackerViewModel* model = (TrackerViewModel*)ctx;
-	FlizzerTrackerApp* tracker = (FlizzerTrackerApp*)(model->tracker);
-
-	canvas_set_color(canvas, ColorXOR);
-
-	canvas_set_custom_font(canvas, u8g2_font_tom_thumb_4x6_tr);
-
-	switch(tracker->mode)
-	{
-		case PATTERN_VIEW:
-		{
-			draw_songinfo_view(canvas, tracker);
-			draw_sequence_view(canvas, tracker);
-			draw_pattern_view(canvas, tracker);
-			break;
-		}
-
-		default: break;
-	}
+    TrackerViewModel *model = (TrackerViewModel *)ctx;
+    FlizzerTrackerApp *tracker = (FlizzerTrackerApp *)(model->tracker);
+
+    canvas_set_color(canvas, ColorXOR);
+
+    canvas_set_custom_font(canvas, u8g2_font_tom_thumb_4x6_tr);
+
+    switch (tracker->mode)
+    {
+        case PATTERN_VIEW:
+        {
+            draw_songinfo_view(canvas, tracker);
+            draw_sequence_view(canvas, tracker);
+            draw_pattern_view(canvas, tracker);
+            break;
+        }
+
+        default:
+            break;
+    }
 }
 
-static bool input_callback(InputEvent* input_event, void* ctx) 
+static bool input_callback(InputEvent *input_event, void *ctx)
 {
-	// Проверяем, что контекст не нулевой
-	furi_assert(ctx);
-	TrackerView* tracker_view = (TrackerView*)ctx;
-	FlizzerTrackerApp* tracker = (FlizzerTrackerApp*)(tracker_view->context);
+    // Проверяем, что контекст не нулевой
+    furi_assert(ctx);
+    TrackerView *tracker_view = (TrackerView *)ctx;
+    FlizzerTrackerApp *tracker = (FlizzerTrackerApp *)(tracker_view->context);
 
-	bool consumed = false;
+    bool consumed = false;
 
-	if(input_event->key == InputKeyBack && input_event->type == InputTypeShort)
-	{
-		tracker->period = furi_get_tick() - tracker->current_time;
-		tracker->current_time = furi_get_tick();
+    if (input_event->key == InputKeyBack && input_event->type == InputTypeShort)
+    {
+        tracker->period = furi_get_tick() - tracker->current_time;
+        tracker->current_time = furi_get_tick();
 
-		tracker->was_it_back_keypress = true;
-	}
+        tracker->was_it_back_keypress = true;
+    }
 
-	else if(input_event->type == InputTypeShort || input_event->type == InputTypeLong)
-	{
-		tracker->was_it_back_keypress = false;
-		tracker->period = 0;
-	}
+    else if (input_event->type == InputTypeShort || input_event->type == InputTypeLong)
+    {
+        tracker->was_it_back_keypress = false;
+        tracker->period = 0;
+    }
 
-	uint32_t final_period = (tracker->was_it_back_keypress ? tracker->period : 0);
+    uint32_t final_period = (tracker->was_it_back_keypress ? tracker->period : 0);
 
-	FlizzerTrackerEvent event = {.type = EventTypeInput, .input = *input_event, .period = final_period};
-	furi_message_queue_put(tracker->event_queue, &event, FuriWaitForever);
+    FlizzerTrackerEvent event = {.type = EventTypeInput, .input = *input_event, .period = final_period};
+    furi_message_queue_put(tracker->event_queue, &event, FuriWaitForever);
 
-	consumed = true;
-	return consumed;
+    consumed = true;
+    return consumed;
 }
 
-TrackerView* tracker_view_alloc(FlizzerTrackerApp* tracker)
+TrackerView *tracker_view_alloc(FlizzerTrackerApp *tracker)
 {
-    TrackerView* tracker_view = malloc(sizeof(TrackerView));
+    TrackerView *tracker_view = malloc(sizeof(TrackerView));
     tracker_view->view = view_alloc();
-	tracker_view->context = tracker;
+    tracker_view->context = tracker;
     view_set_context(tracker_view->view, tracker_view);
     view_allocate_model(tracker_view->view, ViewModelTypeLocking, sizeof(TrackerViewModel));
     view_set_draw_callback(tracker_view->view, draw_callback);
@@ -107,139 +108,140 @@ TrackerView* tracker_view_alloc(FlizzerTrackerApp* tracker)
     return tracker_view;
 }
 
-void tracker_view_free(TrackerView* tracker_view)
+void tracker_view_free(TrackerView *tracker_view)
 {
     furi_assert(tracker_view);
     view_free(tracker_view->view);
     free(tracker_view);
 }
 
-int32_t flizzer_tracker_app(void* p) 
+int32_t flizzer_tracker_app(void *p)
 {
-	UNUSED(p);
+    UNUSED(p);
 
-	FlizzerTrackerApp* tracker = init_tracker(44100, 50, false, 1024);
+    FlizzerTrackerApp *tracker = init_tracker(44100, 50, false, 1024);
 
-	// Текущее событие типа кастомного типа FlizzerTrackerEvent
-	FlizzerTrackerEvent event;
-	// Очередь событий на 8 элементов размера FlizzerTrackerEvent
-	tracker->event_queue = furi_message_queue_alloc(8, sizeof(FlizzerTrackerEvent));
+    // Текущее событие типа кастомного типа FlizzerTrackerEvent
+    FlizzerTrackerEvent event;
+    // Очередь событий на 8 элементов размера FlizzerTrackerEvent
+    tracker->event_queue = furi_message_queue_alloc(8, sizeof(FlizzerTrackerEvent));
 
-	tracker->gui = furi_record_open(RECORD_GUI);
+    tracker->gui = furi_record_open(RECORD_GUI);
     tracker->view_dispatcher = view_dispatcher_alloc();
     tracker->tracker_view = tracker_view_alloc(tracker);
 
     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);
 
-	tracker->notification = furi_record_open(RECORD_NOTIFICATION);
-	notification_message(tracker->notification, &sequence_display_backlight_enforce_on);
-
-	tracker->tracker_engine.master_volume = 0x80;
-
-	tracker->song.speed = 5;
-	tracker->song.rate = tracker->tracker_engine.rate;
-	tracker->song.num_instruments = 2;
-	tracker->song.num_patterns = 3;
-	tracker->song.num_sequence_steps = 4;
-	tracker->song.pattern_length = 64;
-
-	tracker->song.sequence.sequence_step[0].pattern_indices[0] = 0;
-	tracker->song.sequence.sequence_step[0].pattern_indices[1] = 1;
-	tracker->song.sequence.sequence_step[0].pattern_indices[2] = 2;
-	tracker->song.sequence.sequence_step[0].pattern_indices[3] = 2;
-
-	tracker->song.pattern[0].step = malloc(64 * sizeof(TrackerSongPatternStep));
-	tracker->song.pattern[1].step = malloc(64 * sizeof(TrackerSongPatternStep));
-	tracker->song.pattern[2].step = malloc(64 * sizeof(TrackerSongPatternStep));
-
-	memset(tracker->song.pattern[0].step, 0, 64 * sizeof(TrackerSongPatternStep));
-	memset(tracker->song.pattern[1].step, 0, 64 * sizeof(TrackerSongPatternStep));
-	memset(tracker->song.pattern[2].step, 0, 64 * sizeof(TrackerSongPatternStep));
-
-	tracker->song.instrument[0] = malloc(sizeof(Instrument));
-	tracker->song.instrument[1] = malloc(sizeof(Instrument));
-
-	for(int i = 0; i < 64; ++i)
-	{
-		set_note(&tracker->song.pattern[0].step[i], MUS_NOTE_NONE);
-		set_note(&tracker->song.pattern[1].step[i], MUS_NOTE_NONE);
-		set_note(&tracker->song.pattern[2].step[i], MUS_NOTE_NONE);
-
-		set_instrument(&tracker->song.pattern[0].step[i], MUS_NOTE_INSTRUMENT_NONE);
-		set_instrument(&tracker->song.pattern[1].step[i], MUS_NOTE_INSTRUMENT_NONE);
-		set_instrument(&tracker->song.pattern[2].step[i], MUS_NOTE_INSTRUMENT_NONE);
-
-		set_volume(&tracker->song.pattern[0].step[i], MUS_NOTE_VOLUME_NONE);
-		set_volume(&tracker->song.pattern[1].step[i], MUS_NOTE_VOLUME_NONE);
-		set_volume(&tracker->song.pattern[2].step[i], MUS_NOTE_VOLUME_NONE);
-	}
-
-	for(int i = 0; i < 64; i += 8)
-	{
-		set_note(&tracker->song.pattern[0].step[0 + i], 12 * 5);
-		set_note(&tracker->song.pattern[0].step[2 + i], 12 * 5 + 2);
-		set_note(&tracker->song.pattern[0].step[4 + i], 12 * 5 - 2);
-		set_note(&tracker->song.pattern[0].step[6 + i], 12 * 5 + 4);
-
-		set_instrument(&tracker->song.pattern[0].step[0 + i], 0);
-		set_instrument(&tracker->song.pattern[0].step[2 + i], 0);
-		set_instrument(&tracker->song.pattern[0].step[4 + i], 0);
-		set_instrument(&tracker->song.pattern[0].step[6 + i], 0);
-	}
-
-	for(int i = 0; i < 64; i++)
-	{
-		set_note(&tracker->song.pattern[1].step[i], 12 * 7 + 11);
-
-		set_instrument(&tracker->song.pattern[1].step[i], 1);
-	}
-
-	tracker->song.instrument[0]->adsr.a = 0x2;
-	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[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->tracker_engine.playing = false;
-	play();
-
-	// Бесконечный цикл обработки очереди событий
-	while(!(tracker->quit)) 
-	{
-		// Выбираем событие из очереди в переменную event (ждём бесконечно долго, если очередь пуста)
-		// и проверяем, что у нас получилось это сделать
-		furi_check(furi_message_queue_get(tracker->event_queue, &event, FuriWaitForever) == FuriStatusOk);
-
-		// Наше событие — это нажатие кнопки
-		if(event.type == EventTypeInput) 
-		{
-			process_input_event(tracker, &event);
-		}
-	}
-
-	stop();
-
-	notification_message(tracker->notification, &sequence_display_backlight_enforce_auto);
-	furi_record_close(RECORD_NOTIFICATION);
-
-	// Специальная очистка памяти, занимаемой очередью
-	furi_message_queue_free(tracker->event_queue);
-
-	view_dispatcher_remove_view(tracker->view_dispatcher, 0);
+    tracker->notification = furi_record_open(RECORD_NOTIFICATION);
+    notification_message(tracker->notification, &sequence_display_backlight_enforce_on);
+
+    tracker->tracker_engine.master_volume = 0x80;
+
+    tracker->song.speed = 5;
+    tracker->song.rate = tracker->tracker_engine.rate;
+    tracker->song.num_instruments = 2;
+    tracker->song.num_patterns = 3;
+    tracker->song.num_sequence_steps = 4;
+    tracker->song.pattern_length = 64;
+
+    tracker->song.sequence.sequence_step[0].pattern_indices[0] = 0;
+    tracker->song.sequence.sequence_step[0].pattern_indices[1] = 1;
+    tracker->song.sequence.sequence_step[0].pattern_indices[2] = 2;
+    tracker->song.sequence.sequence_step[0].pattern_indices[3] = 2;
+
+    tracker->song.pattern[0].step = malloc(64 * sizeof(TrackerSongPatternStep));
+    tracker->song.pattern[1].step = malloc(64 * sizeof(TrackerSongPatternStep));
+    tracker->song.pattern[2].step = malloc(64 * sizeof(TrackerSongPatternStep));
+
+    memset(tracker->song.pattern[0].step, 0, 64 * sizeof(TrackerSongPatternStep));
+    memset(tracker->song.pattern[1].step, 0, 64 * sizeof(TrackerSongPatternStep));
+    memset(tracker->song.pattern[2].step, 0, 64 * sizeof(TrackerSongPatternStep));
+
+    tracker->song.instrument[0] = malloc(sizeof(Instrument));
+    tracker->song.instrument[1] = malloc(sizeof(Instrument));
+
+    for (int i = 0; i < 64; ++i)
+    {
+        set_note(&tracker->song.pattern[0].step[i], MUS_NOTE_NONE);
+        set_note(&tracker->song.pattern[1].step[i], MUS_NOTE_NONE);
+        set_note(&tracker->song.pattern[2].step[i], MUS_NOTE_NONE);
+
+        set_instrument(&tracker->song.pattern[0].step[i], MUS_NOTE_INSTRUMENT_NONE);
+        set_instrument(&tracker->song.pattern[1].step[i], MUS_NOTE_INSTRUMENT_NONE);
+        set_instrument(&tracker->song.pattern[2].step[i], MUS_NOTE_INSTRUMENT_NONE);
+
+        set_volume(&tracker->song.pattern[0].step[i], MUS_NOTE_VOLUME_NONE);
+        set_volume(&tracker->song.pattern[1].step[i], MUS_NOTE_VOLUME_NONE);
+        set_volume(&tracker->song.pattern[2].step[i], MUS_NOTE_VOLUME_NONE);
+    }
+
+    for (int i = 0; i < 64; i += 8)
+    {
+        set_note(&tracker->song.pattern[0].step[0 + i], 12 * 5);
+        set_note(&tracker->song.pattern[0].step[2 + i], 12 * 5 + 2);
+        set_note(&tracker->song.pattern[0].step[4 + i], 12 * 5 - 2);
+        set_note(&tracker->song.pattern[0].step[6 + i], 12 * 5 + 4);
+
+        set_instrument(&tracker->song.pattern[0].step[0 + i], 0);
+        set_instrument(&tracker->song.pattern[0].step[2 + i], 0);
+        set_instrument(&tracker->song.pattern[0].step[4 + i], 0);
+        set_instrument(&tracker->song.pattern[0].step[6 + i], 0);
+    }
+
+    for (int i = 0; i < 64; i++)
+    {
+        set_note(&tracker->song.pattern[1].step[i], 12 * 7 + 11);
+
+        set_instrument(&tracker->song.pattern[1].step[i], 1);
+    }
+
+    tracker->song.instrument[0]->adsr.a = 0x2;
+    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[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->tracker_engine.playing = false;
+    play();
+
+    // Бесконечный цикл обработки очереди событий
+    while (!(tracker->quit))
+    {
+        // Выбираем событие из очереди в переменную event (ждём бесконечно долго, если очередь пуста)
+        // и проверяем, что у нас получилось это сделать
+        furi_check(furi_message_queue_get(tracker->event_queue, &event, FuriWaitForever) == FuriStatusOk);
+
+        // Наше событие — это нажатие кнопки
+        if (event.type == EventTypeInput)
+        {
+            process_input_event(tracker, &event);
+        }
+    }
+
+    stop();
+
+    notification_message(tracker->notification, &sequence_display_backlight_enforce_auto);
+    furi_record_close(RECORD_NOTIFICATION);
+
+    // Специальная очистка памяти, занимаемой очередью
+    furi_message_queue_free(tracker->event_queue);
+
+    view_dispatcher_remove_view(tracker->view_dispatcher, 0);
     view_dispatcher_free(tracker->view_dispatcher);
     tracker_view_free(tracker->tracker_view);
-	furi_record_close(RECORD_GUI);
+    furi_record_close(RECORD_GUI);
 
-	deinit_tracker(tracker);
+    deinit_tracker(tracker);
 
-	return 0;
+    return 0;
 }

+ 47 - 47
flizzer_tracker.h

@@ -1,19 +1,19 @@
 #pragma once
 
-#include <notification/notification_messages.h>
-#include <stdio.h>
+#include <cli/cli.h>
 #include <furi.h>
 #include <gui/gui.h>
-#include <cli/cli.h>
 #include <input/input.h>
+#include <notification/notification_messages.h>
+#include <stdio.h>
 #include <u8g2_glue.h>
 
 #include <gui/view_dispatcher.h>
 
 #include "flizzer_tracker_hal.h"
 #include "sound_engine/freqs.h"
-#include "sound_engine/sound_engine_filter.h"
 #include "sound_engine/sound_engine_defs.h"
+#include "sound_engine/sound_engine_filter.h"
 #include "tracker_engine/tracker_engine_defs.h"
 
 #define MIDDLE_C (12 * 4)
@@ -21,79 +21,79 @@
 
 typedef enum
 {
-	EventTypeInput,
+    EventTypeInput,
 } EventType;
 
 typedef struct
 {
-	EventType type;
-	InputEvent input;
-	uint32_t period;
+    EventType type;
+    InputEvent input;
+    uint32_t period;
 } FlizzerTrackerEvent;
 
 typedef enum
 {
-	PATTERN_VIEW,
-	INST_EDITOR_VIEW,
-	EXPORT_WAV_VIEW,
+    PATTERN_VIEW,
+    INST_EDITOR_VIEW,
+    EXPORT_WAV_VIEW,
 } TrackerMode;
 
 typedef enum
 {
-	EDIT_PATTERN,
-	EDIT_SEQUENCE,
-	EDIT_SONGINFO,
-	EDIT_INSTRUMENT,
-	EDIT_PROGRAM,
+    EDIT_PATTERN,
+    EDIT_SEQUENCE,
+    EDIT_SONGINFO,
+    EDIT_INSTRUMENT,
+    EDIT_PROGRAM,
 } TrackerFocus;
 
 typedef enum
 {
-	SI_PATTERNPOS,
-	SI_SEQUENCEPOS,
-	SI_SONGSPEED,
-	SI_SONGRATE,
-	SI_MASTERVOL,
-
-	SI_SONGNAME,
-	SI_INSTRUMENTNAME,
-	/* ========  */
-	SI_PARAMS,
+    SI_PATTERNPOS,
+    SI_SEQUENCEPOS,
+    SI_SONGSPEED,
+    SI_SONGRATE,
+    SI_MASTERVOL,
+
+    SI_SONGNAME,
+    SI_INSTRUMENTNAME,
+    /* ========  */
+    SI_PARAMS,
 } SongInfoParam;
 
 typedef struct
 {
-    View* view;
-    void* context;
+    View *view;
+    void *context;
 } TrackerView;
 
-typedef struct 
+typedef struct
 {
-	NotificationApp* notification;
-	FuriMessageQueue* event_queue;
-	Gui* gui;
-	TrackerView* tracker_view;
-	ViewDispatcher* view_dispatcher;
-	bool was_it_back_keypress;
-	uint32_t current_time;
-	uint32_t period;
+    NotificationApp *notification;
+    FuriMessageQueue *event_queue;
+    Gui *gui;
+    TrackerView *tracker_view;
+    ViewDispatcher *view_dispatcher;
+    bool was_it_back_keypress;
+    uint32_t current_time;
+    uint32_t period;
 
-	SoundEngine sound_engine;
-	TrackerEngine tracker_engine;
+    SoundEngine sound_engine;
+    TrackerEngine tracker_engine;
 
-	TrackerSong song;
+    TrackerSong song;
 
-	uint8_t selected_param;
+    uint8_t selected_param;
 
-	uint8_t mode, focus;
-	uint8_t patternx, current_channel, current_digit, program_step, current_instrument, current_note;
-	bool editing;
-	bool was_editing;
+    uint8_t mode, focus;
+    uint8_t patternx, current_channel, current_digit, program_step, current_instrument, current_note;
+    bool editing;
+    bool was_editing;
 
-	bool quit;
+    bool quit;
 } FlizzerTrackerApp;
 
 typedef struct
 {
-	FlizzerTrackerApp* tracker;
+    FlizzerTrackerApp *tracker;
 } TrackerViewModel;

+ 110 - 110
flizzer_tracker_hal.c

@@ -1,187 +1,187 @@
 #include "flizzer_tracker_hal.h"
 #include "flizzer_tracker.h"
 
-void sound_engine_dma_isr(void* ctx)
-{
-	SoundEngine* sound_engine = (SoundEngine*)ctx;
-
-	// half of transfer
-	if(LL_DMA_IsActiveFlag_HT1(DMA1))
-	{
-		LL_DMA_ClearFlag_HT1(DMA1);
-		// fill first half of buffer
-		uint16_t* audio_buffer = sound_engine->audio_buffer;
-		uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
-		sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
-	}
-
-	// transfer complete
-	if(LL_DMA_IsActiveFlag_TC1(DMA1))
-	{
-		LL_DMA_ClearFlag_TC1(DMA1);
-		// fill second half of buffer
-		uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
-		uint16_t* audio_buffer = &sound_engine->audio_buffer[audio_buffer_length];
-		sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
-	}
+void sound_engine_dma_isr(void *ctx)
+{
+    SoundEngine *sound_engine = (SoundEngine *)ctx;
+
+    // half of transfer
+    if (LL_DMA_IsActiveFlag_HT1(DMA1))
+    {
+        LL_DMA_ClearFlag_HT1(DMA1);
+        // fill first half of buffer
+        uint16_t *audio_buffer = sound_engine->audio_buffer;
+        uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
+        sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
+    }
+
+    // transfer complete
+    if (LL_DMA_IsActiveFlag_TC1(DMA1))
+    {
+        LL_DMA_ClearFlag_TC1(DMA1);
+        // fill second half of buffer
+        uint32_t audio_buffer_length = sound_engine->audio_buffer_size / 2;
+        uint16_t *audio_buffer = &sound_engine->audio_buffer[audio_buffer_length];
+        sound_engine_fill_buffer(sound_engine, audio_buffer, audio_buffer_length);
+    }
 }
 
-void tracker_engine_timer_isr(void* ctx)
+void tracker_engine_timer_isr(void *ctx)
 {
-	if(LL_TIM_IsActiveFlag_UPDATE(TIM1)) 
-	{
-		LL_TIM_ClearFlag_UPDATE(TIM1);
-	}
+    if (LL_TIM_IsActiveFlag_UPDATE(TIM1))
+    {
+        LL_TIM_ClearFlag_UPDATE(TIM1);
+    }
 
-	TrackerEngine* tracker_engine = (TrackerEngine*)ctx;
+    TrackerEngine *tracker_engine = (TrackerEngine *)ctx;
 
-	tracker_engine_advance_tick(tracker_engine);
+    tracker_engine_advance_tick(tracker_engine);
 }
 
-void sound_engine_PWM_timer_init(bool external_audio_output) //external audio on pin PA6
+void sound_engine_PWM_timer_init(bool external_audio_output) // external audio on pin PA6
 {
-	LL_TIM_InitTypeDef TIM_InitStruct = {0};
-	LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
+    LL_TIM_InitTypeDef TIM_InitStruct = {0};
+    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
 
-	TIM_InitStruct.Prescaler = 0;
-	TIM_InitStruct.Autoreload = 1023; //10-bit PWM resolution at around 60 kHz PWM rate
-	TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
-	LL_TIM_Init(SPEAKER_PWM_TIMER, &TIM_InitStruct);
+    TIM_InitStruct.Prescaler = 0;
+    TIM_InitStruct.Autoreload = 1023; // 10-bit PWM resolution at around 60 kHz PWM rate
+    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
+    LL_TIM_Init(SPEAKER_PWM_TIMER, &TIM_InitStruct);
 
-	TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
-	TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
-	TIM_OC_InitStruct.CompareValue = 0;
-	LL_TIM_OC_Init(SPEAKER_PWM_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
+    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
+    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
+    TIM_OC_InitStruct.CompareValue = 0;
+    LL_TIM_OC_Init(SPEAKER_PWM_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
 
-	if(external_audio_output)
-	{
-		furi_hal_gpio_init_ex(&gpio_ext_pa6, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
-	}
+    if (external_audio_output)
+    {
+        furi_hal_gpio_init_ex(&gpio_ext_pa6, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
+    }
 
-	else
-	{
-		bool unu = furi_hal_speaker_acquire(1000);
-		UNUSED(unu);
-	}
+    else
+    {
+        bool unu = furi_hal_speaker_acquire(1000);
+        UNUSED(unu);
+    }
 }
 
-void sound_engine_timer_init(uint32_t sample_rate) //external audio on pin PA6
+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};
+    LL_TIM_InitTypeDef TIM_InitStruct = {0};
+    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {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);
+    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);
 
-	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);
+    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);
 }
 
-void tracker_engine_timer_init(uint8_t rate) //0-255 hz
+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};
+    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.CounterMode = LL_TIM_COUNTERMODE_UP;
-	LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
+    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.CounterMode = LL_TIM_COUNTERMODE_UP;
+    LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
 
-	TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
-	TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
-	LL_TIM_OC_Init(TRACKER_ENGINE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
+    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
+    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
+    LL_TIM_OC_Init(TRACKER_ENGINE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
 
-	LL_TIM_EnableIT_UPDATE(TRACKER_ENGINE_TIMER);
+    LL_TIM_EnableIT_UPDATE(TRACKER_ENGINE_TIMER);
 }
 
 void tracker_engine_init_hardware(uint8_t rate)
 {
-	tracker_engine_timer_init(rate);
+    tracker_engine_timer_init(rate);
 }
 
 void sound_engine_dma_init(uint32_t address, uint32_t size)
 {
-	uint32_t dma_dst = (uint32_t) & (SPEAKER_PWM_TIMER->CCR1);
+    uint32_t dma_dst = (uint32_t) & (SPEAKER_PWM_TIMER->CCR1);
 
-	LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
-	LL_DMA_SetDataLength(DMA_INSTANCE, 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_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);
-	LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT);
-	LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT);
-	LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD);
-	LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD);
+    LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM2_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);
+    LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT);
+    LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT);
+    LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD);
+    LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD);
 
-	LL_DMA_EnableIT_TC(DMA_INSTANCE);
-	LL_DMA_EnableIT_HT(DMA_INSTANCE);
+    LL_DMA_EnableIT_TC(DMA_INSTANCE);
+    LL_DMA_EnableIT_HT(DMA_INSTANCE);
 }
 
-void sound_engine_init_hardware(uint32_t sample_rate, bool external_audio_output, uint16_t* audio_buffer, uint32_t audio_buffer_size)
+void sound_engine_init_hardware(uint32_t sample_rate, bool external_audio_output, uint16_t *audio_buffer, uint32_t audio_buffer_size)
 {
-	sound_engine_dma_init((uint32_t)audio_buffer, audio_buffer_size);
-	sound_engine_timer_init(sample_rate);
-	sound_engine_PWM_timer_init(external_audio_output);
+    sound_engine_dma_init((uint32_t)audio_buffer, audio_buffer_size);
+    sound_engine_timer_init(sample_rate);
+    sound_engine_PWM_timer_init(external_audio_output);
 }
 
 void sound_engine_dma_start()
 {
-	LL_DMA_EnableChannel(DMA_INSTANCE);
-	LL_TIM_EnableDMAReq_UPDATE(SAMPLE_RATE_TIMER);
+    LL_DMA_EnableChannel(DMA_INSTANCE);
+    LL_TIM_EnableDMAReq_UPDATE(SAMPLE_RATE_TIMER);
 }
 
 void sound_engine_dma_stop()
 {
-	LL_DMA_DisableChannel(DMA_INSTANCE);
+    LL_DMA_DisableChannel(DMA_INSTANCE);
 }
 
 void sound_engine_start()
 {
-	LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER);
-	LL_TIM_EnableCounter(SAMPLE_RATE_TIMER);
+    LL_TIM_EnableAllOutputs(SAMPLE_RATE_TIMER);
+    LL_TIM_EnableCounter(SAMPLE_RATE_TIMER);
 
-	LL_TIM_EnableAllOutputs(SPEAKER_PWM_TIMER);
-	LL_TIM_EnableCounter(SPEAKER_PWM_TIMER);
+    LL_TIM_EnableAllOutputs(SPEAKER_PWM_TIMER);
+    LL_TIM_EnableCounter(SPEAKER_PWM_TIMER);
 
-	sound_engine_dma_start();
+    sound_engine_dma_start();
 }
 
 void sound_engine_stop()
 {
-	LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER);
-	LL_TIM_DisableCounter(SAMPLE_RATE_TIMER);
+    LL_TIM_DisableAllOutputs(SAMPLE_RATE_TIMER);
+    LL_TIM_DisableCounter(SAMPLE_RATE_TIMER);
 
-	LL_TIM_DisableAllOutputs(SPEAKER_PWM_TIMER);
-	LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
+    LL_TIM_DisableAllOutputs(SPEAKER_PWM_TIMER);
+    LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
 
-	sound_engine_dma_stop();
+    sound_engine_dma_stop();
 }
 
 void tracker_engine_start()
 {
-	LL_TIM_EnableAllOutputs(TRACKER_ENGINE_TIMER);
-	LL_TIM_EnableCounter(TRACKER_ENGINE_TIMER);
+    LL_TIM_EnableAllOutputs(TRACKER_ENGINE_TIMER);
+    LL_TIM_EnableCounter(TRACKER_ENGINE_TIMER);
 }
 
 void tracker_engine_stop()
 {
-	LL_TIM_DisableAllOutputs(TRACKER_ENGINE_TIMER);
-	LL_TIM_DisableCounter(TRACKER_ENGINE_TIMER);
+    LL_TIM_DisableAllOutputs(TRACKER_ENGINE_TIMER);
+    LL_TIM_DisableCounter(TRACKER_ENGINE_TIMER);
 }
 
 void play()
 {
-	tracker_engine_start();
-	sound_engine_start();
+    tracker_engine_start();
+    sound_engine_start();
 }
 
 void stop()
 {
-	sound_engine_stop();
-	tracker_engine_stop();
+    sound_engine_stop();
+    tracker_engine_stop();
 }

+ 4 - 4
flizzer_tracker_hal.h

@@ -3,9 +3,9 @@
 #include "sound_engine/sound_engine.h"
 #include "tracker_engine/tracker_engine.h"
 
-#include <stm32wbxx_ll_tim.h>
 #include <stm32wbxx_ll_dma.h>
 #include <stm32wbxx_ll_gpio.h>
+#include <stm32wbxx_ll_tim.h>
 
 #include <furi_hal.h>
 #include <furi_hal_gpio.h>
@@ -21,9 +21,9 @@
 
 #define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1
 
-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 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 sound_engine_start();
 void sound_engine_stop();

+ 17 - 17
init_deinit.c

@@ -1,30 +1,30 @@
 #include "init_deinit.h"
 
-FlizzerTrackerApp* init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size)
+FlizzerTrackerApp *init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size)
 {
-	FlizzerTrackerApp* tracker = malloc(sizeof(FlizzerTrackerApp));
-	memset(tracker, 0, sizeof(FlizzerTrackerApp));
+    FlizzerTrackerApp *tracker = malloc(sizeof(FlizzerTrackerApp));
+    memset(tracker, 0, sizeof(FlizzerTrackerApp));
 
-	sound_engine_init(&tracker->sound_engine, sample_rate, external_audio_output, audio_buffer_size);
-	tracker_engine_init(&tracker->tracker_engine, rate, &tracker->sound_engine);
+    sound_engine_init(&tracker->sound_engine, sample_rate, external_audio_output, audio_buffer_size);
+    tracker_engine_init(&tracker->tracker_engine, rate, &tracker->sound_engine);
 
-	tracker->tracker_engine.song = &tracker->song;
+    tracker->tracker_engine.song = &tracker->song;
 
-	tracker->current_note = MIDDLE_C;
+    tracker->current_note = MIDDLE_C;
 
-	return tracker;
+    return tracker;
 }
 
-void deinit_tracker(FlizzerTrackerApp* tracker)
+void deinit_tracker(FlizzerTrackerApp *tracker)
 {
-	sound_engine_deinit(&tracker->sound_engine);
-	tracker_engine_deinit(&tracker->tracker_engine, false);
+    sound_engine_deinit(&tracker->sound_engine);
+    tracker_engine_deinit(&tracker->tracker_engine, false);
 
-	FURI_CRITICAL_ENTER();
-	LL_TIM_DeInit(TRACKER_ENGINE_TIMER);
-	LL_TIM_DeInit(SAMPLE_RATE_TIMER);
-	LL_TIM_DeInit(SPEAKER_PWM_TIMER);
-	FURI_CRITICAL_EXIT();
+    FURI_CRITICAL_ENTER();
+    LL_TIM_DeInit(TRACKER_ENGINE_TIMER);
+    LL_TIM_DeInit(SAMPLE_RATE_TIMER);
+    LL_TIM_DeInit(SPEAKER_PWM_TIMER);
+    FURI_CRITICAL_EXIT();
 
-	free(tracker);
+    free(tracker);
 }

+ 3 - 3
init_deinit.h

@@ -1,7 +1,7 @@
 #pragma once
 
-#include "flizzer_tracker_hal.h"
 #include "flizzer_tracker.h"
+#include "flizzer_tracker_hal.h"
 
-FlizzerTrackerApp* init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size);
-void deinit_tracker(FlizzerTrackerApp* tracker);
+FlizzerTrackerApp *init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size);
+void deinit_tracker(FlizzerTrackerApp *tracker);

+ 333 - 322
input/pattern.c

@@ -2,384 +2,395 @@
 
 uint8_t get_field(uint8_t patternx)
 {
-	uint8_t field = 0;
-
-	if(patternx <= 1) field = 0;
-	if(patternx == 2) field = 1;
-	if(patternx == 3) field = 2;
-	if(patternx > 3) field = 3;
-
-	return field;
+    uint8_t field = 0;
+
+    if (patternx <= 1)
+        field = 0;
+    if (patternx == 2)
+        field = 1;
+    if (patternx == 3)
+        field = 2;
+    if (patternx > 3)
+        field = 3;
+
+    return field;
 }
 
-void edit_note(FlizzerTrackerApp* tracker, TrackerSongPatternStep* step, int8_t delta) //here we need data about last note if we place a new note
+void edit_note(FlizzerTrackerApp *tracker, TrackerSongPatternStep *step, int8_t delta) // here we need data about last note if we place a new note
 {
-	int16_t note = tracker_engine_get_note(step);
+    int16_t note = tracker_engine_get_note(step);
 
-	if(note == MUS_NOTE_NONE)
-	{
-		note = tracker->current_note; //remember which note we entered earlier and use it as reference
-	}
+    if (note == MUS_NOTE_NONE)
+    {
+        note = tracker->current_note; // remember which note we entered earlier and use it as reference
+    }
 
-	clamp(note, delta, 0, MAX_NOTE);
+    clamp(note, delta, 0, MAX_NOTE);
 
-	set_note(step, (uint8_t)note);
+    set_note(step, (uint8_t)note);
 
-	tracker->current_note = (uint8_t)note;
+    tracker->current_note = (uint8_t)note;
 }
 
-void edit_instrument(TrackerSongPatternStep* step, int8_t delta)
+void edit_instrument(TrackerSongPatternStep *step, int8_t delta)
 {
-	int16_t inst = tracker_engine_get_instrument(step);
+    int16_t inst = tracker_engine_get_instrument(step);
 
-	if(inst == MUS_NOTE_INSTRUMENT_NONE)
-	{
-		if(delta > 0)
-		{
-			inst = 0;
-		}
+    if (inst == MUS_NOTE_INSTRUMENT_NONE)
+    {
+        if (delta > 0)
+        {
+            inst = 0;
+        }
 
-		else
-		{
-			inst = MUS_NOTE_INSTRUMENT_NONE - 1;
-		}
-	}
+        else
+        {
+            inst = MUS_NOTE_INSTRUMENT_NONE - 1;
+        }
+    }
 
-	clamp(inst, delta, 0, MUS_NOTE_INSTRUMENT_NONE - 1);
+    clamp(inst, delta, 0, MUS_NOTE_INSTRUMENT_NONE - 1);
 
-	set_instrument(step, (uint8_t)inst);
+    set_instrument(step, (uint8_t)inst);
 }
 
-void edit_volume(TrackerSongPatternStep* step, int8_t delta)
+void edit_volume(TrackerSongPatternStep *step, int8_t delta)
 {
-	int16_t vol = tracker_engine_get_volume(step);
+    int16_t vol = tracker_engine_get_volume(step);
 
-	if(vol == MUS_NOTE_VOLUME_NONE)
-	{
-		if(delta > 0)
-		{
-			vol = 0;
-		}
+    if (vol == MUS_NOTE_VOLUME_NONE)
+    {
+        if (delta > 0)
+        {
+            vol = 0;
+        }
 
-		else
-		{
-			vol = MUS_NOTE_VOLUME_NONE - 1;
-		}
-	}
+        else
+        {
+            vol = MUS_NOTE_VOLUME_NONE - 1;
+        }
+    }
 
-	clamp(vol, delta, 0, MUS_NOTE_VOLUME_NONE - 1);
+    clamp(vol, delta, 0, MUS_NOTE_VOLUME_NONE - 1);
 
-	set_volume(step, (uint8_t)vol);
+    set_volume(step, (uint8_t)vol);
 }
 
-void edit_command(TrackerSongPatternStep* step, uint8_t digit, int8_t delta)
+void edit_command(TrackerSongPatternStep *step, uint8_t digit, int8_t delta)
 {
-	int32_t command = tracker_engine_get_command(step);
+    int32_t command = tracker_engine_get_command(step);
 
-	switch(digit)
-	{
-		case 0: //upper 7 bits
-		{
-			int16_t fx_name = ((command & 0x7f00) >> 8);
+    switch (digit)
+    {
+        case 0: // upper 7 bits
+        {
+            int16_t fx_name = ((command & 0x7f00) >> 8);
 
-			if(fx_name + delta > 35) //loop
-			{                        //0-9 and then A-Z
-				fx_name = 0;
-			}
+            if (fx_name + delta > 35) // loop
+            {                         // 0-9 and then A-Z
+                fx_name = 0;
+            }
 
-			else if(fx_name + delta < 0)
-			{
-				fx_name = 35;
-			}
+            else if (fx_name + delta < 0)
+            {
+                fx_name = 35;
+            }
 
-			else
-			{
-				fx_name += delta;
-			}
+            else
+            {
+                fx_name += delta;
+            }
 
-			command &= 0x00ff;
+            command &= 0x00ff;
 
-			command |= (fx_name << 8);
+            command |= (fx_name << 8);
 
-			set_command(step, (uint16_t)command);
+            set_command(step, (uint16_t)command);
 
-			break;
-		}
+            break;
+        }
 
-		case 1: //upper digit of command param
-		{
-			int8_t upper_digit = ((command & 0x00f0) >> 4);
+        case 1: // upper digit of command param
+        {
+            int8_t upper_digit = ((command & 0x00f0) >> 4);
 
-			if(upper_digit + delta > 0xf) //loop
-			{
-				upper_digit = 0;
-			}
+            if (upper_digit + delta > 0xf) // loop
+            {
+                upper_digit = 0;
+            }
 
-			else if(upper_digit + delta < 0)
-			{
-				upper_digit = 0xf;
-			}
+            else if (upper_digit + delta < 0)
+            {
+                upper_digit = 0xf;
+            }
 
-			else
-			{
-				upper_digit += delta;
-			}
+            else
+            {
+                upper_digit += delta;
+            }
 
-			command &= 0xff0f;
+            command &= 0xff0f;
 
-			command |= (upper_digit << 4);
+            command |= (upper_digit << 4);
 
-			set_command(step, (uint16_t)command);
+            set_command(step, (uint16_t)command);
 
-			break;
-		}
+            break;
+        }
 
-		case 2: //lower digit of command param
-		{
-			int8_t lower_digit = (command & 0x000f);
+        case 2: // lower digit of command param
+        {
+            int8_t lower_digit = (command & 0x000f);
 
-			if(lower_digit + delta > 0xf) //loop
-			{
-				lower_digit = 0;
-			}
+            if (lower_digit + delta > 0xf) // loop
+            {
+                lower_digit = 0;
+            }
 
-			else if(lower_digit + delta < 0)
-			{
-				lower_digit = 0xf;
-			}
+            else if (lower_digit + delta < 0)
+            {
+                lower_digit = 0xf;
+            }
 
-			else
-			{
-				lower_digit += delta;
-			}
+            else
+            {
+                lower_digit += delta;
+            }
 
-			command &= 0xfff0;
+            command &= 0xfff0;
 
-			command |= lower_digit;
+            command |= lower_digit;
 
-			set_command(step, (uint16_t)command);
+            set_command(step, (uint16_t)command);
 
-			break;
-		}
+            break;
+        }
 
-		default: break;
-	}
+        default:
+            break;
+    }
 }
 
-void delete_field(TrackerSongPatternStep* step, uint8_t field)
+void delete_field(TrackerSongPatternStep *step, uint8_t field)
 {
-	switch(field)
-	{
-		case 0: //note
-		{
-			set_note(step, MUS_NOTE_NONE);
-			break;
-		}
-
-		case 1: //instrument
-		{
-			set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
-			break;
-		}
-
-		case 2: //volume
-		{
-			set_volume(step, MUS_NOTE_VOLUME_NONE);
-			break;
-		}
-
-		case 3: //command
-		{
-			set_command(step, 0);
-			break;
-		}
-
-		default: break;
-	}
+    switch (field)
+    {
+        case 0: // note
+        {
+            set_note(step, MUS_NOTE_NONE);
+            break;
+        }
+
+        case 1: // instrument
+        {
+            set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
+            break;
+        }
+
+        case 2: // volume
+        {
+            set_volume(step, MUS_NOTE_VOLUME_NONE);
+            break;
+        }
+
+        case 3: // command
+        {
+            set_command(step, 0);
+            break;
+        }
+
+        default:
+            break;
+    }
 }
 
-void edit_pattern_step(FlizzerTrackerApp* tracker, TrackerSongPatternStep* step, int8_t delta)
+void edit_pattern_step(FlizzerTrackerApp *tracker, TrackerSongPatternStep *step, int8_t delta)
 {
-	switch(get_field(tracker->patternx))
-	{
-		case 0: //note
-		{
-			if(tracker->patternx) //editing octave
-			{
-				edit_note(tracker, step, 12 * delta);
-			}
-
-			else //editing note
-			{
-				edit_note(tracker, step, delta);
-			}
-
-			break;
-		}
-
-		case 1: //instrument
-		{
-			edit_instrument(step, delta);
-			break;
-		}
-
-		case 2: //volume
-		{
-			edit_volume(step, delta);
-			break;
-		}
-
-		case 3: //command
-		{
-			uint8_t digit = 0;
-			if(tracker->patternx == 4) digit = 0;
-			if(tracker->patternx == 5) digit = 1;
-			if(tracker->patternx == 6) digit = 2;
-			edit_command(step, digit, delta);
-			break;
-		}
-
-		default: break;
-	}
+    switch (get_field(tracker->patternx))
+    {
+        case 0: // note
+        {
+            if (tracker->patternx) // editing octave
+            {
+                edit_note(tracker, step, 12 * delta);
+            }
+
+            else // editing note
+            {
+                edit_note(tracker, step, delta);
+            }
+
+            break;
+        }
+
+        case 1: // instrument
+        {
+            edit_instrument(step, delta);
+            break;
+        }
+
+        case 2: // volume
+        {
+            edit_volume(step, delta);
+            break;
+        }
+
+        case 3: // command
+        {
+            uint8_t digit = 0;
+            if (tracker->patternx == 4)
+                digit = 0;
+            if (tracker->patternx == 5)
+                digit = 1;
+            if (tracker->patternx == 6)
+                digit = 2;
+            edit_command(step, digit, delta);
+            break;
+        }
+
+        default:
+            break;
+    }
 }
 
-void pattern_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event)
+void pattern_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 {
-	uint8_t sequence_position = tracker->tracker_engine.sequence_position;
-	uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
-	uint8_t pattern_step = tracker->tracker_engine.pattern_position;
-
-	uint8_t pattern_length = tracker->tracker_engine.song->pattern_length;
-
-	TrackerSongPattern* pattern = &tracker->tracker_engine.song->pattern[current_pattern];
-
-	TrackerSongPatternStep* step = NULL;
-
-	if(pattern_step < pattern_length)
-	{
-		step = &pattern->step[pattern_step];
-	}
-
-	if(!(step)) return;
-
-	if(event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
-	{
-		tracker->editing = !tracker->editing;
-	}
-
-	if(event->input.key == InputKeyOk && event->input.type == InputTypeLong)
-	{
-		if(!(tracker->editing))
-		{
-			if(tracker->tracker_engine.playing)
-			{
-				stop_song(tracker);
-			}
-
-			else
-			{
-				play_song(tracker, true);
-			}
-		}
-
-		else
-		{
-			if(get_field(tracker->patternx) == 0)
-			{
-				set_note(step, MUS_NOTE_RELEASE);
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->patternx++;
-
-		if(tracker->patternx > MAX_PATTERNX - 1)
-		{
-			tracker->current_channel++;
-
-			tracker->patternx = 0;
-
-			if(tracker->current_channel > SONG_MAX_CHANNELS - 1)
-			{
-				tracker->current_channel = 0;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->patternx--;
-
-		if(tracker->patternx > MAX_PATTERNX - 1) //unsigned int overflow
-		{
-			tracker->current_channel--;
-
-			tracker->patternx = MAX_PATTERNX - 1;
-
-			if(tracker->current_channel > SONG_MAX_CHANNELS - 1) //unsigned int overflow
-			{
-				tracker->current_channel = SONG_MAX_CHANNELS - 1;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyDown && event->input.type == InputTypeShort)
-	{
-		if(!(tracker->editing))
-		{
-			tracker->tracker_engine.pattern_position++;
-
-			if(tracker->tracker_engine.pattern_position > tracker->tracker_engine.song->pattern_length - 1 && tracker->tracker_engine.sequence_position < tracker->tracker_engine.song->num_sequence_steps - 1)
-			{
-				tracker->tracker_engine.pattern_position = 0;
-				tracker->tracker_engine.sequence_position++;
-			}
-
-			else if(tracker->tracker_engine.pattern_position > tracker->tracker_engine.song->pattern_length - 1)
-			{
-				tracker->tracker_engine.pattern_position = tracker->tracker_engine.song->pattern_length - 1;
-			}
-		}
-
-		if(tracker->editing)
-		{
-			edit_pattern_step(tracker, step, -1);
-		}
-	}
-
-	if(event->input.key == InputKeyUp && event->input.type == InputTypeShort)
-	{
-		if(!(tracker->editing))
-		{
-			int16_t temp_pattern_position = tracker->tracker_engine.pattern_position - 1;
-
-			if(temp_pattern_position < 0)
-			{
-				if(tracker->tracker_engine.sequence_position > 0)
-				{
-					tracker->tracker_engine.sequence_position--;
-					tracker->tracker_engine.pattern_position = tracker->tracker_engine.song->pattern_length - 1;
-				}
-			}
-
-			else
-			{
-				tracker->tracker_engine.pattern_position--;
-			}
-		}
-
-		if(tracker->editing)
-		{
-			edit_pattern_step(tracker, step, 1);
-		}
-	}
-
-	if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && tracker->editing)
-	{
-		uint8_t field = get_field(tracker->patternx);
-
-		delete_field(step, field);
-	}
+    uint8_t sequence_position = tracker->tracker_engine.sequence_position;
+    uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
+    uint8_t pattern_step = tracker->tracker_engine.pattern_position;
+
+    uint8_t pattern_length = tracker->tracker_engine.song->pattern_length;
+
+    TrackerSongPattern *pattern = &tracker->tracker_engine.song->pattern[current_pattern];
+
+    TrackerSongPatternStep *step = NULL;
+
+    if (pattern_step < pattern_length)
+    {
+        step = &pattern->step[pattern_step];
+    }
+
+    if (!(step))
+        return;
+
+    if (event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
+    {
+        tracker->editing = !tracker->editing;
+    }
+
+    if (event->input.key == InputKeyOk && event->input.type == InputTypeLong)
+    {
+        if (!(tracker->editing))
+        {
+            if (tracker->tracker_engine.playing)
+            {
+                stop_song(tracker);
+            }
+
+            else
+            {
+                play_song(tracker, true);
+            }
+        }
+
+        else
+        {
+            if (get_field(tracker->patternx) == 0)
+            {
+                set_note(step, MUS_NOTE_RELEASE);
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->patternx++;
+
+        if (tracker->patternx > MAX_PATTERNX - 1)
+        {
+            tracker->current_channel++;
+
+            tracker->patternx = 0;
+
+            if (tracker->current_channel > SONG_MAX_CHANNELS - 1)
+            {
+                tracker->current_channel = 0;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->patternx--;
+
+        if (tracker->patternx > MAX_PATTERNX - 1) // unsigned int overflow
+        {
+            tracker->current_channel--;
+
+            tracker->patternx = MAX_PATTERNX - 1;
+
+            if (tracker->current_channel > SONG_MAX_CHANNELS - 1) // unsigned int overflow
+            {
+                tracker->current_channel = SONG_MAX_CHANNELS - 1;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyDown && event->input.type == InputTypeShort)
+    {
+        if (!(tracker->editing))
+        {
+            tracker->tracker_engine.pattern_position++;
+
+            if (tracker->tracker_engine.pattern_position > tracker->tracker_engine.song->pattern_length - 1 && tracker->tracker_engine.sequence_position < tracker->tracker_engine.song->num_sequence_steps - 1)
+            {
+                tracker->tracker_engine.pattern_position = 0;
+                tracker->tracker_engine.sequence_position++;
+            }
+
+            else if (tracker->tracker_engine.pattern_position > tracker->tracker_engine.song->pattern_length - 1)
+            {
+                tracker->tracker_engine.pattern_position = tracker->tracker_engine.song->pattern_length - 1;
+            }
+        }
+
+        if (tracker->editing)
+        {
+            edit_pattern_step(tracker, step, -1);
+        }
+    }
+
+    if (event->input.key == InputKeyUp && event->input.type == InputTypeShort)
+    {
+        if (!(tracker->editing))
+        {
+            int16_t temp_pattern_position = tracker->tracker_engine.pattern_position - 1;
+
+            if (temp_pattern_position < 0)
+            {
+                if (tracker->tracker_engine.sequence_position > 0)
+                {
+                    tracker->tracker_engine.sequence_position--;
+                    tracker->tracker_engine.pattern_position = tracker->tracker_engine.song->pattern_length - 1;
+                }
+            }
+
+            else
+            {
+                tracker->tracker_engine.pattern_position--;
+            }
+        }
+
+        if (tracker->editing)
+        {
+            edit_pattern_step(tracker, step, 1);
+        }
+    }
+
+    if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && tracker->editing)
+    {
+        uint8_t field = get_field(tracker->patternx);
+
+        delete_field(step, field);
+    }
 }

+ 3 - 3
input/pattern.h

@@ -1,14 +1,14 @@
 #pragma once
 
-#include <stdio.h>
 #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 "../flizzer_tracker.h"
 #include "../util.h"
 
 #define MAX_PATTERNX (2 + 1 + 1 + 3)
 
-void pattern_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event);
+void pattern_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 168 - 168
input/sequence.c

@@ -1,178 +1,178 @@
 #include "sequence.h"
 
-void delete_sequence_step(FlizzerTrackerApp* tracker)
+void delete_sequence_step(FlizzerTrackerApp *tracker)
 {
-	uint8_t sequence_position = tracker->tracker_engine.sequence_position;
-	uint8_t* pattern = &tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
-	*pattern = 0;
+    uint8_t sequence_position = tracker->tracker_engine.sequence_position;
+    uint8_t *pattern = &tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
+    *pattern = 0;
 }
 
-void edit_sequence_step(FlizzerTrackerApp* tracker, int8_t delta)
+void edit_sequence_step(FlizzerTrackerApp *tracker, int8_t delta)
 {
-	uint8_t digit = tracker->current_digit;
-
-	uint8_t sequence_position = tracker->tracker_engine.sequence_position;
-	uint8_t pattern_index = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
-
-	uint8_t* pattern = &tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
-	uint8_t temp_pattern = *pattern;
-
-	switch(digit)
-	{
-		case 0: //upper nibble
-		{
-			int8_t nibble = ((pattern_index & 0xf0) >> 4);
-
-			if(nibble + delta < 0)
-			{
-				nibble = 0xf;
-			}
-
-			else if(nibble + delta > 0xf)
-			{
-				nibble = 0;
-			}
-
-			else
-			{
-				nibble += delta;
-			}
-
-			temp_pattern &= 0xf0;
-			temp_pattern |= (nibble << 4);
-
-			break;
-		}
-
-		case 1: //lower nibble
-		{
-			int8_t nibble = (pattern_index & 0x0f);
-
-			if(nibble + delta < 0)
-			{
-				nibble = 0xf;
-			}
-
-			else if(nibble + delta > 0xf)
-			{
-				nibble = 0;
-			}
-
-			else
-			{
-				nibble += delta;
-			}
-
-			temp_pattern &= 0xf0;
-			temp_pattern |= nibble;
-
-			break;
-		}
-	}
-
-	if(check_and_allocate_pattern(&tracker->song, temp_pattern))
-	{
-		*pattern = temp_pattern;
-	}
+    uint8_t digit = tracker->current_digit;
+
+    uint8_t sequence_position = tracker->tracker_engine.sequence_position;
+    uint8_t pattern_index = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
+
+    uint8_t *pattern = &tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[tracker->current_channel];
+    uint8_t temp_pattern = *pattern;
+
+    switch (digit)
+    {
+        case 0: // upper nibble
+        {
+            int8_t nibble = ((pattern_index & 0xf0) >> 4);
+
+            if (nibble + delta < 0)
+            {
+                nibble = 0xf;
+            }
+
+            else if (nibble + delta > 0xf)
+            {
+                nibble = 0;
+            }
+
+            else
+            {
+                nibble += delta;
+            }
+
+            temp_pattern &= 0xf0;
+            temp_pattern |= (nibble << 4);
+
+            break;
+        }
+
+        case 1: // lower nibble
+        {
+            int8_t nibble = (pattern_index & 0x0f);
+
+            if (nibble + delta < 0)
+            {
+                nibble = 0xf;
+            }
+
+            else if (nibble + delta > 0xf)
+            {
+                nibble = 0;
+            }
+
+            else
+            {
+                nibble += delta;
+            }
+
+            temp_pattern &= 0xf0;
+            temp_pattern |= nibble;
+
+            break;
+        }
+    }
+
+    if (check_and_allocate_pattern(&tracker->song, temp_pattern))
+    {
+        *pattern = temp_pattern;
+    }
 }
 
-void sequence_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event)
+void sequence_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 {
-	if(event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
-	{
-		tracker->editing = !tracker->editing;
-	}
-
-	/*if(event->input.key == InputKeyOk && event->input.type == InputTypeLong)
-	{
-		if(tracker->tracker_engine.playing)
-		{
-			stop_song(tracker);
-		}
-
-		else
-		{
-			play_song(tracker, true);
-		}
-	}*/
-
-	if(event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->current_digit++;
-
-		if(tracker->current_digit > 1)
-		{
-			tracker->current_channel++;
-
-			tracker->current_digit = 0;
-
-			if(tracker->current_channel > SONG_MAX_CHANNELS - 1)
-			{
-				tracker->current_channel = 0;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->current_digit--;
-
-		if(tracker->current_digit > 1) //unsigned int overflow
-		{
-			tracker->current_channel--;
-
-			tracker->current_digit = 1;
-
-			if(tracker->current_channel > SONG_MAX_CHANNELS - 1) //unsigned int overflow
-			{
-				tracker->current_channel = SONG_MAX_CHANNELS - 1;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyDown && event->input.type == InputTypeShort)
-	{
-		if(!(tracker->editing))
-		{
-			tracker->tracker_engine.sequence_position++;
-
-			if(tracker->tracker_engine.sequence_position > tracker->tracker_engine.song->num_sequence_steps)
-			{
-				tracker->tracker_engine.sequence_position = 0;
-			}
-		}
-
-		if(tracker->editing)
-		{
-			edit_sequence_step(tracker, -1);
-		}
-	}
-
-	if(event->input.key == InputKeyUp && event->input.type == InputTypeShort)
-	{
-		if(!(tracker->editing))
-		{
-			int16_t temp_sequence_position = tracker->tracker_engine.sequence_position - 1;
-
-			if(temp_sequence_position < 0)
-			{
-				tracker->tracker_engine.sequence_position = tracker->tracker_engine.song->num_sequence_steps;
-			}
-
-			else
-			{
-				tracker->tracker_engine.sequence_position--;
-			}
-		}
-
-		if(tracker->editing)
-		{
-			edit_sequence_step(tracker, 1);
-		}
-	}
-
-	if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && tracker->editing)
-	{
-		delete_sequence_step(tracker);
-	}
+    if (event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
+    {
+        tracker->editing = !tracker->editing;
+    }
+
+    /*if(event->input.key == InputKeyOk && event->input.type == InputTypeLong)
+    {
+            if(tracker->tracker_engine.playing)
+            {
+                    stop_song(tracker);
+            }
+
+            else
+            {
+                    play_song(tracker, true);
+            }
+    }*/
+
+    if (event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->current_digit++;
+
+        if (tracker->current_digit > 1)
+        {
+            tracker->current_channel++;
+
+            tracker->current_digit = 0;
+
+            if (tracker->current_channel > SONG_MAX_CHANNELS - 1)
+            {
+                tracker->current_channel = 0;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->current_digit--;
+
+        if (tracker->current_digit > 1) // unsigned int overflow
+        {
+            tracker->current_channel--;
+
+            tracker->current_digit = 1;
+
+            if (tracker->current_channel > SONG_MAX_CHANNELS - 1) // unsigned int overflow
+            {
+                tracker->current_channel = SONG_MAX_CHANNELS - 1;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyDown && event->input.type == InputTypeShort)
+    {
+        if (!(tracker->editing))
+        {
+            tracker->tracker_engine.sequence_position++;
+
+            if (tracker->tracker_engine.sequence_position > tracker->tracker_engine.song->num_sequence_steps)
+            {
+                tracker->tracker_engine.sequence_position = 0;
+            }
+        }
+
+        if (tracker->editing)
+        {
+            edit_sequence_step(tracker, -1);
+        }
+    }
+
+    if (event->input.key == InputKeyUp && event->input.type == InputTypeShort)
+    {
+        if (!(tracker->editing))
+        {
+            int16_t temp_sequence_position = tracker->tracker_engine.sequence_position - 1;
+
+            if (temp_sequence_position < 0)
+            {
+                tracker->tracker_engine.sequence_position = tracker->tracker_engine.song->num_sequence_steps;
+            }
+
+            else
+            {
+                tracker->tracker_engine.sequence_position--;
+            }
+        }
+
+        if (tracker->editing)
+        {
+            edit_sequence_step(tracker, 1);
+        }
+    }
+
+    if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && tracker->editing)
+    {
+        delete_sequence_step(tracker);
+    }
 }

+ 3 - 3
input/sequence.h

@@ -1,12 +1,12 @@
 #pragma once
 
-#include <stdio.h>
 #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 "../flizzer_tracker.h"
 #include "../util.h"
 
-void sequence_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event);
+void sequence_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 121 - 120
input/songinfo.c

@@ -2,128 +2,129 @@
 
 #include <gui/modules/text_input.h>
 
-void edit_songinfo_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta)
+void edit_songinfo_param(FlizzerTrackerApp *tracker, uint8_t selected_param, int8_t delta)
 {
-	if(!(tracker->current_digit))
-	{
-		delta *= 16;
-	}
-
-	switch(selected_param)
-	{
-		case SI_PATTERNPOS:
-		{
-			if((int16_t)tracker->song.pattern_length + (int16_t)delta > 1 && (int16_t)tracker->song.pattern_length + (int16_t)delta <= 0xff)
-			{
-				tracker->song.pattern_length += delta;
-			}
-
-			break;
-		}
-
-		case SI_SEQUENCEPOS:
-		{
-			if((int16_t)tracker->song.num_sequence_steps + (int16_t)delta > 1 && (int16_t)tracker->song.num_sequence_steps + (int16_t)delta <= 0xff)
-			{
-				tracker->song.num_sequence_steps += delta;
-			}
-
-			break;
-		}
-
-		case SI_SONGSPEED:
-		{
-			if((int16_t)tracker->song.speed + (int16_t)delta > 1 && (int16_t)tracker->song.speed + (int16_t)delta <= 0xff)
-			{
-				tracker->song.speed += delta;
-			}
-
-			break;
-		}
-
-		case SI_SONGRATE:
-		{
-			if((int16_t)tracker->song.rate + (int16_t)delta > 1 && (int16_t)tracker->song.rate + (int16_t)delta <= 0xff)
-			{
-				tracker->song.rate += delta;
-			}
-
-			break;
-		}
-
-		case SI_MASTERVOL:
-		{
-			if((int16_t)tracker->tracker_engine.master_volume + (int16_t)delta > 0 && (int16_t)tracker->tracker_engine.master_volume + (int16_t)delta <= 0xff)
-			{
-				tracker->tracker_engine.master_volume += delta;
-			}
-
-			break;
-		}
-
-		case SI_SONGNAME:
-		{
-			break;
-		}
-
-		default: break;
-	}
+    if (!(tracker->current_digit))
+    {
+        delta *= 16;
+    }
+
+    switch (selected_param)
+    {
+        case SI_PATTERNPOS:
+        {
+            if ((int16_t)tracker->song.pattern_length + (int16_t)delta > 1 && (int16_t)tracker->song.pattern_length + (int16_t)delta <= 0xff)
+            {
+                tracker->song.pattern_length += delta;
+            }
+
+            break;
+        }
+
+        case SI_SEQUENCEPOS:
+        {
+            if ((int16_t)tracker->song.num_sequence_steps + (int16_t)delta > 1 && (int16_t)tracker->song.num_sequence_steps + (int16_t)delta <= 0xff)
+            {
+                tracker->song.num_sequence_steps += delta;
+            }
+
+            break;
+        }
+
+        case SI_SONGSPEED:
+        {
+            if ((int16_t)tracker->song.speed + (int16_t)delta > 1 && (int16_t)tracker->song.speed + (int16_t)delta <= 0xff)
+            {
+                tracker->song.speed += delta;
+            }
+
+            break;
+        }
+
+        case SI_SONGRATE:
+        {
+            if ((int16_t)tracker->song.rate + (int16_t)delta > 1 && (int16_t)tracker->song.rate + (int16_t)delta <= 0xff)
+            {
+                tracker->song.rate += delta;
+            }
+
+            break;
+        }
+
+        case SI_MASTERVOL:
+        {
+            if ((int16_t)tracker->tracker_engine.master_volume + (int16_t)delta > 0 && (int16_t)tracker->tracker_engine.master_volume + (int16_t)delta <= 0xff)
+            {
+                tracker->tracker_engine.master_volume += delta;
+            }
+
+            break;
+        }
+
+        case SI_SONGNAME:
+        {
+            break;
+        }
+
+        default:
+            break;
+    }
 }
 
-void songinfo_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event)
+void songinfo_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 {
-	if(event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
-	{
-		tracker->editing = !tracker->editing;
-	}
-
-	if(event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->current_digit++;
-
-		if(tracker->current_digit > 1)
-		{
-			tracker->selected_param++;
-
-			tracker->current_digit = 0;
-
-			if(tracker->selected_param > SI_PARAMS - 1)
-			{
-				tracker->selected_param = 0;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
-	{
-		tracker->current_digit--;
-
-		if(tracker->current_digit > 1) //unsigned int overflow
-		{
-			tracker->selected_param--;
-
-			tracker->current_digit = 1;
-
-			if(tracker->selected_param > SI_PARAMS - 1) //unsigned int overflow
-			{
-				tracker->selected_param = SI_PARAMS - 1;
-			}
-		}
-	}
-
-	if(event->input.key == InputKeyDown && event->input.type == InputTypeShort)
-	{
-		if(tracker->editing)
-		{
-			edit_songinfo_param(tracker, tracker->selected_param, -1);
-		}
-	}
-
-	if(event->input.key == InputKeyUp && event->input.type == InputTypeShort)
-	{
-		if(tracker->editing)
-		{
-			edit_songinfo_param(tracker, tracker->selected_param, 1);
-		}
-	}
+    if (event->input.key == InputKeyOk && event->input.type == InputTypeShort && !tracker->tracker_engine.playing)
+    {
+        tracker->editing = !tracker->editing;
+    }
+
+    if (event->input.key == InputKeyRight && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->current_digit++;
+
+        if (tracker->current_digit > 1)
+        {
+            tracker->selected_param++;
+
+            tracker->current_digit = 0;
+
+            if (tracker->selected_param > SI_PARAMS - 1)
+            {
+                tracker->selected_param = 0;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyLeft && event->input.type == InputTypeShort && tracker->editing)
+    {
+        tracker->current_digit--;
+
+        if (tracker->current_digit > 1) // unsigned int overflow
+        {
+            tracker->selected_param--;
+
+            tracker->current_digit = 1;
+
+            if (tracker->selected_param > SI_PARAMS - 1) // unsigned int overflow
+            {
+                tracker->selected_param = SI_PARAMS - 1;
+            }
+        }
+    }
+
+    if (event->input.key == InputKeyDown && event->input.type == InputTypeShort)
+    {
+        if (tracker->editing)
+        {
+            edit_songinfo_param(tracker, tracker->selected_param, -1);
+        }
+    }
+
+    if (event->input.key == InputKeyUp && event->input.type == InputTypeShort)
+    {
+        if (tracker->editing)
+        {
+            edit_songinfo_param(tracker, tracker->selected_param, 1);
+        }
+    }
 }

+ 3 - 3
input/songinfo.h

@@ -1,12 +1,12 @@
 #pragma once
 
-#include <stdio.h>
 #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 "../flizzer_tracker.h"
 #include "../util.h"
 
-void songinfo_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event);
+void songinfo_edit_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 58 - 56
input_event.c

@@ -1,63 +1,65 @@
 #include "input_event.h"
 
-void cycle_focus(FlizzerTrackerApp* tracker)
+void cycle_focus(FlizzerTrackerApp *tracker)
 {
-	switch(tracker->mode)
-	{
-		case PATTERN_VIEW:
-		{
-			tracker->focus++;
-
-			if(tracker->focus > EDIT_SONGINFO)
-			{
-				tracker->focus = EDIT_PATTERN;
-			}
-		}
-
-		default: break;
-	}
+    switch (tracker->mode)
+    {
+        case PATTERN_VIEW:
+        {
+            tracker->focus++;
+
+            if (tracker->focus > EDIT_SONGINFO)
+            {
+                tracker->focus = EDIT_PATTERN;
+            }
+        }
+
+        default:
+            break;
+    }
 }
 
-void process_input_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event)
+void process_input_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event)
 {
-	/*if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && event->period > 0 && event->period < 200) 
-	{
-		cycle_focus(tracker);
-	}*/
-
-	if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && !(tracker->editing)) 
-	{
-		cycle_focus(tracker);
-		return;
-	}
-
-	// Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
-	if(event->input.key == InputKeyBack && event->input.type == InputTypeLong) 
-	{
-		tracker->quit = true;
-		return;
-	}
-
-	switch(tracker->focus)
-	{
-		case EDIT_PATTERN:
-		{
-			pattern_edit_event(tracker, event);
-			break;
-		}
-
-		case EDIT_SEQUENCE:
-		{
-			sequence_edit_event(tracker, event);
-			break;
-		}
-
-		case EDIT_SONGINFO:
-		{
-			songinfo_edit_event(tracker, event);
-			break;
-		}
-
-		default: break;
-	}
+    /*if(event->input.key == InputKeyBack && event->input.type == InputTypeShort && event->period > 0 && event->period < 200)
+    {
+            cycle_focus(tracker);
+    }*/
+
+    if (event->input.key == InputKeyBack && event->input.type == InputTypeShort && !(tracker->editing))
+    {
+        cycle_focus(tracker);
+        return;
+    }
+
+    // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
+    if (event->input.key == InputKeyBack && event->input.type == InputTypeLong)
+    {
+        tracker->quit = true;
+        return;
+    }
+
+    switch (tracker->focus)
+    {
+        case EDIT_PATTERN:
+        {
+            pattern_edit_event(tracker, event);
+            break;
+        }
+
+        case EDIT_SEQUENCE:
+        {
+            sequence_edit_event(tracker, event);
+            break;
+        }
+
+        case EDIT_SONGINFO:
+        {
+            songinfo_edit_event(tracker, event);
+            break;
+        }
+
+        default:
+            break;
+    }
 }

+ 3 - 3
input_event.h

@@ -1,16 +1,16 @@
 #pragma once
 
-#include <stdio.h>
 #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 "flizzer_tracker.h"
 #include "util.h"
 
 #include "input/pattern.h"
 #include "input/sequence.h"
 #include "input/songinfo.h"
 
-void process_input_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event);
+void process_input_event(FlizzerTrackerApp *tracker, FlizzerTrackerEvent *event);

+ 28 - 28
sound_engine/freqs.c

@@ -1,38 +1,38 @@
 #include "freqs.h"
 
-const uint32_t frequency_table[FREQ_TAB_SIZE] = 
-{
-	(uint32_t)(2093.00 * 1024), //7th octave, the highest in this tracker
-	(uint32_t)(2217.46 * 1024), //frequency precision is 1 / 1024th of Hz
-	(uint32_t)(2349.32 * 1024),
-	(uint32_t)(2489.02 * 1024),
-	(uint32_t)(2637.02 * 1024),
-	(uint32_t)(2793.83 * 1024),
-	(uint32_t)(2959.96 * 1024),
-	(uint32_t)(3135.96 * 1024),
-	(uint32_t)(3322.44 * 1024),
-	(uint32_t)(3520.00 * 1024),
-	(uint32_t)(3729.31 * 1024),
-	(uint32_t)(3951.07 * 1024),
+const uint32_t frequency_table[FREQ_TAB_SIZE] =
+    {
+        (uint32_t)(2093.00 * 1024), // 7th octave, the highest in this tracker
+        (uint32_t)(2217.46 * 1024), // frequency precision is 1 / 1024th of Hz
+        (uint32_t)(2349.32 * 1024),
+        (uint32_t)(2489.02 * 1024),
+        (uint32_t)(2637.02 * 1024),
+        (uint32_t)(2793.83 * 1024),
+        (uint32_t)(2959.96 * 1024),
+        (uint32_t)(3135.96 * 1024),
+        (uint32_t)(3322.44 * 1024),
+        (uint32_t)(3520.00 * 1024),
+        (uint32_t)(3729.31 * 1024),
+        (uint32_t)(3951.07 * 1024),
 };
 
 uint32_t get_freq(uint16_t note)
 {
-	if (note >= ((FREQ_TAB_SIZE * 8) << 8))
-	{
-		return frequency_table[FREQ_TAB_SIZE - 1];
-	}
+    if (note >= ((FREQ_TAB_SIZE * 8) << 8))
+    {
+        return frequency_table[FREQ_TAB_SIZE - 1];
+    }
 
-	if ((note & 0xff) == 0)
-	{
-		return frequency_table[((note >> 8) % 12)] / ((NUM_OCTAVES) - ((note >> 8) / 12)); //wrap to one octave
-	}
+    if ((note & 0xff) == 0)
+    {
+        return frequency_table[((note >> 8) % 12)] / ((NUM_OCTAVES) - ((note >> 8) / 12)); // wrap to one octave
+    }
 
-	else
-	{
-		uint64_t f1 = frequency_table[((note >> 8) % 12)] / ((NUM_OCTAVES) - ((note >> 8) / 12));
-		uint64_t f2 = frequency_table[(((note >> 8) + 1) % 12)] / ((NUM_OCTAVES) - (((note >> 8) + 1) / 12));
+    else
+    {
+        uint64_t f1 = frequency_table[((note >> 8) % 12)] / ((NUM_OCTAVES) - ((note >> 8) / 12));
+        uint64_t f2 = frequency_table[(((note >> 8) + 1) % 12)] / ((NUM_OCTAVES) - (((note >> 8) + 1) / 12));
 
-		return f1 + (uint64_t)((f2 - f1) * (note & 0xff)) / 256;
-	}
+        return f1 + (uint64_t)((f2 - f1) * (note & 0xff)) / 256;
+    }
 }

+ 1 - 1
sound_engine/freqs.h

@@ -3,7 +3,7 @@
 #include <stdio.h>
 
 #define FREQ_TAB_SIZE 12 /* one octave */
-#define NUM_OCTAVES 8 /* 0-7th octaves */
+#define NUM_OCTAVES 8    /* 0-7th octaves */
 
 extern const uint32_t frequency_table[FREQ_TAB_SIZE];
 

+ 132 - 132
sound_engine/sound_engine.c

@@ -5,158 +5,158 @@
 
 #define PI 3.1415
 
-void sound_engine_init(SoundEngine* sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size)
+void sound_engine_init(SoundEngine *sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size)
 {
-	sound_engine->audio_buffer = malloc(audio_buffer_size * sizeof(sound_engine->audio_buffer[0]));
-	memset(sound_engine->audio_buffer, 0, sizeof(SoundEngine));
-	sound_engine->audio_buffer_size = audio_buffer_size;
-	sound_engine->sample_rate = sample_rate;
-	sound_engine->external_audio_output = external_audio_output;
+    sound_engine->audio_buffer = malloc(audio_buffer_size * sizeof(sound_engine->audio_buffer[0]));
+    memset(sound_engine->audio_buffer, 0, sizeof(SoundEngine));
+    sound_engine->audio_buffer_size = audio_buffer_size;
+    sound_engine->sample_rate = sample_rate;
+    sound_engine->external_audio_output = external_audio_output;
 
-	for(int i = 0; i < NUM_CHANNELS; ++i)
-	{
-		sound_engine->channel[i].lfsr = RANDOM_SEED;
-	}
+    for (int i = 0; i < NUM_CHANNELS; ++i)
+    {
+        sound_engine->channel[i].lfsr = RANDOM_SEED;
+    }
 
-	for(int i = 0; i < SINE_LUT_SIZE; ++i)
-	{
-		sound_engine->sine_lut[i] = (uint8_t)((sinf(i / 64.0 * PI) + 1.0) * 127.0);
-	}
+    for (int i = 0; i < SINE_LUT_SIZE; ++i)
+    {
+        sound_engine->sine_lut[i] = (uint8_t)((sinf(i / 64.0 * PI) + 1.0) * 127.0);
+    }
 
-	furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdDma1Ch1, 15, sound_engine_dma_isr, sound_engine);
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdDma1Ch1, 15, sound_engine_dma_isr, sound_engine);
 
-	sound_engine_init_hardware(sample_rate, external_audio_output, sound_engine->audio_buffer, audio_buffer_size);
+    sound_engine_init_hardware(sample_rate, external_audio_output, sound_engine->audio_buffer, audio_buffer_size);
 }
 
-void sound_engine_deinit(SoundEngine* sound_engine)
+void sound_engine_deinit(SoundEngine *sound_engine)
 {
-	free(sound_engine->audio_buffer);
+    free(sound_engine->audio_buffer);
 
-	if(!(sound_engine->external_audio_output))
-	{
-		furi_hal_speaker_release();
-	}
+    if (!(sound_engine->external_audio_output))
+    {
+        furi_hal_speaker_release();
+    }
 
-	else
-	{
-		furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull);
-	}
+    else
+    {
+        furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull);
+    }
 
-	furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdDma1Ch1, 13, NULL, NULL);
-	sound_engine_stop();
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdDma1Ch1, 13, NULL, NULL);
+    sound_engine_stop();
 }
 
-void sound_engine_set_channel_frequency(SoundEngine* sound_engine, SoundEngineChannel* channel, uint16_t note)
+void sound_engine_set_channel_frequency(SoundEngine *sound_engine, SoundEngineChannel *channel, uint16_t note)
 {
-	uint32_t frequency = get_freq(note);
+    uint32_t frequency = get_freq(note);
 
-	if(frequency != 0)
-	{
-		channel->frequency = (uint64_t)(ACC_LENGTH) / (uint64_t)1024 * (uint64_t)(frequency) / (uint64_t)sound_engine->sample_rate;
-	}
+    if (frequency != 0)
+    {
+        channel->frequency = (uint64_t)(ACC_LENGTH) / (uint64_t)1024 * (uint64_t)(frequency) / (uint64_t)sound_engine->sample_rate;
+    }
 
-	else
-	{
-		channel->frequency = 0;
-	}
+    else
+    {
+        channel->frequency = 0;
+    }
 }
 
-void sound_engine_enable_gate(SoundEngine* sound_engine, SoundEngineChannel* channel, bool enable)
+void sound_engine_enable_gate(SoundEngine *sound_engine, SoundEngineChannel *channel, bool enable)
 {
-	if(enable)
-	{
-		channel->adsr.envelope = 0;
-		channel->adsr.envelope_speed = envspd(sound_engine, channel->adsr.a);
-		channel->adsr.envelope_state = ATTACK;
-
-		channel->flags |= SE_ENABLE_GATE;
-
-		if(channel->flags & SE_ENABLE_KEYDOWN_SYNC)
-		{
-			channel->accumulator = 0;
-		}
-	}
-
-	else
-	{
-		channel->adsr.envelope_state = RELEASE;
-		channel->adsr.envelope_speed = envspd(sound_engine, channel->adsr.r);
-	}
+    if (enable)
+    {
+        channel->adsr.envelope = 0;
+        channel->adsr.envelope_speed = envspd(sound_engine, channel->adsr.a);
+        channel->adsr.envelope_state = ATTACK;
+
+        channel->flags |= SE_ENABLE_GATE;
+
+        if (channel->flags & SE_ENABLE_KEYDOWN_SYNC)
+        {
+            channel->accumulator = 0;
+        }
+    }
+
+    else
+    {
+        channel->adsr.envelope_state = RELEASE;
+        channel->adsr.envelope_speed = envspd(sound_engine, channel->adsr.r);
+    }
 }
 
-void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size)
+void sound_engine_fill_buffer(SoundEngine *sound_engine, uint16_t *audio_buffer, uint32_t audio_buffer_size)
 {
-	int32_t channel_output[NUM_CHANNELS];
-	int32_t channel_output_final[NUM_CHANNELS];
-
-	for(uint32_t i = 0; i < audio_buffer_size; ++i)
-	{
-		int32_t output = WAVE_AMP / 2 / 64;
-
-		for(uint32_t chan = 0; chan < NUM_CHANNELS; ++chan)
-		{
-			SoundEngineChannel* channel = &sound_engine->channel[chan];
-
-			if(channel->frequency > 0)
-			{
-				uint32_t prev_acc = channel->accumulator;
-
-				channel->accumulator += channel->frequency;
-
-				channel->sync_bit |= (channel->accumulator & ACC_LENGTH);
-
-				channel->accumulator &= ACC_LENGTH - 1;
-
-				if(channel->flags & SE_ENABLE_HARD_SYNC)
-				{
-					uint8_t hard_sync_src = channel->hard_sync == 0xff ? i : channel->hard_sync;
-					
-					if(sound_engine->channel[hard_sync_src].sync_bit)
-					{
-						channel->accumulator = 0;
-					}
-				}
-
-				channel_output[chan] = sound_engine_osc(sound_engine, channel, prev_acc) - WAVE_AMP / 2;
-
-				if(channel->flags & SE_ENABLE_RING_MOD)
-				{
-					uint8_t ring_mod_src = channel->ring_mod == 0xff ? i : channel->ring_mod;
-					channel_output[chan] = channel_output[chan] * channel_output[ring_mod_src] / WAVE_AMP;
-				}
-
-				channel_output_final[chan] = sound_engine_cycle_and_output_adsr(channel_output[chan], sound_engine, &channel->adsr, &channel->flags);
-				
-				if(channel->flags & SE_ENABLE_FILTER)
-				{
-					sound_engine_filter_cycle(&channel->filter, channel_output_final[chan]);
-
-					switch(channel->filter_mode)
-					{
-						case FIL_OUTPUT_LOWPASS:
-						{
-							channel_output_final[chan] = sound_engine_output_lowpass(&channel->filter);
-							break;
-						}
-
-						case FIL_OUTPUT_HIGHPASS:
-						{
-							channel_output_final[chan] = sound_engine_output_highpass(&channel->filter);
-							break;
-						}
-
-						case FIL_OUTPUT_BANDPASS:
-						{
-							channel_output_final[chan] = sound_engine_output_bandpass(&channel->filter);
-							break;
-						}
-					}
-				}
-
-				output += ((channel_output_final[chan]) / (int32_t)(64 * 4)); //2 more bits so all channels fit
-			}
-		}
-
-		audio_buffer[i] = output;
-	}
+    int32_t channel_output[NUM_CHANNELS];
+    int32_t channel_output_final[NUM_CHANNELS];
+
+    for (uint32_t i = 0; i < audio_buffer_size; ++i)
+    {
+        int32_t output = WAVE_AMP / 2 / 64;
+
+        for (uint32_t chan = 0; chan < NUM_CHANNELS; ++chan)
+        {
+            SoundEngineChannel *channel = &sound_engine->channel[chan];
+
+            if (channel->frequency > 0)
+            {
+                uint32_t prev_acc = channel->accumulator;
+
+                channel->accumulator += channel->frequency;
+
+                channel->sync_bit |= (channel->accumulator & ACC_LENGTH);
+
+                channel->accumulator &= ACC_LENGTH - 1;
+
+                if (channel->flags & SE_ENABLE_HARD_SYNC)
+                {
+                    uint8_t hard_sync_src = channel->hard_sync == 0xff ? i : channel->hard_sync;
+
+                    if (sound_engine->channel[hard_sync_src].sync_bit)
+                    {
+                        channel->accumulator = 0;
+                    }
+                }
+
+                channel_output[chan] = sound_engine_osc(sound_engine, channel, prev_acc) - WAVE_AMP / 2;
+
+                if (channel->flags & SE_ENABLE_RING_MOD)
+                {
+                    uint8_t ring_mod_src = channel->ring_mod == 0xff ? i : channel->ring_mod;
+                    channel_output[chan] = channel_output[chan] * channel_output[ring_mod_src] / WAVE_AMP;
+                }
+
+                channel_output_final[chan] = sound_engine_cycle_and_output_adsr(channel_output[chan], sound_engine, &channel->adsr, &channel->flags);
+
+                if (channel->flags & SE_ENABLE_FILTER)
+                {
+                    sound_engine_filter_cycle(&channel->filter, channel_output_final[chan]);
+
+                    switch (channel->filter_mode)
+                    {
+                        case FIL_OUTPUT_LOWPASS:
+                        {
+                            channel_output_final[chan] = sound_engine_output_lowpass(&channel->filter);
+                            break;
+                        }
+
+                        case FIL_OUTPUT_HIGHPASS:
+                        {
+                            channel_output_final[chan] = sound_engine_output_highpass(&channel->filter);
+                            break;
+                        }
+
+                        case FIL_OUTPUT_BANDPASS:
+                        {
+                            channel_output_final[chan] = sound_engine_output_bandpass(&channel->filter);
+                            break;
+                        }
+                    }
+                }
+
+                output += ((channel_output_final[chan]) / (int32_t)(64 * 4)); // 2 more bits so all channels fit
+            }
+        }
+
+        audio_buffer[i] = output;
+    }
 }

+ 8 - 8
sound_engine/sound_engine.h

@@ -1,13 +1,13 @@
 #pragma once
 
-#include "sound_engine_osc.h"
-#include "sound_engine_filter.h"
 #include "freqs.h"
-#include "sound_engine_defs.h"
 #include "sound_engine_adsr.h"
+#include "sound_engine_defs.h"
+#include "sound_engine_filter.h"
+#include "sound_engine_osc.h"
 
-void sound_engine_init(SoundEngine* sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size);
-void sound_engine_deinit(SoundEngine* sound_engine);
-void sound_engine_set_channel_frequency(SoundEngine* sound_engine, SoundEngineChannel* channel, uint16_t note);
-void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size);
-void sound_engine_enable_gate(SoundEngine* sound_engine, SoundEngineChannel* channel, bool enable);
+void sound_engine_init(SoundEngine *sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size);
+void sound_engine_deinit(SoundEngine *sound_engine);
+void sound_engine_set_channel_frequency(SoundEngine *sound_engine, SoundEngineChannel *channel, uint16_t note);
+void sound_engine_fill_buffer(SoundEngine *sound_engine, uint16_t *audio_buffer, uint32_t audio_buffer_size);
+void sound_engine_enable_gate(SoundEngine *sound_engine, SoundEngineChannel *channel, bool enable);

+ 53 - 53
sound_engine/sound_engine_adsr.c

@@ -1,65 +1,65 @@
 #include "sound_engine_adsr.h"
 
-int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine* eng, SoundEngineADSR* adsr, uint16_t* flags)
+int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine *eng, SoundEngineADSR *adsr, uint16_t *flags)
 {
-	switch(adsr->envelope_state)
-	{
-		case ATTACK:
-		{
-			adsr->envelope += adsr->envelope_speed;
-			
-			if (adsr->envelope >= MAX_ADSR) 
-			{
-				adsr->envelope_state = DECAY;
-				adsr->envelope = MAX_ADSR;
+    switch (adsr->envelope_state)
+    {
+        case ATTACK:
+        {
+            adsr->envelope += adsr->envelope_speed;
 
-				adsr->envelope_speed = envspd(eng, adsr->d);
-			}
+            if (adsr->envelope >= MAX_ADSR)
+            {
+                adsr->envelope_state = DECAY;
+                adsr->envelope = MAX_ADSR;
 
-			break;
-		}
+                adsr->envelope_speed = envspd(eng, adsr->d);
+            }
 
-		case DECAY:
-		{
-			if (adsr->envelope > ((uint32_t)adsr->s << 17) + adsr->envelope_speed)
-			{
-				adsr->envelope -= adsr->envelope_speed;
-			}
-			
-			else
-			{
-				adsr->envelope = (uint32_t)adsr->s << 17;
-				adsr->envelope_state = (adsr->s == 0) ? RELEASE : SUSTAIN;
-				
-				adsr->envelope_speed = envspd(eng, adsr->r);
-			}
+            break;
+        }
 
-			break;
-		}
+        case DECAY:
+        {
+            if (adsr->envelope > ((uint32_t)adsr->s << 17) + adsr->envelope_speed)
+            {
+                adsr->envelope -= adsr->envelope_speed;
+            }
 
-		case SUSTAIN:
-		case DONE:
-		{
-			break;
-		}
+            else
+            {
+                adsr->envelope = (uint32_t)adsr->s << 17;
+                adsr->envelope_state = (adsr->s == 0) ? RELEASE : SUSTAIN;
 
-		case RELEASE:
-		{
-			if (adsr->envelope > adsr->envelope_speed)
-			{
-				adsr->envelope -= adsr->envelope_speed;
-			}
-			
-			else 
-			{
-				adsr->envelope_state = DONE;
-				*flags &= ~SE_ENABLE_GATE;
-				adsr->envelope = 0;
-			}
+                adsr->envelope_speed = envspd(eng, adsr->r);
+            }
 
-			break;
-		}
-	}
+            break;
+        }
 
-	return (int32_t)((int64_t)input * (int64_t)adsr->envelope / (int64_t)MAX_ADSR * (int64_t)adsr->volume / (int64_t)MAX_ADSR_VOLUME);
+        case SUSTAIN:
+        case DONE:
+        {
+            break;
+        }
+
+        case RELEASE:
+        {
+            if (adsr->envelope > adsr->envelope_speed)
+            {
+                adsr->envelope -= adsr->envelope_speed;
+            }
+
+            else
+            {
+                adsr->envelope_state = DONE;
+                *flags &= ~SE_ENABLE_GATE;
+                adsr->envelope = 0;
+            }
+
+            break;
+        }
+    }
+
+    return (int32_t)((int64_t)input * (int64_t)adsr->envelope / (int64_t)MAX_ADSR * (int64_t)adsr->volume / (int64_t)MAX_ADSR_VOLUME);
 }

+ 1 - 1
sound_engine/sound_engine_adsr.h

@@ -2,4 +2,4 @@
 
 #include "sound_engine_defs.h"
 
-int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine* eng, SoundEngineADSR* adsr, uint16_t* flags);
+int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine *eng, SoundEngineADSR *adsr, uint16_t *flags);

+ 45 - 45
sound_engine/sound_engine_defs.h

@@ -1,7 +1,7 @@
 #pragma once
 
-#include <stdio.h>
 #include <stdbool.h>
+#include <stdio.h>
 
 #define NUM_CHANNELS 4
 
@@ -19,83 +19,83 @@
 #define MAX_ADSR (0xff << 17)
 #define MAX_ADSR_VOLUME 0x80
 #define BASE_FREQ 22050
-#define envspd(eng, slope) ((slope) != 0 ? (((uint64_t)MAX_ADSR / ((slope) * (slope) * 256 / 8)) * BASE_FREQ / eng->sample_rate) : ((uint64_t)MAX_ADSR * BASE_FREQ / eng->sample_rate))
+#define envspd(eng, slope) ((slope) != 0 ? (((uint64_t)MAX_ADSR / ((slope) * (slope)*256 / 8)) * BASE_FREQ / eng->sample_rate) : ((uint64_t)MAX_ADSR * BASE_FREQ / eng->sample_rate))
 
 typedef enum
 {
-	SE_WAVEFORM_NONE = 0,
-	SE_WAVEFORM_NOISE = 1,
-	SE_WAVEFORM_PULSE = 2,
-	SE_WAVEFORM_TRIANGLE = 4,
-	SE_WAVEFORM_SAW = 8,
-	SE_WAVEFORM_NOISE_METAL = 16,
-	SE_WAVEFORM_SINE = 32,
+    SE_WAVEFORM_NONE = 0,
+    SE_WAVEFORM_NOISE = 1,
+    SE_WAVEFORM_PULSE = 2,
+    SE_WAVEFORM_TRIANGLE = 4,
+    SE_WAVEFORM_SAW = 8,
+    SE_WAVEFORM_NOISE_METAL = 16,
+    SE_WAVEFORM_SINE = 32,
 } SoudEngineWaveformType;
 
 typedef enum
 {
-	SE_ENABLE_FILTER = 1,
-	SE_ENABLE_GATE = 2,
-	SE_ENABLE_RING_MOD = 4,
-	SE_ENABLE_HARD_SYNC = 8,
-	SE_ENABLE_KEYDOWN_SYNC = 16, //sync oscillators on keydown
+    SE_ENABLE_FILTER = 1,
+    SE_ENABLE_GATE = 2,
+    SE_ENABLE_RING_MOD = 4,
+    SE_ENABLE_HARD_SYNC = 8,
+    SE_ENABLE_KEYDOWN_SYNC = 16, // sync oscillators on keydown
 } SoundEngineFlags;
 
 typedef enum
 {
-	FIL_OUTPUT_LOWPASS = 1,
-	FIL_OUTPUT_HIGHPASS = 2,
-	FIL_OUTPUT_BANDPASS = 3,
+    FIL_OUTPUT_LOWPASS = 1,
+    FIL_OUTPUT_HIGHPASS = 2,
+    FIL_OUTPUT_BANDPASS = 3,
 } SoundEngineFilterModes;
 
 typedef enum
 {
-	ATTACK = 1,
-	DECAY = 2,
-	SUSTAIN = 3,
-	RELEASE = 4,
-	DONE = 5,
+    ATTACK = 1,
+    DECAY = 2,
+    SUSTAIN = 3,
+    RELEASE = 4,
+    DONE = 5,
 } SoundEngineEnvelopeStates;
 
 typedef struct
 {
-	uint8_t a, d, s, r, volume, envelope_state;
-	uint32_t envelope, envelope_speed;
+    uint8_t a, d, s, r, volume, envelope_state;
+    uint32_t envelope, envelope_speed;
 } SoundEngineADSR;
 
 typedef struct
 {
-	int32_t f, q, p;
-	int32_t b0, b1, b2, b3, b4; //filter coefficients
+    int32_t f, q, p;
+    int32_t b0, b1, b2, b3, b4; // filter coefficients
 } SoundEngineFilter;
 
 typedef struct
 {
-	uint32_t accumulator;
-	uint32_t frequency;
-	uint8_t waveform;
-	uint16_t pw;
-	uint32_t lfsr;
-	SoundEngineADSR adsr;
+    uint32_t accumulator;
+    uint32_t frequency;
+    uint8_t waveform;
+    uint16_t pw;
+    uint32_t lfsr;
+    SoundEngineADSR adsr;
 
-	uint16_t flags;
+    uint16_t flags;
 
-	uint8_t ring_mod, hard_sync; //0xff = self
-	uint8_t sync_bit;
+    uint8_t ring_mod, hard_sync; // 0xff = self
+    uint8_t sync_bit;
 
-	uint8_t filter_mode;
-	uint16_t filter_cutoff;
-	uint16_t filter_resonace;
+    uint8_t filter_mode;
+    uint16_t filter_cutoff;
+    uint16_t filter_resonace;
 
-	SoundEngineFilter filter;
+    SoundEngineFilter filter;
 } SoundEngineChannel;
 
 typedef struct
 {
-	SoundEngineChannel channel[NUM_CHANNELS];
-	uint32_t sample_rate;
-	uint16_t* audio_buffer;
-	uint32_t audio_buffer_size;
-	bool external_audio_output;
-	uint8_t sine_lut[SINE_LUT_SIZE];
+    SoundEngineChannel channel[NUM_CHANNELS];
+    uint32_t sample_rate;
+    uint16_t *audio_buffer;
+    uint32_t audio_buffer_size;
+    bool external_audio_output;
+    uint8_t sine_lut[SINE_LUT_SIZE];
 } SoundEngine;

+ 22 - 22
sound_engine/sound_engine_filter.c

@@ -1,38 +1,38 @@
 #include "sound_engine_filter.h"
 
-void sound_engine_filter_set_coeff(SoundEngineFilter* flt, uint32_t frequency, uint16_t resonance)
+void sound_engine_filter_set_coeff(SoundEngineFilter *flt, uint32_t frequency, uint16_t resonance)
 {
-	flt->q = 2048 - frequency;
-	flt->p = frequency + ((int32_t)(0.8f * 2048.0f) * frequency / 2048 * flt->q) / 2048;
-	flt->f = flt->p + flt->p - 2048;
-	flt->q = resonance;
+    flt->q = 2048 - frequency;
+    flt->p = frequency + ((int32_t)(0.8f * 2048.0f) * frequency / 2048 * flt->q) / 2048;
+    flt->f = flt->p + flt->p - 2048;
+    flt->q = resonance;
 }
 
-void sound_engine_filter_cycle(SoundEngineFilter* flt, int32_t input)
+void sound_engine_filter_cycle(SoundEngineFilter *flt, int32_t input)
 {
-	input -= flt->q * flt->b4 / 2048; //feedback
-	int32_t t1 = flt->b1;  
-	flt->b1 = (input + flt->b0) * flt->p / 2048 - flt->b1 * flt->f / 2048;
-	int32_t t2 = flt->b2;  
-	flt->b2 = (flt->b1 + t1) * flt->p / 2048 - flt->b2 * flt->f / 2048;
-	t1 = flt->b3;
-	flt->b3 = (flt->b2 + t2) * flt->p / 2048 - flt->b3 * flt->f / 2048;
-	flt->b4 = (flt->b3 + t1) * flt->p / 2048 - flt->b4 * flt->f / 2048;
-	
-	flt->b0 = input;
+    input -= flt->q * flt->b4 / 2048; // feedback
+    int32_t t1 = flt->b1;
+    flt->b1 = (input + flt->b0) * flt->p / 2048 - flt->b1 * flt->f / 2048;
+    int32_t t2 = flt->b2;
+    flt->b2 = (flt->b1 + t1) * flt->p / 2048 - flt->b2 * flt->f / 2048;
+    t1 = flt->b3;
+    flt->b3 = (flt->b2 + t2) * flt->p / 2048 - flt->b3 * flt->f / 2048;
+    flt->b4 = (flt->b3 + t1) * flt->p / 2048 - flt->b4 * flt->f / 2048;
+
+    flt->b0 = input;
 }
 
-int32_t sound_engine_output_lowpass(SoundEngineFilter* flt)
+int32_t sound_engine_output_lowpass(SoundEngineFilter *flt)
 {
-	return flt->b4;
+    return flt->b4;
 }
 
-int32_t sound_engine_output_highpass(SoundEngineFilter* flt)
+int32_t sound_engine_output_highpass(SoundEngineFilter *flt)
 {
-	return flt->b0 - flt->b4;
+    return flt->b0 - flt->b4;
 }
 
-int32_t sound_engine_output_bandpass(SoundEngineFilter* flt)
+int32_t sound_engine_output_bandpass(SoundEngineFilter *flt)
 {
-	return 3 * (flt->b3 - flt->b4);
+    return 3 * (flt->b3 - flt->b4);
 }

+ 5 - 5
sound_engine/sound_engine_filter.h

@@ -2,8 +2,8 @@
 
 #include "sound_engine_defs.h"
 
-void sound_engine_filter_set_coeff(SoundEngineFilter* flt, uint32_t frequency, uint16_t resonance);
-void sound_engine_filter_cycle(SoundEngineFilter* flt, int32_t input);
-int32_t sound_engine_output_lowpass(SoundEngineFilter* flt);
-int32_t sound_engine_output_highpass(SoundEngineFilter* flt);
-int32_t sound_engine_output_bandpass(SoundEngineFilter* flt);
+void sound_engine_filter_set_coeff(SoundEngineFilter *flt, uint32_t frequency, uint16_t resonance);
+void sound_engine_filter_cycle(SoundEngineFilter *flt, int32_t input);
+int32_t sound_engine_output_lowpass(SoundEngineFilter *flt);
+int32_t sound_engine_output_highpass(SoundEngineFilter *flt);
+int32_t sound_engine_output_bandpass(SoundEngineFilter *flt);

+ 70 - 73
sound_engine/sound_engine_osc.c

@@ -1,93 +1,90 @@
 #include "sound_engine_osc.h"
 
-static inline uint16_t sound_engine_pulse(uint32_t acc, uint32_t pw) //0-FFF pulse width range
+static inline uint16_t sound_engine_pulse(uint32_t acc, uint32_t pw) // 0-FFF pulse width range
 {
-	return (((acc >> (((uint32_t)ACC_BITS - 17))) >= ((pw == 0xfff ? pw + 1 : pw) << 4) ? (WAVE_AMP - 1) : 0));
+    return (((acc >> (((uint32_t)ACC_BITS - 17))) >= ((pw == 0xfff ? pw + 1 : pw) << 4) ? (WAVE_AMP - 1) : 0));
 }
 
-static inline uint16_t sound_engine_saw(uint32_t acc) 
+static inline uint16_t sound_engine_saw(uint32_t acc)
 {
-	return (acc >> (ACC_BITS - OUTPUT_BITS - 1)) & (WAVE_AMP - 1);
+    return (acc >> (ACC_BITS - OUTPUT_BITS - 1)) & (WAVE_AMP - 1);
 }
 
-
 static inline uint16_t sound_engine_triangle(uint32_t acc)
 {
-	return ((((acc & (ACC_LENGTH / 2)) ? ~acc : acc) >> (ACC_BITS - OUTPUT_BITS - 2)) & (WAVE_AMP * 2 - 1));
+    return ((((acc & (ACC_LENGTH / 2)) ? ~acc : acc) >> (ACC_BITS - OUTPUT_BITS - 2)) & (WAVE_AMP * 2 - 1));
 }
 
-static inline uint16_t sound_engine_sine(uint32_t acc, SoundEngine* sound_engine) 
+static inline uint16_t sound_engine_sine(uint32_t acc, SoundEngine *sound_engine)
 {
-	return (sound_engine->sine_lut[(acc >> (ACC_BITS - SINE_LUT_BITDEPTH))] << (OUTPUT_BITS - SINE_LUT_BITDEPTH));
+    return (sound_engine->sine_lut[(acc >> (ACC_BITS - SINE_LUT_BITDEPTH))] << (OUTPUT_BITS - SINE_LUT_BITDEPTH));
 }
 
-inline static void shift_lfsr(uint32_t* v, uint32_t tap_0, uint32_t tap_1)
+inline static void shift_lfsr(uint32_t *v, uint32_t tap_0, uint32_t tap_1)
 {
-	typedef uint32_t T;
-	const T zero = (T)(0);
-	const T lsb = zero + (T)(1);
-	const T feedback = (
-		(lsb << (tap_0)) ^
-		(lsb << (tap_1))
-	);
-
-	*v = (*v >> 1) ^ ((zero - (*v & lsb)) & feedback);
+    typedef uint32_t T;
+    const T zero = (T)(0);
+    const T lsb = zero + (T)(1);
+    const T feedback = ((lsb << (tap_0)) ^
+                        (lsb << (tap_1)));
+
+    *v = (*v >> 1) ^ ((zero - (*v & lsb)) & feedback);
 }
 
-uint16_t sound_engine_osc(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t prev_acc)
+uint16_t sound_engine_osc(SoundEngine *sound_engine, SoundEngineChannel *channel, uint32_t prev_acc)
 {
-	switch(channel->waveform)
-	{
-		case SE_WAVEFORM_NOISE:
-		{
-			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
-			{
-				shift_lfsr(&channel->lfsr, 22, 17);
-				channel->lfsr &= (1 << (22 + 1)) - 1;
-			}
-
-			return (channel->lfsr) & (WAVE_AMP - 1);
-
-			break;
-		}
-
-		case SE_WAVEFORM_PULSE:
-		{
-			return sound_engine_pulse(channel->accumulator, channel->pw);
-			break;
-		}
-
-		case SE_WAVEFORM_TRIANGLE:
-		{
-			return sound_engine_triangle(channel->accumulator);
-			break;
-		}
-		
-		case SE_WAVEFORM_SAW:
-		{
-			return sound_engine_saw(channel->accumulator);
-			break;
-		}
-
-		case SE_WAVEFORM_NOISE_METAL:
-		{
-			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
-			{
-				shift_lfsr(&channel->lfsr, 14, 8);
-				channel->lfsr &= (1 << (14 + 1)) - 1;
-			}
-
-			return (channel->lfsr) & (WAVE_AMP - 1);
-
-			break;
-		}
-
-		case SE_WAVEFORM_SINE:
-		{
-			return sound_engine_sine(channel->accumulator, sound_engine);
-			break;
-		}
-	}
-
-	return 0;
+    switch (channel->waveform)
+    {
+        case SE_WAVEFORM_NOISE:
+        {
+            if ((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
+            {
+                shift_lfsr(&channel->lfsr, 22, 17);
+                channel->lfsr &= (1 << (22 + 1)) - 1;
+            }
+
+            return (channel->lfsr) & (WAVE_AMP - 1);
+
+            break;
+        }
+
+        case SE_WAVEFORM_PULSE:
+        {
+            return sound_engine_pulse(channel->accumulator, channel->pw);
+            break;
+        }
+
+        case SE_WAVEFORM_TRIANGLE:
+        {
+            return sound_engine_triangle(channel->accumulator);
+            break;
+        }
+
+        case SE_WAVEFORM_SAW:
+        {
+            return sound_engine_saw(channel->accumulator);
+            break;
+        }
+
+        case SE_WAVEFORM_NOISE_METAL:
+        {
+            if ((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
+            {
+                shift_lfsr(&channel->lfsr, 14, 8);
+                channel->lfsr &= (1 << (14 + 1)) - 1;
+            }
+
+            return (channel->lfsr) & (WAVE_AMP - 1);
+
+            break;
+        }
+
+        case SE_WAVEFORM_SINE:
+        {
+            return sound_engine_sine(channel->accumulator, sound_engine);
+            break;
+        }
+    }
+
+    return 0;
 }

+ 1 - 1
sound_engine/sound_engine_osc.h

@@ -2,4 +2,4 @@
 
 #include "sound_engine_defs.h"
 
-uint16_t sound_engine_osc(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t prev_acc);
+uint16_t sound_engine_osc(SoundEngine *sound_engine, SoundEngineChannel *channel, uint32_t prev_acc);

+ 197 - 191
tracker_engine/tracker_engine.c

@@ -4,282 +4,288 @@
 
 #include <furi_hal.h>
 
-void tracker_engine_init(TrackerEngine* tracker_engine, uint8_t rate, SoundEngine* sound_engine)
+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);
-	tracker_engine_init_hardware(rate);
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 14, tracker_engine_timer_isr, (void *)tracker_engine);
+    tracker_engine_init_hardware(rate);
 
-	tracker_engine->sound_engine = sound_engine;
-	tracker_engine->rate = rate;
+    tracker_engine->sound_engine = sound_engine;
+    tracker_engine->rate = rate;
 }
 
-void tracker_engine_deinit_song(TrackerSong* song, bool free_song)
+void tracker_engine_deinit_song(TrackerSong *song, bool free_song)
 {
-	for(int i = 0; i < MAX_PATTERNS; i++)
-	{
-		if(song->pattern[i].step != NULL)
-		{
-			free(song->pattern[i].step);
-		}
-	}
-
-	for(int i = 0; i < MAX_INSTRUMENTS; i++)
-	{
-		if(song->instrument[i] != NULL)
-		{
-			free(song->instrument[i]);
-		}
-	}
-
-	if(free_song)
-	{
-		free(song);
-	}
+    for (int i = 0; i < MAX_PATTERNS; i++)
+    {
+        if (song->pattern[i].step != NULL)
+        {
+            free(song->pattern[i].step);
+        }
+    }
+
+    for (int i = 0; i < MAX_INSTRUMENTS; i++)
+    {
+        if (song->instrument[i] != NULL)
+        {
+            free(song->instrument[i]);
+        }
+    }
+
+    if (free_song)
+    {
+        free(song);
+    }
 }
 
-void tracker_engine_deinit(TrackerEngine* tracker_engine, bool free_song)
+void tracker_engine_deinit(TrackerEngine *tracker_engine, bool free_song)
 {
-	tracker_engine_deinit_song(tracker_engine->song, free_song);
+    tracker_engine_deinit_song(tracker_engine->song, free_song);
 
-	furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 13, NULL, NULL);
-	tracker_engine_stop();
+    furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 13, NULL, NULL);
+    tracker_engine_stop();
 }
 
-uint8_t tracker_engine_get_note(TrackerSongPatternStep* step)
+uint8_t tracker_engine_get_note(TrackerSongPatternStep *step)
 {
-	return (step->note & 0x7f);
+    return (step->note & 0x7f);
 }
 
-uint8_t tracker_engine_get_instrument(TrackerSongPatternStep* step)
+uint8_t tracker_engine_get_instrument(TrackerSongPatternStep *step)
 {
-	return ((step->note & 0x80) >> 3) | ((step->inst_vol & 0xf0) >> 4);
+    return ((step->note & 0x80) >> 3) | ((step->inst_vol & 0xf0) >> 4);
 }
 
-uint8_t tracker_engine_get_volume(TrackerSongPatternStep* step)
+uint8_t tracker_engine_get_volume(TrackerSongPatternStep *step)
 {
-	return (step->inst_vol & 0xf) | ((step->command & 0x8000) >> 11);
+    return (step->inst_vol & 0xf) | ((step->command & 0x8000) >> 11);
 }
 
-uint16_t tracker_engine_get_command(TrackerSongPatternStep* step)
+uint16_t tracker_engine_get_command(TrackerSongPatternStep *step)
 {
-	return (step->command & 0x7fff);
+    return (step->command & 0x7fff);
 }
 
-void tracker_engine_set_note(TrackerEngine* tracker_engine, uint8_t chan, uint16_t note, bool update_note)
+void tracker_engine_set_note(TrackerEngine *tracker_engine, uint8_t chan, uint16_t note, bool update_note)
 {
-	if(update_note) tracker_engine->channel[chan].note = note;
+    if (update_note)
+        tracker_engine->channel[chan].note = note;
 
-	sound_engine_set_channel_frequency(tracker_engine->sound_engine, &tracker_engine->sound_engine->channel[chan], note);
+    sound_engine_set_channel_frequency(tracker_engine->sound_engine, &tracker_engine->sound_engine->channel[chan], note);
 }
 
-void tracker_engine_trigger_instrument_internal(TrackerEngine* tracker_engine, uint8_t chan, Instrument* pinst, uint16_t note)
+void tracker_engine_trigger_instrument_internal(TrackerEngine *tracker_engine, uint8_t chan, Instrument *pinst, uint16_t note)
 {
-	SoundEngineChannel* se_channel = &tracker_engine->sound_engine->channel[chan];
-	TrackerEngineChannel* te_channel = &tracker_engine->channel[chan];
+    SoundEngineChannel *se_channel = &tracker_engine->sound_engine->channel[chan];
+    TrackerEngineChannel *te_channel = &tracker_engine->channel[chan];
 
-	te_channel->channel_flags = TEC_PLAYING | (te_channel->channel_flags & TEC_DISABLED);
+    te_channel->channel_flags = TEC_PLAYING | (te_channel->channel_flags & TEC_DISABLED);
 
-	if(!(pinst->flags & TE_PROG_NO_RESTART) && pinst->program_period > 0)
-	{
-		te_channel->channel_flags |= TEC_PROGRAM_RUNNING;
+    if (!(pinst->flags & TE_PROG_NO_RESTART) && pinst->program_period > 0)
+    {
+        te_channel->channel_flags |= TEC_PROGRAM_RUNNING;
 
-		te_channel->program_counter = 0;
-		te_channel->program_loop = 0;
-		te_channel->program_period = 0;
-		te_channel->program_tick = 0;
-	}
+        te_channel->program_counter = 0;
+        te_channel->program_loop = 0;
+        te_channel->program_period = 0;
+        te_channel->program_tick = 0;
+    }
 
-	te_channel->program_period = pinst->program_period;
+    te_channel->program_period = pinst->program_period;
 
-	te_channel->instrument = pinst;
+    te_channel->instrument = pinst;
 
-	se_channel->waveform = pinst->waveform;
-	se_channel->flags = pinst->sound_engine_flags;
+    se_channel->waveform = pinst->waveform;
+    se_channel->flags = pinst->sound_engine_flags;
 
-	te_channel->flags = pinst->flags;
+    te_channel->flags = pinst->flags;
 
-	te_channel->arpeggio_note = 0;
-	te_channel->fixed_note = 0xffff;
+    te_channel->arpeggio_note = 0;
+    te_channel->fixed_note = 0xffff;
 
-	tracker_engine_set_note(tracker_engine, chan, note + (uint16_t)pinst->finetune, true);
+    tracker_engine_set_note(tracker_engine, chan, note + (uint16_t)pinst->finetune, true);
 
-	te_channel->last_note = te_channel->target_note = note + (uint16_t)pinst->finetune;
+    te_channel->last_note = te_channel->target_note = note + (uint16_t)pinst->finetune;
 
-	if(pinst->sound_engine_flags & SE_ENABLE_KEYDOWN_SYNC)
-	{
-		te_channel->vibrato_position = te_channel->pwm_position = 0;
-	}
+    if (pinst->sound_engine_flags & SE_ENABLE_KEYDOWN_SYNC)
+    {
+        te_channel->vibrato_position = te_channel->pwm_position = 0;
+    }
 
-	if(pinst->flags & TE_SET_CUTOFF)
-	{
-		te_channel->filter_cutoff = pinst->filter_cutoff;
-		te_channel->filter_resonance = pinst->filter_resonance;
+    if (pinst->flags & TE_SET_CUTOFF)
+    {
+        te_channel->filter_cutoff = pinst->filter_cutoff;
+        te_channel->filter_resonance = pinst->filter_resonance;
 
-		sound_engine_filter_set_coeff(&se_channel->filter, te_channel->filter_cutoff, (te_channel->filter_resonance << 5));
-	}
+        sound_engine_filter_set_coeff(&se_channel->filter, te_channel->filter_cutoff, (te_channel->filter_resonance << 5));
+    }
 
-	if(pinst->flags & TE_SET_PW)
-	{
-		te_channel->pw = (pinst->pw << 4);
-		se_channel->pw = (pinst->pw << 4);
-	}
+    if (pinst->flags & TE_SET_PW)
+    {
+        te_channel->pw = (pinst->pw << 4);
+        se_channel->pw = (pinst->pw << 4);
+    }
 
-	te_channel->slide_speed = 0;
+    te_channel->slide_speed = 0;
 
-	se_channel->adsr.a = pinst->adsr.a;
-	se_channel->adsr.d = pinst->adsr.d;
-	se_channel->adsr.s = pinst->adsr.s;
-	se_channel->adsr.r = pinst->adsr.r;
-	se_channel->adsr.volume = pinst->adsr.volume;
+    se_channel->adsr.a = pinst->adsr.a;
+    se_channel->adsr.d = pinst->adsr.d;
+    se_channel->adsr.s = pinst->adsr.s;
+    se_channel->adsr.r = pinst->adsr.r;
+    se_channel->adsr.volume = pinst->adsr.volume;
 
-	sound_engine_enable_gate(tracker_engine->sound_engine, &tracker_engine->sound_engine->channel[chan], true);
+    sound_engine_enable_gate(tracker_engine->sound_engine, &tracker_engine->sound_engine->channel[chan], true);
 }
 
-void tracker_engine_execute_track_command(TrackerEngine* tracker_engine, uint8_t chan, TrackerSongPatternStep* step, bool first_tick)
+void tracker_engine_execute_track_command(TrackerEngine *tracker_engine, uint8_t chan, TrackerSongPatternStep *step, bool first_tick)
 {
-	UNUSED(first_tick);
-	UNUSED(tracker_engine);
-	UNUSED(chan);
+    UNUSED(first_tick);
+    UNUSED(tracker_engine);
+    UNUSED(chan);
 
-	uint8_t vol = tracker_engine_get_volume(step);
+    uint8_t vol = tracker_engine_get_volume(step);
 
-	if(vol != MUS_NOTE_VOLUME_NONE)
-	{
-		tracker_engine->sound_engine->channel[chan].adsr.volume = (int32_t)tracker_engine->sound_engine->channel[chan].adsr.volume * (int32_t)vol / (MUS_NOTE_VOLUME_NONE - 1);
-	}
+    if (vol != MUS_NOTE_VOLUME_NONE)
+    {
+        tracker_engine->sound_engine->channel[chan].adsr.volume = (int32_t)tracker_engine->sound_engine->channel[chan].adsr.volume * (int32_t)vol / (MUS_NOTE_VOLUME_NONE - 1);
+    }
 
-	//TODO: add actual big ass function that executes commands; add arpeggio commands there
+    // TODO: add actual big ass function that executes commands; add arpeggio commands there
 }
 
-void tracker_engine_advance_tick(TrackerEngine* tracker_engine)
+void tracker_engine_advance_tick(TrackerEngine *tracker_engine)
 {
-	if(!(tracker_engine->playing)) return;
+    if (!(tracker_engine->playing))
+        return;
 
-	if(!(tracker_engine->song)) return;
+    if (!(tracker_engine->song))
+        return;
 
-	if(!(tracker_engine->sound_engine)) return;
+    if (!(tracker_engine->sound_engine))
+        return;
 
-	TrackerSong* song = tracker_engine->song;
+    TrackerSong *song = tracker_engine->song;
 
-	for(int chan = 0; chan < SONG_MAX_CHANNELS; ++chan)
-	{
-		SoundEngineChannel* se_channel = &tracker_engine->sound_engine->channel[chan];
-		TrackerEngineChannel* te_channel = &tracker_engine->channel[chan];
+    for (int chan = 0; chan < SONG_MAX_CHANNELS; ++chan)
+    {
+        SoundEngineChannel *se_channel = &tracker_engine->sound_engine->channel[chan];
+        TrackerEngineChannel *te_channel = &tracker_engine->channel[chan];
 
-		uint8_t sequence_position = tracker_engine->sequence_position;
-		uint8_t current_pattern = song->sequence.sequence_step[sequence_position].pattern_indices[chan];
-		uint8_t pattern_step = tracker_engine->pattern_position;
+        uint8_t sequence_position = tracker_engine->sequence_position;
+        uint8_t current_pattern = song->sequence.sequence_step[sequence_position].pattern_indices[chan];
+        uint8_t pattern_step = tracker_engine->pattern_position;
 
-		TrackerSongPattern* pattern = &song->pattern[current_pattern];
+        TrackerSongPattern *pattern = &song->pattern[current_pattern];
 
-		uint8_t note_delay = 0; //TODO: add note delay command
+        uint8_t note_delay = 0; // TODO: add note delay command
 
-		if(tracker_engine->current_tick == note_delay)
-		{
-			uint8_t note = tracker_engine_get_note(&pattern->step[pattern_step]);
-			uint8_t inst = tracker_engine_get_instrument(&pattern->step[pattern_step]);
+        if (tracker_engine->current_tick == note_delay)
+        {
+            uint8_t note = tracker_engine_get_note(&pattern->step[pattern_step]);
+            uint8_t inst = tracker_engine_get_instrument(&pattern->step[pattern_step]);
 
-			Instrument* pinst = NULL;
+            Instrument *pinst = NULL;
 
-			if(inst == MUS_NOTE_INSTRUMENT_NONE)
-			{
-				pinst = te_channel->instrument;
-			}
+            if (inst == MUS_NOTE_INSTRUMENT_NONE)
+            {
+                pinst = te_channel->instrument;
+            }
 
-			else
-			{
-				if(inst < song->num_instruments)
-				{
-					pinst = song->instrument[inst];
-					te_channel->instrument = pinst;
-				}
-			}
+            else
+            {
+                if (inst < song->num_instruments)
+                {
+                    pinst = song->instrument[inst];
+                    te_channel->instrument = pinst;
+                }
+            }
 
-			//TODO: add note cut command
+            // TODO: add note cut command
 
-			if(note == MUS_NOTE_RELEASE)
-			{
-				sound_engine_enable_gate(tracker_engine->sound_engine, se_channel, 0);
-			}
+            if (note == MUS_NOTE_RELEASE)
+            {
+                sound_engine_enable_gate(tracker_engine->sound_engine, se_channel, 0);
+            }
 
-			else if(pinst && note != MUS_NOTE_RELEASE && note != MUS_NOTE_CUT && note != MUS_NOTE_NONE)
-			{
-				te_channel->slide_speed = 0;
+            else if (pinst && note != MUS_NOTE_RELEASE && note != MUS_NOTE_CUT && note != MUS_NOTE_NONE)
+            {
+                te_channel->slide_speed = 0;
 
-				//TODO: add setting slide speed if slide command is there
+                // TODO: add setting slide speed if slide command is there
 
-				//te_channel->slide_speed = pinst->slide_speed;
+                // te_channel->slide_speed = pinst->slide_speed;
 
-				uint8_t prev_adsr_volume = se_channel->adsr.volume;
+                uint8_t prev_adsr_volume = se_channel->adsr.volume;
 
-				tracker_engine_trigger_instrument_internal(tracker_engine, chan, pinst, note << 8);
-				te_channel->note = (note << 8);
+                tracker_engine_trigger_instrument_internal(tracker_engine, chan, pinst, note << 8);
+                te_channel->note = (note << 8);
 
-				te_channel->target_note = (note << 8) + pinst->finetune;
+                te_channel->target_note = (note << 8) + pinst->finetune;
 
-				if(inst == MUS_NOTE_INSTRUMENT_NONE)
-				{
-					se_channel->adsr.volume = prev_adsr_volume;
-				}
-			}
-		}
+                if (inst == MUS_NOTE_INSTRUMENT_NONE)
+                {
+                    se_channel->adsr.volume = prev_adsr_volume;
+                }
+            }
+        }
 
-		tracker_engine_execute_track_command(tracker_engine, chan, &pattern->step[pattern_step], tracker_engine->current_tick == note_delay);
+        tracker_engine_execute_track_command(tracker_engine, chan, &pattern->step[pattern_step], tracker_engine->current_tick == note_delay);
 
-		if(te_channel->flags & TEC_PLAYING)
-		{
-			if(!(se_channel->flags & SE_ENABLE_GATE))
-			{
-				te_channel->flags &= ~(TEC_PLAYING);
-			}
+        if (te_channel->flags & TEC_PLAYING)
+        {
+            if (!(se_channel->flags & SE_ENABLE_GATE))
+            {
+                te_channel->flags &= ~(TEC_PLAYING);
+            }
 
-			if(te_channel->slide_speed != 0)
-			{
-				if(te_channel->target_note > te_channel->note)
-				{
-					te_channel->target_note += fmin(te_channel->slide_speed, te_channel->target_note - te_channel->note);
-				}
+            if (te_channel->slide_speed != 0)
+            {
+                if (te_channel->target_note > te_channel->note)
+                {
+                    te_channel->target_note += fmin(te_channel->slide_speed, te_channel->target_note - te_channel->note);
+                }
 
-				else if(te_channel->target_note < te_channel->note)
-				{
-					te_channel->target_note -= fmin(te_channel->slide_speed, te_channel->note - te_channel->target_note);
-				}
-			}
+                else if (te_channel->target_note < te_channel->note)
+                {
+                    te_channel->target_note -= fmin(te_channel->slide_speed, te_channel->note - te_channel->target_note);
+                }
+            }
 
-			//TODO: add instrument program execution
+            // TODO: add instrument program execution
 
-			//TODO: add PWM and vibrato execution
-			uint8_t vib = 0;
-			int32_t chn_note = (te_channel->fixed_note != 0xffff ? te_channel->fixed_note : te_channel->note) + vib + ((int16_t)te_channel->arpeggio_note << 8);
+            // TODO: add PWM and vibrato execution
+            uint8_t vib = 0;
+            int32_t chn_note = (te_channel->fixed_note != 0xffff ? te_channel->fixed_note : te_channel->note) + vib + ((int16_t)te_channel->arpeggio_note << 8);
 
-			if(chn_note < 0) chn_note = 0;
-			if(chn_note > ((12 * 7 + 11) << 8)) chn_note = ((12 * 7 + 11) << 8); //highest note is B-7
+            if (chn_note < 0)
+                chn_note = 0;
+            if (chn_note > ((12 * 7 + 11) << 8))
+                chn_note = ((12 * 7 + 11) << 8); // highest note is B-7
 
-			tracker_engine_set_note(tracker_engine, chan, (uint16_t)chn_note, false);
-		}
-	}
+            tracker_engine_set_note(tracker_engine, chan, (uint16_t)chn_note, false);
+        }
+    }
 
-	tracker_engine->current_tick++;
+    tracker_engine->current_tick++;
 
-	if(tracker_engine->current_tick >= song->speed)
-	{
-		//TODO: add pattern loop and pattern skip commands
+    if (tracker_engine->current_tick >= song->speed)
+    {
+        // TODO: add pattern loop and pattern skip commands
 
-		tracker_engine->pattern_position++;
+        tracker_engine->pattern_position++;
 
-		tracker_engine->current_tick = 0;
+        tracker_engine->current_tick = 0;
 
-		if(tracker_engine->pattern_position >= song->pattern_length)
-		{
-			tracker_engine->pattern_position = 0;
-			tracker_engine->sequence_position++;
-
-			if(tracker_engine->sequence_position >= song->num_sequence_steps)
-			{
-				tracker_engine->playing = false; //TODO: add song loop handling
-				tracker_engine->sequence_position--;
-				tracker_engine->pattern_position = song->pattern_length - 1;
-			}
-		}
-	}
+        if (tracker_engine->pattern_position >= song->pattern_length)
+        {
+            tracker_engine->pattern_position = 0;
+            tracker_engine->sequence_position++;
+
+            if (tracker_engine->sequence_position >= song->num_sequence_steps)
+            {
+                tracker_engine->playing = false; // TODO: add song loop handling
+                tracker_engine->sequence_position--;
+                tracker_engine->pattern_position = song->pattern_length - 1;
+            }
+        }
+    }
 }

+ 7 - 7
tracker_engine/tracker_engine.h

@@ -2,11 +2,11 @@
 
 #include "tracker_engine_defs.h"
 
-void tracker_engine_init(TrackerEngine* tracker_engine, uint8_t rate, SoundEngine* sound_engine);
-void tracker_engine_deinit(TrackerEngine* tracker_engine, bool free_song);
-void tracker_engine_advance_tick(TrackerEngine* tracker_engine);
+void tracker_engine_init(TrackerEngine *tracker_engine, uint8_t rate, SoundEngine *sound_engine);
+void tracker_engine_deinit(TrackerEngine *tracker_engine, bool free_song);
+void tracker_engine_advance_tick(TrackerEngine *tracker_engine);
 
-uint8_t tracker_engine_get_note(TrackerSongPatternStep* step);
-uint8_t tracker_engine_get_instrument(TrackerSongPatternStep* step);
-uint8_t tracker_engine_get_volume(TrackerSongPatternStep* step);
-uint16_t tracker_engine_get_command(TrackerSongPatternStep* step);
+uint8_t tracker_engine_get_note(TrackerSongPatternStep *step);
+uint8_t tracker_engine_get_instrument(TrackerSongPatternStep *step);
+uint8_t tracker_engine_get_volume(TrackerSongPatternStep *step);
+uint16_t tracker_engine_get_command(TrackerSongPatternStep *step);

+ 64 - 64
tracker_engine/tracker_engine_defs.h

@@ -1,7 +1,7 @@
 #pragma once
 
-#include <stdio.h>
 #include <stdbool.h>
+#include <stdio.h>
 
 #include "../sound_engine/sound_engine_defs.h"
 
@@ -28,135 +28,135 @@
 
 typedef enum
 {
-	TE_ENABLE_VIBRATO = 1,
-	TE_ENABLE_PWM = 2,
-	TE_PROG_NO_RESTART = 4,
-	TE_SET_CUTOFF = 8,
-	TE_SET_PW = 16,
-	TE_KEY_SYNC = 32, //sync oscillators on keydown
-	TE_RETRIGGER_ON_SLIDE = 64, //call trigger instrument function even if slide command is there
+    TE_ENABLE_VIBRATO = 1,
+    TE_ENABLE_PWM = 2,
+    TE_PROG_NO_RESTART = 4,
+    TE_SET_CUTOFF = 8,
+    TE_SET_PW = 16,
+    TE_KEY_SYNC = 32,           // sync oscillators on keydown
+    TE_RETRIGGER_ON_SLIDE = 64, // call trigger instrument function even if slide command is there
 } TrackerEngineFlags;
 
 typedef enum
 {
-	TEC_PLAYING = 1,
-	TEC_PROGRAM_RUNNING = 2,
-	TEC_DISABLED = 4,
+    TEC_PLAYING = 1,
+    TEC_PROGRAM_RUNNING = 2,
+    TEC_DISABLED = 4,
 } TrackerEngineChannelFlags;
 
 typedef struct
 {
-	uint8_t a, d, s, r, volume;
+    uint8_t a, d, s, r, volume;
 } InstrumentAdsr;
 
 typedef struct
 {
-	char name[MUS_INST_NAME_LEN + 1];
+    char name[MUS_INST_NAME_LEN + 1];
 
-	uint8_t waveform;
-	uint16_t flags;
-	uint16_t sound_engine_flags;
+    uint8_t waveform;
+    uint16_t flags;
+    uint16_t sound_engine_flags;
 
-	uint8_t slide_speed;
+    uint8_t slide_speed;
 
-	InstrumentAdsr adsr;
+    InstrumentAdsr adsr;
 
-	uint8_t ring_mod, hard_sync; //0xff = self
+    uint8_t ring_mod, hard_sync; // 0xff = self
 
-	uint8_t pw; //store only one byte since we don't have the luxury of virtually unlimited memory!
+    uint8_t pw; // store only one byte since we don't have the luxury of virtually unlimited memory!
 
-	uint16_t program[INST_PROG_LEN]; //MSB is unite bit (indicates this and next command must be executed at once)
-	uint8_t program_period;
+    uint16_t program[INST_PROG_LEN]; // MSB is unite bit (indicates this and next command must be executed at once)
+    uint8_t program_period;
 
-	uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
-	uint8_t pwm_speed, pwm_depth, pwm_delay;
+    uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
+    uint8_t pwm_speed, pwm_depth, pwm_delay;
 
-	uint8_t filter_cutoff, filter_resonance, filter_type;
+    uint8_t filter_cutoff, filter_resonance, filter_type;
 
-	int8_t finetune;
+    int8_t finetune;
 } Instrument;
 
 typedef struct
 {
-	Instrument* instrument;
+    Instrument *instrument;
 
-	uint16_t flags;
+    uint16_t flags;
 
-	uint8_t channel_flags;
+    uint8_t channel_flags;
 
-	uint16_t note, target_note, last_note, fixed_note;
-	int16_t arpeggio_note;
+    uint16_t note, target_note, last_note, fixed_note;
+    int16_t arpeggio_note;
 
-	uint8_t volume;
+    uint8_t volume;
 
-	uint8_t program_counter, program_tick, program_loop, program_period;
+    uint8_t program_counter, program_tick, program_loop, program_period;
 
-	uint16_t filter_cutoff;
-	uint8_t filter_resonance, filter_type;
+    uint16_t filter_cutoff;
+    uint8_t filter_resonance, filter_type;
 
-	uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
-	uint8_t pwm_speed, pwm_depth, pwm_delay;
+    uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
+    uint8_t pwm_speed, pwm_depth, pwm_delay;
 
-	uint16_t vibrato_position, pwm_position;
+    uint16_t vibrato_position, pwm_position;
 
-	uint8_t extarp1, extarp2;
+    uint8_t extarp1, extarp2;
 
-	uint16_t pw;
+    uint16_t pw;
 
-	uint8_t slide_speed;
+    uint8_t slide_speed;
 } TrackerEngineChannel;
 
 typedef struct
 {
-	uint8_t note; //MSB is used for instrument number MSB
-	uint8_t inst_vol; //high nibble + MSB from note = instrument, low nibble = 4 volume LSBs
-	uint16_t command; //MSB used as volume MSB
+    uint8_t note;     // MSB is used for instrument number MSB
+    uint8_t inst_vol; // high nibble + MSB from note = instrument, low nibble = 4 volume LSBs
+    uint16_t command; // MSB used as volume MSB
 } TrackerSongPatternStep;
 
 typedef struct
 {
-	TrackerSongPatternStep* step;
+    TrackerSongPatternStep *step;
 } TrackerSongPattern;
 
 typedef struct
 {
-	uint8_t pattern_indices[SONG_MAX_CHANNELS];
+    uint8_t pattern_indices[SONG_MAX_CHANNELS];
 } TrackerSongSequenceStep;
 
 typedef struct
 {
-	TrackerSongSequenceStep sequence_step[MAX_SEQUENCE_LENGTH];
+    TrackerSongSequenceStep sequence_step[MAX_SEQUENCE_LENGTH];
 } TrackerSongSequence;
 
 typedef struct
 {
-	Instrument* instrument[MAX_INSTRUMENTS];
-	TrackerSongPattern pattern[MAX_PATTERNS];
-	TrackerSongSequence sequence;
+    Instrument *instrument[MAX_INSTRUMENTS];
+    TrackerSongPattern pattern[MAX_PATTERNS];
+    TrackerSongSequence sequence;
 
-	uint8_t num_patterns, num_sequence_steps, num_instruments;
-	uint8_t pattern_length;
+    uint8_t num_patterns, num_sequence_steps, num_instruments;
+    uint8_t pattern_length;
 
-	char song_name[MUS_SONG_NAME_LEN + 1];
-	uint8_t speed, rate;
+    char song_name[MUS_SONG_NAME_LEN + 1];
+    uint8_t speed, rate;
 
-	uint8_t loop_start, loop_end;
+    uint8_t loop_start, loop_end;
 } TrackerSong;
 
 typedef struct
 {
-	TrackerEngineChannel channel[SONG_MAX_CHANNELS];
+    TrackerEngineChannel channel[SONG_MAX_CHANNELS];
 
-	TrackerSong* song;
-	SoundEngine* sound_engine;
+    TrackerSong *song;
+    SoundEngine *sound_engine;
 
-	uint8_t pattern_position, sequence_position, current_tick;
-	uint16_t absolute_position; //sequence_position * pattern_length + pattern_position
+    uint8_t pattern_position, sequence_position, current_tick;
+    uint16_t absolute_position; // sequence_position * pattern_length + pattern_position
 
-	uint8_t pattern_length;
+    uint8_t pattern_length;
 
-	uint8_t speed, rate;
-	uint8_t master_volume;
+    uint8_t speed, rate;
+    uint8_t master_volume;
 
-	bool playing; //if we reach the end of the song and song does not loop we just stop there
+    bool playing; // if we reach the end of the song and song does not loop we just stop there
 } TrackerEngine;

+ 80 - 79
util.c

@@ -1,113 +1,114 @@
 #include "util.h"
 
-void set_note(TrackerSongPatternStep* step, uint8_t note)
+void set_note(TrackerSongPatternStep *step, uint8_t note)
 {
-	step->note &= 0x80;
-	step->note |= (note & 0x7f);
+    step->note &= 0x80;
+    step->note |= (note & 0x7f);
 }
 
-void set_instrument(TrackerSongPatternStep* step, uint8_t inst)
+void set_instrument(TrackerSongPatternStep *step, uint8_t inst)
 {
-	step->note &= 0x7f;
-	step->inst_vol &= 0x0f;
+    step->note &= 0x7f;
+    step->inst_vol &= 0x0f;
 
-	step->note |= ((inst & 0x10) << 3);
-	step->inst_vol |= ((inst & 0xf) << 4);
+    step->note |= ((inst & 0x10) << 3);
+    step->inst_vol |= ((inst & 0xf) << 4);
 }
 
-void set_volume(TrackerSongPatternStep* step, uint8_t vol)
+void set_volume(TrackerSongPatternStep *step, uint8_t vol)
 {
-	step->command &= 0x7fff;
-	step->inst_vol &= 0xf0;
+    step->command &= 0x7fff;
+    step->inst_vol &= 0xf0;
 
-	step->command |= ((vol & 0x10) << 11);
-	step->inst_vol |= (vol & 0xf);
+    step->command |= ((vol & 0x10) << 11);
+    step->inst_vol |= (vol & 0xf);
 }
 
-void set_command(TrackerSongPatternStep* step, uint16_t command)
+void set_command(TrackerSongPatternStep *step, uint16_t command)
 {
-	step->command &= 0x8000;
-	step->command |= command & (0x7fff);
+    step->command &= 0x8000;
+    step->command |= command & (0x7fff);
 }
 
-void play_song(FlizzerTrackerApp* tracker, bool from_cursor)
+void play_song(FlizzerTrackerApp *tracker, bool from_cursor)
 {
-	tracker->tracker_engine.playing = true;
-	tracker->was_editing = tracker->editing;
-	tracker->editing = false;
+    tracker->tracker_engine.playing = true;
+    tracker->was_editing = tracker->editing;
+    tracker->editing = false;
 
-	if(!(from_cursor))
-	{
-		tracker->tracker_engine.pattern_position = 0;
-	}
+    if (!(from_cursor))
+    {
+        tracker->tracker_engine.pattern_position = 0;
+    }
 
-	play();
+    play();
 }
 
-void stop_song(FlizzerTrackerApp* tracker)
+void stop_song(FlizzerTrackerApp *tracker)
 {
-	tracker->tracker_engine.playing = false;
-	tracker->editing = tracker->was_editing;
-	stop();
+    tracker->tracker_engine.playing = false;
+    tracker->editing = tracker->was_editing;
+    stop();
 }
 
-bool is_pattern_empty(TrackerSong* song, uint8_t pattern)
+bool is_pattern_empty(TrackerSong *song, uint8_t pattern)
 {
-	TrackerSongPattern song_pattern = song->pattern[pattern];
-
-	for(int i = 0; i < song->pattern_length; i++)
-	{
-		TrackerSongPatternStep* step = &song_pattern.step[i];
-
-		if(tracker_engine_get_note(step) != MUS_NOTE_NONE ||
-		tracker_engine_get_instrument(step) != MUS_NOTE_INSTRUMENT_NONE ||
-		tracker_engine_get_volume(step) != MUS_NOTE_VOLUME_NONE ||
-		tracker_engine_get_command(step) != 0)
-		{
-			return false;
-		}
-	}
-
-	return true;
+    TrackerSongPattern song_pattern = song->pattern[pattern];
+
+    for (int i = 0; i < song->pattern_length; i++)
+    {
+        TrackerSongPatternStep *step = &song_pattern.step[i];
+
+        if (tracker_engine_get_note(step) != MUS_NOTE_NONE ||
+            tracker_engine_get_instrument(step) != MUS_NOTE_INSTRUMENT_NONE ||
+            tracker_engine_get_volume(step) != MUS_NOTE_VOLUME_NONE ||
+            tracker_engine_get_command(step) != 0)
+        {
+            return false;
+        }
+    }
+
+    return true;
 }
 
-void set_empty_pattern(TrackerSong* song, uint8_t pattern)
+void set_empty_pattern(TrackerSong *song, uint8_t pattern)
 {
-	TrackerSongPattern song_pattern = song->pattern[pattern];
+    TrackerSongPattern song_pattern = song->pattern[pattern];
 
-	for(int i = 0; i < song->pattern_length; i++)
-	{
-		TrackerSongPatternStep* step = &song_pattern.step[i];
+    for (int i = 0; i < song->pattern_length; i++)
+    {
+        TrackerSongPatternStep *step = &song_pattern.step[i];
 
-		set_note(step, MUS_NOTE_NONE);
-		set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
-		set_volume(step, MUS_NOTE_VOLUME_NONE);
-		set_command(step, 0);
-	}
+        set_note(step, MUS_NOTE_NONE);
+        set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
+        set_volume(step, MUS_NOTE_VOLUME_NONE);
+        set_command(step, 0);
+    }
 }
 
-bool check_and_allocate_pattern(TrackerSong* song, uint8_t pattern)
+bool check_and_allocate_pattern(TrackerSong *song, uint8_t pattern)
 {
-	if(pattern < song->num_patterns) //we can set this pattern since it already exists
-	{
-		return true;
-	}
-
-	else
-	{
-		if(song->pattern[pattern - 1].step == NULL) return false; //if we hop through several patterns (e.g. editing upper digit)
-
-		if(!(is_pattern_empty(song, pattern - 1))) //don't let the user flood the song with empty patterns
-		{
-			song->pattern[pattern].step = malloc(sizeof(TrackerSongPatternStep) * song->pattern_length);
-			set_empty_pattern(song, pattern);
-			song->num_patterns++;
-			return true;
-		}
-
-		else
-		{
-			return false;
-		}
-	}
+    if (pattern < song->num_patterns) // we can set this pattern since it already exists
+    {
+        return true;
+    }
+
+    else
+    {
+        if (song->pattern[pattern - 1].step == NULL)
+            return false; // if we hop through several patterns (e.g. editing upper digit)
+
+        if (!(is_pattern_empty(song, pattern - 1))) // don't let the user flood the song with empty patterns
+        {
+            song->pattern[pattern].step = malloc(sizeof(TrackerSongPatternStep) * song->pattern_length);
+            set_empty_pattern(song, pattern);
+            song->num_patterns++;
+            return true;
+        }
+
+        else
+        {
+            return false;
+        }
+    }
 }

+ 11 - 11
util.h

@@ -1,22 +1,22 @@
 #pragma once
 
-#include <stdio.h>
 #include <stdbool.h>
+#include <stdio.h>
 
+#include "flizzer_tracker.h"
 #include "sound_engine/sound_engine_defs.h"
 #include "tracker_engine/tracker_engine_defs.h"
-#include "flizzer_tracker.h"
 
 #define clamp(val, add, _min, _max) val = fmin(_max, fmax(_min, (int32_t)val + add))
 
-void set_note(TrackerSongPatternStep* step, uint8_t note);
-void set_instrument(TrackerSongPatternStep* step, uint8_t inst);
-void set_volume(TrackerSongPatternStep* step, uint8_t vol);
-void set_command(TrackerSongPatternStep* step, uint16_t command);
+void set_note(TrackerSongPatternStep *step, uint8_t note);
+void set_instrument(TrackerSongPatternStep *step, uint8_t inst);
+void set_volume(TrackerSongPatternStep *step, uint8_t vol);
+void set_command(TrackerSongPatternStep *step, uint16_t command);
 
-void play_song(FlizzerTrackerApp* tracker, bool from_cursor);
-void stop_song(FlizzerTrackerApp* tracker);
+void play_song(FlizzerTrackerApp *tracker, bool from_cursor);
+void stop_song(FlizzerTrackerApp *tracker);
 
-void set_empty_pattern(TrackerSong* song, uint8_t pattern);
-bool is_pattern_empty(TrackerSong* song, uint8_t pattern);
-bool check_and_allocate_pattern(TrackerSong* song, uint8_t pattern);
+void set_empty_pattern(TrackerSong *song, uint8_t pattern);
+bool is_pattern_empty(TrackerSong *song, uint8_t pattern);
+bool check_and_allocate_pattern(TrackerSong *song, uint8_t pattern);

+ 254 - 213
view/pattern_editor.c

@@ -4,264 +4,305 @@
 
 #define PATTERN_EDITOR_Y (64 - (6 * 5) - 1)
 
-static const char* notenames[] =
-{
-	"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-",
+static const char *notenames[] =
+    {
+        "C-",
+        "C#",
+        "D-",
+        "D#",
+        "E-",
+        "F-",
+        "F#",
+        "G-",
+        "G#",
+        "A-",
+        "A#",
+        "B-",
 };
 
-char* notename(uint8_t note)
+char *notename(uint8_t note)
 {
-	static char buffer[4];
+    static char buffer[4];
 
-	if(note == MUS_NOTE_CUT)
-	{
-		snprintf(buffer, sizeof(buffer), "%s", "OFF");
-	}
+    if (note == MUS_NOTE_CUT)
+    {
+        snprintf(buffer, sizeof(buffer), "%s", "OFF");
+    }
 
-	if(note == MUS_NOTE_RELEASE)
-	{
-		snprintf(buffer, sizeof(buffer), "   ");
-	}
+    if (note == MUS_NOTE_RELEASE)
+    {
+        snprintf(buffer, sizeof(buffer), "   ");
+    }
 
-	else
-	{
-		snprintf(buffer, sizeof(buffer), "%s%d", notenames[note % 12], note / 12);
-	}
+    else
+    {
+        snprintf(buffer, sizeof(buffer), "%s%d", notenames[note % 12], note / 12);
+    }
 
-	return buffer;
+    return buffer;
 }
 
-static const char to_char_array[] = 
-{
-	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-	'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-	'U', 'V', 'W', 'X', 'Y', 'Z',
+static const char to_char_array[] =
+    {
+        '0',
+        '1',
+        '2',
+        '3',
+        '4',
+        '5',
+        '6',
+        '7',
+        '8',
+        '9',
+        'A',
+        'B',
+        'C',
+        'D',
+        'E',
+        'F',
+        'G',
+        'H',
+        'I',
+        'J',
+        'K',
+        'L',
+        'M',
+        'N',
+        'O',
+        'P',
+        'Q',
+        'R',
+        'S',
+        'T',
+        'U',
+        'V',
+        'W',
+        'X',
+        'Y',
+        'Z',
 };
 
 char to_char(uint8_t number)
 {
-	return to_char_array[number];
+    return to_char_array[number];
 }
 
-void draw_pattern_view(Canvas* canvas, FlizzerTrackerApp* tracker)
+void draw_pattern_view(Canvas *canvas, FlizzerTrackerApp *tracker)
 {
-	char command_buffer[6] = {0};
-	char buffer[11] = {0};
-
-	canvas_draw_line(canvas, 0, PATTERN_EDITOR_Y, 127, PATTERN_EDITOR_Y);
-
-	for(int i = 1; i < SONG_MAX_CHANNELS; ++i)
-	{
-		for(int y = PATTERN_EDITOR_Y + 1; y < 64; y += 2)
-		{
-			canvas_draw_dot(canvas, i * 32 - 1, y);
-		}
-	}
-
-	for(int i = 0; i < SONG_MAX_CHANNELS; ++i)
-	{
-		uint8_t sequence_position = tracker->tracker_engine.sequence_position;
-		uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[i];
-		uint8_t pattern_step = tracker->tracker_engine.pattern_position;
-
-		uint8_t pattern_length = tracker->tracker_engine.song->pattern_length;
-
-		TrackerSongPattern* pattern = &tracker->tracker_engine.song->pattern[current_pattern];
-
-		for(uint8_t pos = 0; pos < 5; ++pos)
-		{
-			TrackerSongPatternStep* step = NULL;
-
-			if(pattern_step - 2 + pos >= 0 && pattern_step - 2 + pos < pattern_length)
-			{
-				step = &pattern->step[pattern_step + pos - 2];
-			}
-
-			uint8_t string_x = i * 32;
-			uint8_t string_y = PATTERN_EDITOR_Y + 6 * pos + 6 + 1;
-			
-			if(step)
-			{
-				uint8_t note = tracker_engine_get_note(step);
-				uint8_t inst = tracker_engine_get_instrument(step);
-				uint8_t vol = tracker_engine_get_volume(step);
-				uint16_t command = tracker_engine_get_command(step);
-
-				char inst_ch = to_char(inst);
-				char vol_ch = to_char(vol);
-				char command_ch = to_char(command >> 8);
-				
-				if(inst == MUS_NOTE_INSTRUMENT_NONE)
-				{
-					inst_ch = '-';
-				}
-
-				if(vol == MUS_NOTE_VOLUME_NONE)
-				{
-					vol_ch = '-';
-				}
-
-				if(command == 0)
-				{
-					snprintf(command_buffer, sizeof(command_buffer), "---");
-				}
-
-				else
-				{
-					snprintf(command_buffer, sizeof(command_buffer), "%c%02X", command_ch, (command & 0xff));
-				}
-
-				snprintf(buffer, sizeof(buffer), "%s%c%c%s", (note == MUS_NOTE_NONE ? "---" : notename(note)), inst_ch, vol_ch, command_buffer);
-
-				canvas_draw_str(canvas, string_x, string_y, buffer);
-
-				if(note == MUS_NOTE_RELEASE)
-				{
-					canvas_draw_icon(canvas, string_x, string_y - 5, &I_note_release);
-				}
-			}
-		}
-	}
-
-	if(tracker->editing && tracker->focus == EDIT_PATTERN)
-	{
-		uint8_t x = tracker->current_channel * 32 + tracker->patternx * 4 + (tracker->patternx > 0 ? 4 : 0) - 1;
-		uint8_t y = PATTERN_EDITOR_Y + 6 * 2 + 1;
-
-		canvas_draw_box(canvas, x, y, (tracker->patternx > 0 ? 5 : 9), 7);
-	}
+    char command_buffer[6] = {0};
+    char buffer[11] = {0};
+
+    canvas_draw_line(canvas, 0, PATTERN_EDITOR_Y, 127, PATTERN_EDITOR_Y);
+
+    for (int i = 1; i < SONG_MAX_CHANNELS; ++i)
+    {
+        for (int y = PATTERN_EDITOR_Y + 1; y < 64; y += 2)
+        {
+            canvas_draw_dot(canvas, i * 32 - 1, y);
+        }
+    }
+
+    for (int i = 0; i < SONG_MAX_CHANNELS; ++i)
+    {
+        uint8_t sequence_position = tracker->tracker_engine.sequence_position;
+        uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[sequence_position].pattern_indices[i];
+        uint8_t pattern_step = tracker->tracker_engine.pattern_position;
+
+        uint8_t pattern_length = tracker->tracker_engine.song->pattern_length;
+
+        TrackerSongPattern *pattern = &tracker->tracker_engine.song->pattern[current_pattern];
+
+        for (uint8_t pos = 0; pos < 5; ++pos)
+        {
+            TrackerSongPatternStep *step = NULL;
+
+            if (pattern_step - 2 + pos >= 0 && pattern_step - 2 + pos < pattern_length)
+            {
+                step = &pattern->step[pattern_step + pos - 2];
+            }
+
+            uint8_t string_x = i * 32;
+            uint8_t string_y = PATTERN_EDITOR_Y + 6 * pos + 6 + 1;
+
+            if (step)
+            {
+                uint8_t note = tracker_engine_get_note(step);
+                uint8_t inst = tracker_engine_get_instrument(step);
+                uint8_t vol = tracker_engine_get_volume(step);
+                uint16_t command = tracker_engine_get_command(step);
+
+                char inst_ch = to_char(inst);
+                char vol_ch = to_char(vol);
+                char command_ch = to_char(command >> 8);
+
+                if (inst == MUS_NOTE_INSTRUMENT_NONE)
+                {
+                    inst_ch = '-';
+                }
+
+                if (vol == MUS_NOTE_VOLUME_NONE)
+                {
+                    vol_ch = '-';
+                }
+
+                if (command == 0)
+                {
+                    snprintf(command_buffer, sizeof(command_buffer), "---");
+                }
+
+                else
+                {
+                    snprintf(command_buffer, sizeof(command_buffer), "%c%02X", command_ch, (command & 0xff));
+                }
+
+                snprintf(buffer, sizeof(buffer), "%s%c%c%s", (note == MUS_NOTE_NONE ? "---" : notename(note)), inst_ch, vol_ch, command_buffer);
+
+                canvas_draw_str(canvas, string_x, string_y, buffer);
+
+                if (note == MUS_NOTE_RELEASE)
+                {
+                    canvas_draw_icon(canvas, string_x, string_y - 5, &I_note_release);
+                }
+            }
+        }
+    }
+
+    if (tracker->editing && tracker->focus == EDIT_PATTERN)
+    {
+        uint8_t x = tracker->current_channel * 32 + tracker->patternx * 4 + (tracker->patternx > 0 ? 4 : 0) - 1;
+        uint8_t y = PATTERN_EDITOR_Y + 6 * 2 + 1;
+
+        canvas_draw_box(canvas, x, y, (tracker->patternx > 0 ? 5 : 9), 7);
+    }
 }
 
 #define SEQ_SLIDER_X (4 * (4 * 2 + 1) + 2)
 #define SEQ_SLIDER_Y (32)
 
-void draw_sequence_view(Canvas* canvas, FlizzerTrackerApp* tracker)
+void draw_sequence_view(Canvas *canvas, FlizzerTrackerApp *tracker)
 {
-	char buffer[4];
+    char buffer[4];
 
-	uint8_t sequence_position = tracker->tracker_engine.sequence_position;
+    uint8_t sequence_position = tracker->tracker_engine.sequence_position;
 
-	for(int pos = sequence_position - 2; pos < sequence_position + 3; pos++)
-	{
-		if(pos >= 0 && pos < tracker->song.num_sequence_steps)
-		{
-			for(int i = 0; i < SONG_MAX_CHANNELS; ++i)
-			{
-				uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[pos].pattern_indices[i];
+    for (int pos = sequence_position - 2; pos < sequence_position + 3; pos++)
+    {
+        if (pos >= 0 && pos < tracker->song.num_sequence_steps)
+        {
+            for (int i = 0; i < SONG_MAX_CHANNELS; ++i)
+            {
+                uint8_t current_pattern = tracker->tracker_engine.song->sequence.sequence_step[pos].pattern_indices[i];
 
-				uint8_t x = i * (4 * 2 + 1) + 3;
-				uint8_t y = (pos - (sequence_position - 2)) * 6 + 5;
+                uint8_t x = i * (4 * 2 + 1) + 3;
+                uint8_t y = (pos - (sequence_position - 2)) * 6 + 5;
 
-				snprintf(buffer, sizeof(buffer), "%02X", current_pattern);
-				canvas_draw_str(canvas, x, y, buffer);
-			}
-		}
-	}
+                snprintf(buffer, sizeof(buffer), "%02X", current_pattern);
+                canvas_draw_str(canvas, x, y, buffer);
+            }
+        }
+    }
 
-	//TODO: add song loop indication
+    // TODO: add song loop indication
 
-	canvas_set_color(canvas, ColorBlack);
+    canvas_set_color(canvas, ColorBlack);
 
-	canvas_draw_line(canvas, SEQ_SLIDER_X, 0, SEQ_SLIDER_X + 2, 0);
-	canvas_draw_line(canvas, SEQ_SLIDER_X, SEQ_SLIDER_Y, SEQ_SLIDER_X + 2, SEQ_SLIDER_Y);
+    canvas_draw_line(canvas, SEQ_SLIDER_X, 0, SEQ_SLIDER_X + 2, 0);
+    canvas_draw_line(canvas, SEQ_SLIDER_X, SEQ_SLIDER_Y, SEQ_SLIDER_X + 2, SEQ_SLIDER_Y);
 
-	canvas_draw_line(canvas, SEQ_SLIDER_X, 0, SEQ_SLIDER_X, SEQ_SLIDER_Y);
-	canvas_draw_line(canvas, SEQ_SLIDER_X + 2, 0, SEQ_SLIDER_X + 2, SEQ_SLIDER_Y);
+    canvas_draw_line(canvas, SEQ_SLIDER_X, 0, SEQ_SLIDER_X, SEQ_SLIDER_Y);
+    canvas_draw_line(canvas, SEQ_SLIDER_X + 2, 0, SEQ_SLIDER_X + 2, SEQ_SLIDER_Y);
 
-	uint8_t start_pos = sequence_position * (SEQ_SLIDER_Y - 2) / tracker->song.num_sequence_steps + 1;
-	uint8_t slider_length = (SEQ_SLIDER_Y - 2) / tracker->song.num_sequence_steps + 1;
+    uint8_t start_pos = sequence_position * (SEQ_SLIDER_Y - 2) / tracker->song.num_sequence_steps + 1;
+    uint8_t slider_length = (SEQ_SLIDER_Y - 2) / tracker->song.num_sequence_steps + 1;
 
-	canvas_draw_line(canvas, SEQ_SLIDER_X + 1, start_pos, SEQ_SLIDER_X + 1, (start_pos + slider_length));
+    canvas_draw_line(canvas, SEQ_SLIDER_X + 1, start_pos, SEQ_SLIDER_X + 1, (start_pos + slider_length));
 
-	canvas_set_color(canvas, ColorXOR);
+    canvas_set_color(canvas, ColorXOR);
 
-	if(tracker->editing && tracker->focus == EDIT_SEQUENCE)
-	{
-		uint8_t x = tracker->current_channel * (4 + 4 + 1) + (tracker->current_digit ? 4 : 0) + 2;
-		uint8_t y = 11;
+    if (tracker->editing && tracker->focus == EDIT_SEQUENCE)
+    {
+        uint8_t x = tracker->current_channel * (4 + 4 + 1) + (tracker->current_digit ? 4 : 0) + 2;
+        uint8_t y = 11;
 
-		canvas_draw_box(canvas, x, y, 5, 7);
-	}
+        canvas_draw_box(canvas, x, y, 5, 7);
+    }
 }
 
 #define member_size(type, member) sizeof(((type *)0)->member)
 
-#define SONG_HEADER_SIZE (member_size(TrackerSong, song_name) + member_size(TrackerSong, speed) + member_size(TrackerSong, rate) \
- + member_size(TrackerSong, loop_start) + member_size(TrackerSong, loop_end) + member_size(TrackerSong, num_patterns) \
- + member_size(TrackerSong, num_sequence_steps) + member_size(TrackerSong, num_instruments) + member_size(TrackerSong, pattern_length))
+#define SONG_HEADER_SIZE (member_size(TrackerSong, song_name) + member_size(TrackerSong, speed) + member_size(TrackerSong, rate) + member_size(TrackerSong, loop_start) + member_size(TrackerSong, loop_end) + member_size(TrackerSong, num_patterns) + member_size(TrackerSong, num_sequence_steps) + member_size(TrackerSong, num_instruments) + member_size(TrackerSong, pattern_length))
 
-uint32_t calculate_song_size(TrackerSong* song)
+uint32_t calculate_song_size(TrackerSong *song)
 {
-	uint32_t song_size = SONG_HEADER_SIZE + sizeof(Instrument) * song->num_instruments + sizeof(TrackerSongPatternStep) * song->num_patterns * song->pattern_length + sizeof(TrackerSongSequenceStep) * song->num_sequence_steps;
-	return song_size;
+    uint32_t song_size = SONG_HEADER_SIZE + sizeof(Instrument) * song->num_instruments + sizeof(TrackerSongPatternStep) * song->num_patterns * song->pattern_length + sizeof(TrackerSongSequenceStep) * song->num_sequence_steps;
+    return song_size;
 }
 
-void draw_generic_n_digit_field(FlizzerTrackerApp* tracker, Canvas* canvas, uint8_t focus, uint8_t param, const char* text, uint8_t x, uint8_t y, uint8_t digits) //last 1-2 symbols are digits we are editing
+void draw_generic_n_digit_field(FlizzerTrackerApp *tracker, Canvas *canvas, uint8_t focus, uint8_t param, const char *text, uint8_t x, uint8_t y, uint8_t digits) // last 1-2 symbols are digits we are editing
 {
-	canvas_draw_str(canvas, x, y, text);
-
-	if(tracker->focus == focus && tracker->selected_param == param && tracker->editing)
-	{
-		if(param != SI_SONGNAME && param != SI_INSTRUMENTNAME)
-		{
-			canvas_draw_box(canvas, x + strlen(text) * 4 - digits * 4 + tracker->current_digit * 4 - 1, y - 6, 5, 7);
-		}
-
-		else
-		{
-			canvas_draw_box(canvas, x - 1, y - 6, strlen(text) * 4 + 2, 7);
-		}
-	}
+    canvas_draw_str(canvas, x, y, text);
+
+    if (tracker->focus == focus && tracker->selected_param == param && tracker->editing)
+    {
+        if (param != SI_SONGNAME && param != SI_INSTRUMENTNAME)
+        {
+            canvas_draw_box(canvas, x + strlen(text) * 4 - digits * 4 + tracker->current_digit * 4 - 1, y - 6, 5, 7);
+        }
+
+        else
+        {
+            canvas_draw_box(canvas, x - 1, y - 6, strlen(text) * 4 + 2, 7);
+        }
+    }
 }
 
-void draw_songinfo_view(Canvas* canvas, FlizzerTrackerApp* tracker)
+void draw_songinfo_view(Canvas *canvas, FlizzerTrackerApp *tracker)
 {
-	char buffer[30];
-
-	snprintf(buffer, sizeof(buffer), "PAT.P.%02X/%02X", tracker->tracker_engine.pattern_position, tracker->song.pattern_length - 1);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_PATTERNPOS, buffer, 42, 5, 2);
-	snprintf(buffer, sizeof(buffer), "SEQ.P.%02X/%02X", tracker->tracker_engine.sequence_position, tracker->song.num_sequence_steps);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SEQUENCEPOS, buffer, 42, 11, 2);
-	snprintf(buffer, sizeof(buffer), "SPD.%02X", tracker->song.speed);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGSPEED, buffer, 42, 17, 2);
-	snprintf(buffer, sizeof(buffer), "RATE %02X", tracker->song.rate);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGRATE, buffer, 42 + 4 * 7, 17, 2);
-	snprintf(buffer, sizeof(buffer), "VOL %02X", tracker->tracker_engine.master_volume);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_MASTERVOL, buffer, 42 + 4 * 7 + 4 * 8, 17, 2);
-
-	snprintf(buffer, sizeof(buffer), "SONG:%s", tracker->song.song_name);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGNAME, buffer, 42, 23, 1);
-	snprintf(buffer, sizeof(buffer), "INST:%s", tracker->song.instrument[tracker->current_instrument]->name);
-	draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_INSTRUMENTNAME, buffer, 42, 29, 1);
-
-	uint32_t song_size = calculate_song_size(&tracker->song);
-	uint32_t free_bytes = memmgr_get_free_heap();
-	canvas_draw_line(canvas, 128 - 4 * 10 - 2, 0, 128 - 4 * 10 - 2, 10);
-
-	char song_size_buffer[12];
-	char free_bytes_buffer[12];
-
-	if(song_size > 999)
-	{
-		snprintf(song_size_buffer, sizeof(song_size_buffer), "TUNE:%.1fK", (double)song_size / (double)1024.0);
-	}
-
-	else
-	{
-		snprintf(song_size_buffer, sizeof(song_size_buffer), "TUNE:%ld", song_size);
-	}
-
-	if(free_bytes > 999)
-	{
-		snprintf(free_bytes_buffer, sizeof(song_size_buffer), "FREE:%.1fK", (double)free_bytes / (double)1024.0);
-	}
-
-	else
-	{
-		snprintf(free_bytes_buffer, sizeof(song_size_buffer), "FREE:%ld", free_bytes);
-	}
-
-	canvas_draw_str(canvas, 128 - 4 * 10, 5, song_size_buffer);
-	canvas_draw_str(canvas, 128 - 4 * 10, 11, free_bytes_buffer);
+    char buffer[30];
+
+    snprintf(buffer, sizeof(buffer), "PAT.P.%02X/%02X", tracker->tracker_engine.pattern_position, tracker->song.pattern_length - 1);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_PATTERNPOS, buffer, 42, 5, 2);
+    snprintf(buffer, sizeof(buffer), "SEQ.P.%02X/%02X", tracker->tracker_engine.sequence_position, tracker->song.num_sequence_steps);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SEQUENCEPOS, buffer, 42, 11, 2);
+    snprintf(buffer, sizeof(buffer), "SPD.%02X", tracker->song.speed);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGSPEED, buffer, 42, 17, 2);
+    snprintf(buffer, sizeof(buffer), "RATE %02X", tracker->song.rate);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGRATE, buffer, 42 + 4 * 7, 17, 2);
+    snprintf(buffer, sizeof(buffer), "VOL %02X", tracker->tracker_engine.master_volume);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_MASTERVOL, buffer, 42 + 4 * 7 + 4 * 8, 17, 2);
+
+    snprintf(buffer, sizeof(buffer), "SONG:%s", tracker->song.song_name);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_SONGNAME, buffer, 42, 23, 1);
+    snprintf(buffer, sizeof(buffer), "INST:%s", tracker->song.instrument[tracker->current_instrument]->name);
+    draw_generic_n_digit_field(tracker, canvas, EDIT_SONGINFO, SI_INSTRUMENTNAME, buffer, 42, 29, 1);
+
+    uint32_t song_size = calculate_song_size(&tracker->song);
+    uint32_t free_bytes = memmgr_get_free_heap();
+    canvas_draw_line(canvas, 128 - 4 * 10 - 2, 0, 128 - 4 * 10 - 2, 10);
+
+    char song_size_buffer[12];
+    char free_bytes_buffer[12];
+
+    if (song_size > 999)
+    {
+        snprintf(song_size_buffer, sizeof(song_size_buffer), "TUNE:%.1fK", (double)song_size / (double)1024.0);
+    }
+
+    else
+    {
+        snprintf(song_size_buffer, sizeof(song_size_buffer), "TUNE:%ld", song_size);
+    }
+
+    if (free_bytes > 999)
+    {
+        snprintf(free_bytes_buffer, sizeof(song_size_buffer), "FREE:%.1fK", (double)free_bytes / (double)1024.0);
+    }
+
+    else
+    {
+        snprintf(free_bytes_buffer, sizeof(song_size_buffer), "FREE:%ld", free_bytes);
+    }
+
+    canvas_draw_str(canvas, 128 - 4 * 10, 5, song_size_buffer);
+    canvas_draw_str(canvas, 128 - 4 * 10, 11, free_bytes_buffer);
 }

+ 4 - 4
view/pattern_editor.h

@@ -1,11 +1,11 @@
 #pragma once
 
-#include "../tracker_engine/tracker_engine_defs.h"
 #include "../flizzer_tracker.h"
+#include "../tracker_engine/tracker_engine_defs.h"
 
 #include <furi.h>
 #include <gui/gui.h>
 
-void draw_pattern_view(Canvas* canvas, FlizzerTrackerApp* tracker);
-void draw_sequence_view(Canvas* canvas, FlizzerTrackerApp* tracker);
-void draw_songinfo_view(Canvas* canvas, FlizzerTrackerApp* tracker);
+void draw_pattern_view(Canvas *canvas, FlizzerTrackerApp *tracker);
+void draw_sequence_view(Canvas *canvas, FlizzerTrackerApp *tracker);
+void draw_songinfo_view(Canvas *canvas, FlizzerTrackerApp *tracker);