Browse Source

Update zeitraffer.c

theageoflove 2 years ago
parent
commit
41653a2823
1 changed files with 421 additions and 384 deletions
  1. 421 384
      zeitraffer.c

+ 421 - 384
zeitraffer.c

@@ -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;
+}