| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #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;
- }
|