|
|
@@ -1,11 +1,17 @@
|
|
|
#include <stdio.h>
|
|
|
+
|
|
|
#include <furi.h>
|
|
|
+
|
|
|
#include <gui/gui.h>
|
|
|
+
|
|
|
#include <input/input.h>
|
|
|
+
|
|
|
#include <notification/notification_messages.h>
|
|
|
+
|
|
|
#include <flipper_format/flipper_format.h>
|
|
|
|
|
|
#include "gpio_item.h"
|
|
|
+
|
|
|
#include "zeitraffer_icons.h"
|
|
|
|
|
|
#define CONFIG_FILE_DIRECTORY_PATH "/ext/apps_data/zeitraffer"
|
|
|
@@ -24,405 +30,436 @@ int32_t Delay = 3; // Задержка на отскочить
|
|
|
bool Work = false;
|
|
|
|
|
|
const NotificationSequence sequence_click = {
|
|
|
- &message_note_c7,
|
|
|
- &message_delay_50,
|
|
|
- &message_sound_off,
|
|
|
- NULL,
|
|
|
+ &
|
|
|
+ message_note_c7,
|
|
|
+ &
|
|
|
+ message_delay_50,
|
|
|
+ &
|
|
|
+ message_sound_off,
|
|
|
+ NULL,
|
|
|
};
|
|
|
|
|
|
typedef enum {
|
|
|
- EventTypeTick,
|
|
|
- EventTypeInput,
|
|
|
-} EventType;
|
|
|
+ EventTypeTick,
|
|
|
+ EventTypeInput,
|
|
|
+}
|
|
|
+EventType;
|
|
|
|
|
|
typedef struct {
|
|
|
- EventType type;
|
|
|
- InputEvent input;
|
|
|
-} ZeitrafferEvent;
|
|
|
-
|
|
|
-static void draw_callback(Canvas* canvas, void* ctx) {
|
|
|
- UNUSED(ctx);
|
|
|
- char temp_str[36];
|
|
|
- canvas_clear(canvas);
|
|
|
- canvas_set_font(canvas, FontPrimary);
|
|
|
- switch (Count) {
|
|
|
- case -1:
|
|
|
- snprintf(temp_str,sizeof(temp_str),"Set: BULB %li sec",Time);
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- snprintf(temp_str,sizeof(temp_str),"Set: infinite, %li sec",Time);
|
|
|
- break;
|
|
|
- default:
|
|
|
- snprintf(temp_str,sizeof(temp_str),"Set: %li frames, %li sec",Count,Time);
|
|
|
- }
|
|
|
- canvas_draw_str(canvas, 3, 15, temp_str);
|
|
|
- snprintf(temp_str,sizeof(temp_str),"Left: %li frames, %li sec",WorkCount,WorkTime);
|
|
|
- canvas_draw_str(canvas, 3, 35, temp_str);
|
|
|
-
|
|
|
- switch (Backlight) {
|
|
|
- case 1:
|
|
|
- canvas_draw_str(canvas, 13, 55, "ON");
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- canvas_draw_str(canvas, 13, 55, "OFF");
|
|
|
- break;
|
|
|
- default:
|
|
|
- canvas_draw_str(canvas, 13, 55, "AUTO");
|
|
|
- }
|
|
|
-
|
|
|
- if(Work){
|
|
|
- canvas_draw_icon(canvas, 85, 41, &I_ButtonUpHollow_7x4);
|
|
|
- canvas_draw_icon(canvas, 85, 57, &I_ButtonDownHollow_7x4);
|
|
|
- canvas_draw_icon(canvas, 59, 48, &I_ButtonLeftHollow_4x7);
|
|
|
- canvas_draw_icon(canvas, 72, 48, &I_ButtonRightHollow_4x7);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- canvas_draw_icon(canvas, 85, 41, &I_ButtonUp_7x4);
|
|
|
- canvas_draw_icon(canvas, 85, 57, &I_ButtonDown_7x4);
|
|
|
- canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7);
|
|
|
- canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7);
|
|
|
- }
|
|
|
-
|
|
|
- canvas_draw_icon(canvas, 3, 48, &I_Pin_star_7x7);
|
|
|
-
|
|
|
- canvas_set_font(canvas, FontPrimary);
|
|
|
- canvas_draw_str(canvas, 65, 55, "F");
|
|
|
-
|
|
|
- canvas_set_font(canvas, FontPrimary);
|
|
|
- canvas_draw_str(canvas, 85, 55, "S");
|
|
|
-
|
|
|
-
|
|
|
- //canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7);
|
|
|
- //canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7);
|
|
|
-
|
|
|
- if(Work) {canvas_draw_icon(canvas, 106, 46, &I_loading_10px);}
|
|
|
+ EventType type;
|
|
|
+ InputEvent input;
|
|
|
+}
|
|
|
+ZeitrafferEvent;
|
|
|
+
|
|
|
+static void draw_callback(Canvas * canvas, void * ctx) {
|
|
|
+ UNUSED(ctx);
|
|
|
+ char temp_str[36];
|
|
|
+ canvas_clear(canvas);
|
|
|
+ canvas_set_font(canvas, FontPrimary);
|
|
|
+ switch (Count) {
|
|
|
+ case -1:
|
|
|
+ snprintf(temp_str, sizeof(temp_str), "Set: BULB %li sec", Time);
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ snprintf(temp_str, sizeof(temp_str), "Set: infinite, %li sec", Time);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ snprintf(temp_str, sizeof(temp_str), "Set: %li frames, %li sec", Count, Time);
|
|
|
+ }
|
|
|
+ canvas_draw_str(canvas, 3, 15, temp_str);
|
|
|
+ snprintf(temp_str, sizeof(temp_str), "Left: %li frames, %li sec", WorkCount, WorkTime);
|
|
|
+ canvas_draw_str(canvas, 3, 35, temp_str);
|
|
|
+
|
|
|
+ switch (Backlight) {
|
|
|
+ case 1:
|
|
|
+ canvas_draw_str(canvas, 13, 55, "ON");
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ canvas_draw_str(canvas, 13, 55, "OFF");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ canvas_draw_str(canvas, 13, 55, "AUTO");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Work) {
|
|
|
+ canvas_draw_icon(canvas, 85, 41, & I_ButtonUpHollow_7x4);
|
|
|
+ canvas_draw_icon(canvas, 85, 57, & I_ButtonDownHollow_7x4);
|
|
|
+ canvas_draw_icon(canvas, 59, 48, & I_ButtonLeftHollow_4x7);
|
|
|
+ canvas_draw_icon(canvas, 72, 48, & I_ButtonRightHollow_4x7);
|
|
|
+ } else {
|
|
|
+ canvas_draw_icon(canvas, 85, 41, & I_ButtonUp_7x4);
|
|
|
+ canvas_draw_icon(canvas, 85, 57, & I_ButtonDown_7x4);
|
|
|
+ canvas_draw_icon(canvas, 59, 48, & I_ButtonLeft_4x7);
|
|
|
+ canvas_draw_icon(canvas, 72, 48, & I_ButtonRight_4x7);
|
|
|
+ }
|
|
|
+
|
|
|
+ canvas_draw_icon(canvas, 3, 48, & I_Pin_star_7x7);
|
|
|
+
|
|
|
+ canvas_set_font(canvas, FontPrimary);
|
|
|
+ canvas_draw_str(canvas, 65, 55, "F");
|
|
|
+
|
|
|
+ canvas_set_font(canvas, FontPrimary);
|
|
|
+ canvas_draw_str(canvas, 85, 55, "S");
|
|
|
+
|
|
|
+ //canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7);
|
|
|
+ //canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7);
|
|
|
+
|
|
|
+ if (Work) {
|
|
|
+ canvas_draw_icon(canvas, 106, 46, & I_loading_10px);
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
-static void input_callback(InputEvent* input_event, void* ctx) {
|
|
|
- // Проверяем, что контекст не нулевой
|
|
|
- furi_assert(ctx);
|
|
|
- FuriMessageQueue* event_queue = ctx;
|
|
|
+static void input_callback(InputEvent * input_event, void * ctx) {
|
|
|
+ // Проверяем, что контекст не нулевой
|
|
|
+ furi_assert(ctx);
|
|
|
+ FuriMessageQueue * event_queue = ctx;
|
|
|
|
|
|
- ZeitrafferEvent event = {.type = EventTypeInput, .input = *input_event};
|
|
|
- furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
|
|
+ ZeitrafferEvent event = {
|
|
|
+ .type = EventTypeInput,
|
|
|
+ .input = * input_event
|
|
|
+ };
|
|
|
+ furi_message_queue_put(event_queue, & event, FuriWaitForever);
|
|
|
}
|
|
|
|
|
|
-static void timer_callback(FuriMessageQueue* event_queue) {
|
|
|
- // Проверяем, что контекст не нулевой
|
|
|
- furi_assert(event_queue);
|
|
|
+static void timer_callback(FuriMessageQueue * event_queue) {
|
|
|
+ // Проверяем, что контекст не нулевой
|
|
|
+ furi_assert(event_queue);
|
|
|
|
|
|
- ZeitrafferEvent event = {.type = EventTypeTick};
|
|
|
- furi_message_queue_put(event_queue, &event, 0);
|
|
|
+ ZeitrafferEvent event = {
|
|
|
+ .type = EventTypeTick
|
|
|
+ };
|
|
|
+ furi_message_queue_put(event_queue, & event, 0);
|
|
|
}
|
|
|
|
|
|
-int32_t zeitraffer_app(void* p) {
|
|
|
- UNUSED(p);
|
|
|
-
|
|
|
- // Текущее событие типа кастомного типа ZeitrafferEvent
|
|
|
- ZeitrafferEvent event;
|
|
|
- // Очередь событий на 8 элементов размера ZeitrafferEvent
|
|
|
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(ZeitrafferEvent));
|
|
|
-
|
|
|
- // Создаем новый view port
|
|
|
- ViewPort* view_port = view_port_alloc();
|
|
|
- // Создаем callback отрисовки, без контекста
|
|
|
- view_port_draw_callback_set(view_port, draw_callback, NULL);
|
|
|
- // Создаем callback нажатий на клавиши, в качестве контекста передаем
|
|
|
- // нашу очередь сообщений, чтоб запихивать в неё эти события
|
|
|
- view_port_input_callback_set(view_port, input_callback, event_queue);
|
|
|
-
|
|
|
- // Создаем GUI приложения
|
|
|
- Gui* gui = furi_record_open(RECORD_GUI);
|
|
|
- // Подключаем view port к GUI в полноэкранном режиме
|
|
|
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
|
|
-
|
|
|
- // Конфигурим пины
|
|
|
- gpio_item_configure_all_pins(GpioModeOutputPushPull);
|
|
|
-
|
|
|
- // Создаем периодический таймер с коллбэком, куда в качестве
|
|
|
- // контекста будет передаваться наша очередь событий
|
|
|
- FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
|
|
|
- // Запускаем таймер
|
|
|
- //furi_timer_start(timer, 1500);
|
|
|
-
|
|
|
- // Включаем нотификации
|
|
|
- NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION);
|
|
|
-
|
|
|
-
|
|
|
- Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
|
-
|
|
|
- // Загружаем настройки
|
|
|
- FlipperFormat* load = flipper_format_file_alloc(storage);
|
|
|
-
|
|
|
- do {
|
|
|
- if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_file_open_existing(load, CONFIG_FILE_PATH)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_read_int32(load, "Time", &Time, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_read_int32(load, "Count", &Count, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_read_int32(load, "Backlight", &Backlight, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_read_int32(load, "Delay", &Delay, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- notification_message(notifications, &sequence_success);
|
|
|
-
|
|
|
- } while(0);
|
|
|
-
|
|
|
- flipper_format_free(load);
|
|
|
-
|
|
|
- // Бесконечный цикл обработки очереди событий
|
|
|
- while(1) {
|
|
|
- // Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
|
|
|
- // и проверяем, что у нас получилось это сделать
|
|
|
- furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
|
|
|
-
|
|
|
- // Наше событие — это нажатие кнопки
|
|
|
- if(event.type == EventTypeInput) {
|
|
|
- if(event.input.type == InputTypeShort) { // Короткие нажатия
|
|
|
-
|
|
|
- if(event.input.key == InputKeyBack) {
|
|
|
- if(Work) { // Если таймер запущен - нефиг мацать кнопки!
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- WorkCount = Count;
|
|
|
- WorkTime = 3;
|
|
|
- if (Count == 0) {
|
|
|
- InfiniteShot = true;
|
|
|
- WorkCount = 1;
|
|
|
- }
|
|
|
- else
|
|
|
- InfiniteShot = false;
|
|
|
-
|
|
|
- notification_message(notifications, &sequence_success);
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyRight) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Count++;
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyLeft) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Count--;
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyUp) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Time++;
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyDown) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Time--;
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyOk) {
|
|
|
-
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- furi_timer_stop(timer);
|
|
|
- Work = false;
|
|
|
- }
|
|
|
- else {
|
|
|
- furi_timer_start(timer, 1000);
|
|
|
- Work = true;
|
|
|
-
|
|
|
- if (WorkCount == 0)
|
|
|
- WorkCount = Count;
|
|
|
-
|
|
|
- if (WorkTime == 0)
|
|
|
- WorkTime = Delay;
|
|
|
-
|
|
|
- if (Count == 1)
|
|
|
- WorkTime = Time;
|
|
|
-
|
|
|
- if (Count == 0) {
|
|
|
- InfiniteShot = true;
|
|
|
- WorkCount = 1;
|
|
|
- }
|
|
|
- else
|
|
|
- InfiniteShot = false;
|
|
|
-
|
|
|
- if (Count == -1) {
|
|
|
- gpio_item_set_pin(4, true);
|
|
|
- gpio_item_set_pin(5, true);
|
|
|
- Bulb = true;
|
|
|
- WorkCount = 1;
|
|
|
- WorkTime = Time;
|
|
|
- }
|
|
|
- else
|
|
|
- Bulb = false;
|
|
|
-
|
|
|
- notification_message(notifications, &sequence_success);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.type == InputTypeLong) { // Длинные нажатия
|
|
|
- // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
|
|
|
- if(event.input.key == InputKeyBack) {
|
|
|
- if(furi_timer_is_running(timer)) { // А если работает таймер - не выходим :D
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- gpio_item_set_all_pins(false);
|
|
|
- furi_timer_stop(timer);
|
|
|
- notification_message(notifications, &sequence_display_backlight_enforce_auto);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyOk) {
|
|
|
- // Нам ваша подсветка и нахой не нужна! Или нужна?
|
|
|
- Backlight++;
|
|
|
- if (Backlight > 2) Backlight = 0;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if(event.input.type == InputTypeRepeat) { // Зажатые кнопки
|
|
|
- if(event.input.key == InputKeyRight) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Count = Count+10;
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyLeft) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Count = Count-10;
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyUp) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Time = Time+10;
|
|
|
- }
|
|
|
- }
|
|
|
- if(event.input.key == InputKeyDown) {
|
|
|
- if(furi_timer_is_running(timer)) {
|
|
|
- notification_message(notifications, &sequence_error);
|
|
|
- }
|
|
|
- else {
|
|
|
- Time = Time-10;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+int32_t zeitraffer_app(void * p) {
|
|
|
+ UNUSED(p);
|
|
|
+
|
|
|
+ // Текущее событие типа кастомного типа ZeitrafferEvent
|
|
|
+ ZeitrafferEvent event;
|
|
|
+ // Очередь событий на 8 элементов размера ZeitrafferEvent
|
|
|
+ FuriMessageQueue * event_queue = furi_message_queue_alloc(8, sizeof(ZeitrafferEvent));
|
|
|
+
|
|
|
+ // Создаем новый view port
|
|
|
+ ViewPort * view_port = view_port_alloc();
|
|
|
+ // Создаем callback отрисовки, без контекста
|
|
|
+ view_port_draw_callback_set(view_port, draw_callback, NULL);
|
|
|
+ // Создаем callback нажатий на клавиши, в качестве контекста передаем
|
|
|
+ // нашу очередь сообщений, чтоб запихивать в неё эти события
|
|
|
+ view_port_input_callback_set(view_port, input_callback, event_queue);
|
|
|
+
|
|
|
+ // Создаем GUI приложения
|
|
|
+ Gui * gui = furi_record_open(RECORD_GUI);
|
|
|
+ // Подключаем view port к GUI в полноэкранном режиме
|
|
|
+ gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
|
|
+
|
|
|
+ // Конфигурим пины
|
|
|
+ gpio_item_configure_all_pins(GpioModeOutputPushPull);
|
|
|
+
|
|
|
+ // Создаем периодический таймер с коллбэком, куда в качестве
|
|
|
+ // контекста будет передаваться наша очередь событий
|
|
|
+ FuriTimer * timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
|
|
|
+ // Запускаем таймер
|
|
|
+ //furi_timer_start(timer, 1500);
|
|
|
+
|
|
|
+ // Включаем нотификации
|
|
|
+ NotificationApp * notifications = furi_record_open(RECORD_NOTIFICATION);
|
|
|
+
|
|
|
+ Storage * storage = furi_record_open(RECORD_STORAGE);
|
|
|
+
|
|
|
+ // Загружаем настройки
|
|
|
+ FlipperFormat * load = flipper_format_file_alloc(storage);
|
|
|
+
|
|
|
+ do {
|
|
|
+ if (!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_file_open_existing(load, CONFIG_FILE_PATH)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_read_int32(load, "Time", & Time, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_read_int32(load, "Count", & Count, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_read_int32(load, "Backlight", & Backlight, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_read_int32(load, "Delay", & Delay, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ notification_message(notifications, & sequence_success);
|
|
|
+
|
|
|
+ } while (0);
|
|
|
+
|
|
|
+ flipper_format_free(load);
|
|
|
+
|
|
|
+ // Бесконечный цикл обработки очереди событий
|
|
|
+ while (1) {
|
|
|
+ // Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
|
|
|
+ // и проверяем, что у нас получилось это сделать
|
|
|
+ furi_check(furi_message_queue_get(event_queue, & event, FuriWaitForever) == FuriStatusOk);
|
|
|
+
|
|
|
+ // Наше событие — это нажатие кнопки
|
|
|
+ if (event.type == EventTypeInput) {
|
|
|
+ if (event.input.type == InputTypeShort) { // Короткие нажатия
|
|
|
+
|
|
|
+ if (event.input.key == InputKeyBack) {
|
|
|
+ if (Work) { // Если таймер запущен - нефиг мацать кнопки!
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ WorkCount = Count;
|
|
|
+ WorkTime = 3;
|
|
|
+ if (Count == 0) {
|
|
|
+ InfiniteShot = true;
|
|
|
+ WorkCount = 1;
|
|
|
+ } else
|
|
|
+ InfiniteShot = false;
|
|
|
+
|
|
|
+ notification_message(notifications, & sequence_success);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // Наше событие — это сработавший таймер
|
|
|
- else if(event.type == EventTypeTick) {
|
|
|
-
|
|
|
- WorkTime--;
|
|
|
-
|
|
|
- if( WorkTime < 1 ) { // фоткаем
|
|
|
- notification_message(notifications, &sequence_blink_white_100);
|
|
|
- if (Bulb) {
|
|
|
- gpio_item_set_all_pins(false); WorkCount = 0;
|
|
|
- }
|
|
|
- else {
|
|
|
- WorkCount--;
|
|
|
- view_port_update(view_port);
|
|
|
- notification_message(notifications, &sequence_click);
|
|
|
- // Дрыгаем ногами
|
|
|
- //gpio_item_set_all_pins(true);
|
|
|
- gpio_item_set_pin(4, true);
|
|
|
- gpio_item_set_pin(5, true);
|
|
|
- furi_delay_ms(400); // На короткие нажатия фотик плохо реагирует
|
|
|
- gpio_item_set_pin(4, false);
|
|
|
- gpio_item_set_pin(5, false);
|
|
|
- //gpio_item_set_all_pins(false);
|
|
|
-
|
|
|
- if (InfiniteShot) WorkCount++;
|
|
|
-
|
|
|
- WorkTime = Time;
|
|
|
- view_port_update(view_port);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // Отправляем нотификацию мигания синим светодиодом
|
|
|
- notification_message(notifications, &sequence_blink_blue_100);
|
|
|
- }
|
|
|
-
|
|
|
- if( WorkCount < 1 ) { // закончили
|
|
|
- Work = false;
|
|
|
- gpio_item_set_all_pins(false);
|
|
|
- furi_timer_stop(timer);
|
|
|
- notification_message(notifications, &sequence_audiovisual_alert);
|
|
|
- WorkTime = 3;
|
|
|
- WorkCount = 0;
|
|
|
- }
|
|
|
-
|
|
|
- switch (Backlight) { // чо по подсветке?
|
|
|
- case 1:
|
|
|
- notification_message(notifications, &sequence_display_backlight_on);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- notification_message(notifications, &sequence_display_backlight_off);
|
|
|
- break;
|
|
|
- default:
|
|
|
- notification_message(notifications, &sequence_display_backlight_enforce_auto);
|
|
|
- }
|
|
|
-
|
|
|
+ if (event.input.key == InputKeyRight) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Count++;
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyLeft) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Count--;
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyUp) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Time++;
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyDown) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Time--;
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyOk) {
|
|
|
+
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ furi_timer_stop(timer);
|
|
|
+ Work = false;
|
|
|
+ } else {
|
|
|
+ furi_timer_start(timer, 1000);
|
|
|
+ Work = true;
|
|
|
+
|
|
|
+ if (WorkCount == 0)
|
|
|
+ WorkCount = Count;
|
|
|
+
|
|
|
+ if (WorkTime == 0)
|
|
|
+ WorkTime = Delay;
|
|
|
+
|
|
|
+ if (Count == 1)
|
|
|
+ WorkTime = Time;
|
|
|
+
|
|
|
+ if (Count == 0) {
|
|
|
+ InfiniteShot = true;
|
|
|
+ WorkCount = 1;
|
|
|
+ } else
|
|
|
+ InfiniteShot = false;
|
|
|
+
|
|
|
+ if (Count == -1) {
|
|
|
+ gpio_item_set_pin(4, true);
|
|
|
+ gpio_item_set_pin(5, true);
|
|
|
+ Bulb = true;
|
|
|
+ WorkCount = 1;
|
|
|
+ WorkTime = Time;
|
|
|
+ } else
|
|
|
+ Bulb = false;
|
|
|
+
|
|
|
+ notification_message(notifications, & sequence_success);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.type == InputTypeLong) { // Длинные нажатия
|
|
|
+ // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
|
|
|
+ if (event.input.key == InputKeyBack) {
|
|
|
+ if (furi_timer_is_running(timer)) { // А если работает таймер - не выходим :D
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ gpio_item_set_all_pins(false);
|
|
|
+ furi_timer_stop(timer);
|
|
|
+ notification_message(notifications, & sequence_display_backlight_enforce_auto);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyOk) {
|
|
|
+ // Нам ваша подсветка и нахой не нужна! Или нужна?
|
|
|
+ Backlight++;
|
|
|
+ if (Backlight > 2) Backlight = 0;
|
|
|
}
|
|
|
- if (Time < 1) Time = 1; // Не даём открутить таймер меньше единицы
|
|
|
- if (Count < -1) Count = 0; // А тут даём, бо 0 кадров это бесконечная съёмка, а -1 кадров - BULB
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // Схороняем настройки
|
|
|
- FlipperFormat* save = flipper_format_file_alloc(storage);
|
|
|
-
|
|
|
- do {
|
|
|
-
|
|
|
- if(!flipper_format_file_open_always(save, CONFIG_FILE_PATH)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_header_cstr(save, "Zeitraffer", 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_comment_cstr(save, "Zeitraffer app settings: № of frames, interval time, backlight type, Delay")) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_int32(save, "Time", &Time, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_int32(save, "Count", &Count, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_int32(save, "Backlight", &Backlight, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
- if(!flipper_format_write_int32(save, "Delay", &Delay, 1)) {notification_message(notifications, &sequence_error); break;}
|
|
|
-
|
|
|
- } while(0);
|
|
|
-
|
|
|
- flipper_format_free(save);
|
|
|
-
|
|
|
- furi_record_close(RECORD_STORAGE);
|
|
|
-
|
|
|
- // Очищаем таймер
|
|
|
- furi_timer_free(timer);
|
|
|
-
|
|
|
- // Специальная очистка памяти, занимаемой очередью
|
|
|
- furi_message_queue_free(event_queue);
|
|
|
-
|
|
|
- // Чистим созданные объекты, связанные с интерфейсом
|
|
|
- gui_remove_view_port(gui, view_port);
|
|
|
- view_port_free(view_port);
|
|
|
- furi_record_close(RECORD_GUI);
|
|
|
|
|
|
- // Очищаем нотификации
|
|
|
- furi_record_close(RECORD_NOTIFICATION);
|
|
|
+ }
|
|
|
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ if (event.input.type == InputTypeRepeat) { // Зажатые кнопки
|
|
|
+ if (event.input.key == InputKeyRight) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Count = Count + 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyLeft) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Count = Count - 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyUp) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Time = Time + 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.input.key == InputKeyDown) {
|
|
|
+ if (furi_timer_is_running(timer)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ } else {
|
|
|
+ Time = Time - 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Наше событие — это сработавший таймер
|
|
|
+ else if (event.type == EventTypeTick) {
|
|
|
+
|
|
|
+ WorkTime--;
|
|
|
+
|
|
|
+ if (WorkTime < 1) { // фоткаем
|
|
|
+ notification_message(notifications, & sequence_blink_white_100);
|
|
|
+ if (Bulb) {
|
|
|
+ gpio_item_set_all_pins(false);
|
|
|
+ WorkCount = 0;
|
|
|
+ } else {
|
|
|
+ WorkCount--;
|
|
|
+ view_port_update(view_port);
|
|
|
+ notification_message(notifications, & sequence_click);
|
|
|
+ // Дрыгаем ногами
|
|
|
+ //gpio_item_set_all_pins(true);
|
|
|
+ gpio_item_set_pin(4, true);
|
|
|
+ gpio_item_set_pin(5, true);
|
|
|
+ furi_delay_ms(400); // На короткие нажатия фотик плохо реагирует
|
|
|
+ gpio_item_set_pin(4, false);
|
|
|
+ gpio_item_set_pin(5, false);
|
|
|
+ //gpio_item_set_all_pins(false);
|
|
|
+
|
|
|
+ if (InfiniteShot) WorkCount++;
|
|
|
+
|
|
|
+ WorkTime = Time;
|
|
|
+ view_port_update(view_port);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Отправляем нотификацию мигания синим светодиодом
|
|
|
+ notification_message(notifications, & sequence_blink_blue_100);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WorkCount < 1) { // закончили
|
|
|
+ Work = false;
|
|
|
+ gpio_item_set_all_pins(false);
|
|
|
+ furi_timer_stop(timer);
|
|
|
+ notification_message(notifications, & sequence_audiovisual_alert);
|
|
|
+ WorkTime = 3;
|
|
|
+ WorkCount = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (Backlight) { // чо по подсветке?
|
|
|
+ case 1:
|
|
|
+ notification_message(notifications, & sequence_display_backlight_on);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ notification_message(notifications, & sequence_display_backlight_off);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ notification_message(notifications, & sequence_display_backlight_enforce_auto);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (Time < 1) Time = 1; // Не даём открутить таймер меньше единицы
|
|
|
+ if (Count < -1) Count = 0; // А тут даём, бо 0 кадров это бесконечная съёмка, а -1 кадров - BULB
|
|
|
+ }
|
|
|
+
|
|
|
+ // Схороняем настройки
|
|
|
+ FlipperFormat * save = flipper_format_file_alloc(storage);
|
|
|
+
|
|
|
+ do {
|
|
|
+
|
|
|
+ if (!flipper_format_file_open_always(save, CONFIG_FILE_PATH)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_header_cstr(save, "Zeitraffer", 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_comment_cstr(save, "Zeitraffer app settings: № of frames, interval time, backlight type, Delay")) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_int32(save, "Time", & Time, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_int32(save, "Count", & Count, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_int32(save, "Backlight", & Backlight, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!flipper_format_write_int32(save, "Delay", & Delay, 1)) {
|
|
|
+ notification_message(notifications, & sequence_error);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while (0);
|
|
|
+
|
|
|
+ flipper_format_free(save);
|
|
|
+
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+
|
|
|
+ // Очищаем таймер
|
|
|
+ furi_timer_free(timer);
|
|
|
+
|
|
|
+ // Специальная очистка памяти, занимаемой очередью
|
|
|
+ furi_message_queue_free(event_queue);
|
|
|
+
|
|
|
+ // Чистим созданные объекты, связанные с интерфейсом
|
|
|
+ gui_remove_view_port(gui, view_port);
|
|
|
+ view_port_free(view_port);
|
|
|
+ furi_record_close(RECORD_GUI);
|
|
|
+
|
|
|
+ // Очищаем нотификации
|
|
|
+ furi_record_close(RECORD_NOTIFICATION);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|