SimplyMinimal 3 лет назад
Родитель
Сommit
0f017643a2
1 измененных файлов с 197 добавлено и 0 удалено
  1. 197 0
      simon_says.c

+ 197 - 0
simon_says.c

@@ -0,0 +1,197 @@
+#include <furi.h>
+#include <furi_hal.h>
+#include <gui/gui.h>
+#include <gui/elements.h>
+#include <gui/icon.h>
+#include <input/input.h>
+#include <notification/notification.h>
+#include <notification/notification_messages.h>
+#include <stdbool.h> // Header-file for boolean data-type.
+#include <stdio.h>
+#include <string.h>
+
+/* generated by fbt from .png files in images folder */
+#include <simon_says_icons.h>
+
+#define WIDTH 64
+#define HEIGHT 144
+
+enum {
+    up,
+    down,
+    left,
+    right,
+} direction;
+
+typedef struct {
+    bool isPlayerTurn;
+} SimonSaysData;
+
+// Sequence to indicate that this is the beginning of a turn
+const NotificationSequence sequence_begin_turn = {
+    &message_display_backlight_on,
+    &message_vibro_on,
+    &message_note_g5,
+    &message_delay_50,
+    &message_note_c6,
+    &message_delay_50,
+    &message_note_e5,
+    &message_vibro_off,
+    &message_sound_off,
+    NULL,
+};
+
+// sequence to indicate that we've reached the end of a turn
+const NotificationSequence sequence_end_turn = {
+    &message_display_backlight_on,
+    &message_red_0,
+    &message_vibro_on,
+    &message_note_g5,
+    &message_delay_50,
+    &message_note_e5,
+    &message_delay_50,
+    &message_vibro_off,
+    &message_sound_off,
+    &message_do_not_reset,
+    NULL,
+};
+
+// Indicate that drawing is enabled.
+const NotificationSequence sequence_player_turn_enabled = {
+    &message_red_255,
+    &message_do_not_reset,
+    NULL,
+};
+
+// Indicate that drawing is disabled.
+const NotificationSequence sequence_player_turn_disabled = {
+    &message_red_0,
+    &message_do_not_reset,
+    NULL,
+};
+
+const NotificationSequence sequence_cleanup = {
+    &message_red_0,
+    &message_green_0,
+    &message_blue_0,
+    &message_sound_off,
+    &message_vibro_off,
+    NULL,
+};
+
+void simon_says_draw_callback(Canvas* canvas, void* ctx) {
+    const SimonSaysData* game_state = acquire_mutex((ValueMutex*)ctx, 25);
+    UNUSED(ctx);
+
+    canvas_clear(canvas);
+
+    canvas_draw_icon(canvas, 2, 2, &I_board); // Draw board
+
+    //release the mutex
+    release_mutex((ValueMutex*)ctx, game_state);
+}
+
+void game_tick(void* ctx) {
+    SimonSaysData* game_state = acquire_mutex((ValueMutex*)ctx, 25);
+    UNUSED(ctx);
+
+    //release the mutex
+    release_mutex((ValueMutex*)ctx, game_state);
+}
+
+void simon_says_input_callback(InputEvent* input_event, void* ctx) {
+    furi_assert(ctx);
+    FuriMessageQueue* event_queue = ctx;
+    furi_message_queue_put(event_queue, input_event, FuriWaitForever);
+}
+
+int32_t simon_says_app(void* p) {
+    UNUSED(p);
+    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+
+    SimonSaysData* simon_says_state = malloc(sizeof(SimonSaysData));
+    ValueMutex simon_value_mutex;
+    if(!init_mutex(&simon_value_mutex, simon_says_state, sizeof(SimonSaysData))) {
+        FURI_LOG_E("simon_says", "cannot create mutex\r\n");
+        free(simon_says_state);
+        return -1;
+    }
+
+    // Configure view port
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, simon_says_draw_callback, &simon_value_mutex);
+    view_port_input_callback_set(view_port, simon_says_input_callback, event_queue);
+
+    // Register view port in GUI
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
+
+    InputEvent event;
+
+    /* Create a timer. We do data analysis in the callback. */
+    FuriTimer* timer = furi_timer_alloc(game_tick, FuriTimerTypePeriodic, simon_says_state);
+    furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10);
+
+    while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
+        //break out of the loop if the back key is pressed
+        if(event.key == InputKeyBack && event.type == InputTypeLong) {
+            break;
+        }
+
+        // Placholder button states
+        if(event.key == InputKeyBack && event.type == InputTypeLong) {
+            view_port_update(view_port);
+        }
+
+        // Keep LED on while drawing
+        if(simon_says_state->isPlayerTurn) {
+            notification_message(notification, &sequence_player_turn_enabled);
+        } else {
+            notification_message(notification, &sequence_player_turn_disabled);
+        }
+
+        // Placholder button states
+        if(event.key == InputKeyOk && event.type == InputTypeShort) {
+            // Do Nothing
+        }
+
+        // Placholder button states
+        if(event.key == InputKeyOk && event.type == InputTypeLong) {
+            // notification_message(furi_record_open(RECORD_NOTIFICATION), &sequence_begin_turn);
+            notification_message(notification, &sequence_begin_turn);
+            view_port_update(view_port);
+        }
+
+        // Placholder button states
+        if(event.type == InputTypeShort || event.type == InputTypeRepeat ||
+           event.type == InputTypeLong) {
+            switch(event.key) {
+            case InputKeyUp:
+                break;
+            case InputKeyDown:
+                break;
+            case InputKeyLeft:
+                break;
+            case InputKeyRight:
+                break;
+            default:
+                break;
+            }
+
+            view_port_update(view_port);
+        }
+    }
+
+    furi_timer_free(timer);
+    notification_message(notification, &sequence_cleanup);
+    gui_remove_view_port(gui, view_port);
+    view_port_free(view_port);
+    furi_message_queue_free(event_queue);
+    free(simon_says_state);
+    furi_record_close(RECORD_NOTIFICATION);
+    furi_record_close(RECORD_GUI);
+
+    return 0;
+}