Rename Irukagotchi to Dolphin. Add basic game state structures. (#268)
* Rename Irukagotchi to Dolphin. Add basic game state structures. * Dolphin: state, counters, api. BT: shared access to flash. Flash: write api. * add fake -1 deeds, example of changing icounter Co-authored-by: coreglitch <mail@s3f.ru>
This commit is contained in:
		
							parent
							
								
									3ba1738acd
								
							
						
					
					
						commit
						73ecc7cde6
					
				| @ -30,7 +30,7 @@ void app_loader(void* p); | |||||||
| void cc1101_workaround(void* p); | void cc1101_workaround(void* p); | ||||||
| void lf_rfid_workaround(void* p); | void lf_rfid_workaround(void* p); | ||||||
| void nfc_task(void* p); | void nfc_task(void* p); | ||||||
| void irukagotchi_task(void* p); | void dolphin_task(void* p); | ||||||
| void power_task(void* p); | void power_task(void* p); | ||||||
| void bt_task(void* p); | void bt_task(void* p); | ||||||
| void sd_card_test(void* p); | void sd_card_test(void* p); | ||||||
| @ -88,9 +88,9 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { | |||||||
|      .icon = A_Plugins_14}, |      .icon = A_Plugins_14}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_IRUKAGOTCHI | #ifdef APP_DOLPHIN | ||||||
|     {.app = irukagotchi_task, |     {.app = dolphin_task, | ||||||
|      .name = "irukagotchi_task", |      .name = "dolphin_task", | ||||||
|      .libs = {1, FURI_LIB{"menu_task"}}, |      .libs = {1, FURI_LIB{"menu_task"}}, | ||||||
|      .icon = A_Plugins_14}, |      .icon = A_Plugins_14}, | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ APP_POWER = 1 | |||||||
| APP_BT = 1 | APP_BT = 1 | ||||||
| APP_CLI = 1 | APP_CLI = 1 | ||||||
| BUILD_IRDA  = 1 | BUILD_IRDA  = 1 | ||||||
| APP_IRUKAGOTCHI = 1 | APP_DOLPHIN = 1 | ||||||
| BUILD_EXAMPLE_BLINK = 1 | BUILD_EXAMPLE_BLINK = 1 | ||||||
| BUILD_EXAMPLE_UART_WRITE = 1 | BUILD_EXAMPLE_UART_WRITE = 1 | ||||||
| BUILD_EXAMPLE_INPUT_DUMP = 1 | BUILD_EXAMPLE_INPUT_DUMP = 1 | ||||||
| @ -36,11 +36,11 @@ CFLAGS		+= -DAPP_NFC | |||||||
| C_SOURCES	+= $(wildcard $(APP_DIR)/nfc/*.c) | C_SOURCES	+= $(wildcard $(APP_DIR)/nfc/*.c) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| APP_IRUKAGOTCHI ?= 0 | APP_DOLPHIN ?= 0 | ||||||
| ifeq ($(APP_IRUKAGOTCHI), 1) | ifeq ($(APP_DOLPHIN), 1) | ||||||
| APP_MENU	= 1 | APP_MENU	= 1 | ||||||
| CFLAGS		+= -DAPP_IRUKAGOTCHI | CFLAGS		+= -DAPP_DOLPHIN | ||||||
| C_SOURCES	+= $(wildcard $(APP_DIR)/irukagotchi/*.c) | C_SOURCES	+= $(wildcard $(APP_DIR)/dolphin/*.c) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| APP_POWER ?= 0 | APP_POWER ?= 0 | ||||||
|  | |||||||
							
								
								
									
										124
									
								
								applications/dolphin/dolphin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								applications/dolphin/dolphin.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | |||||||
|  | #include "dolphin_i.h" | ||||||
|  | 
 | ||||||
|  | void dolphin_draw_callback(Canvas* canvas, void* context) { | ||||||
|  |     Dolphin* dolphin = context; | ||||||
|  | 
 | ||||||
|  |     canvas_clear(canvas); | ||||||
|  |     canvas_set_color(canvas, ColorBlack); | ||||||
|  |     if(dolphin->screen == DolphinScreenIdle) { | ||||||
|  |         dolphin_draw_idle(canvas, dolphin); | ||||||
|  |     } else if(dolphin->screen == DolphinScreenDebug) { | ||||||
|  |         dolphin_draw_debug(canvas, dolphin); | ||||||
|  |     } else if(dolphin->screen == DolphinScreenStats) { | ||||||
|  |         dolphin_draw_stats(canvas, dolphin); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_draw_idle(Canvas* canvas, Dolphin* dolphin) { | ||||||
|  |     canvas_draw_icon(canvas, 128 - 80, 0, dolphin->icon); | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|  |     canvas_draw_str(canvas, 2, 10, "/\\: Stats"); | ||||||
|  |     canvas_draw_str(canvas, 5, 32, "OK: Menu"); | ||||||
|  |     canvas_draw_str(canvas, 2, 52, "\\/: Version"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_draw_debug(Canvas* canvas, Dolphin* dolphin) { | ||||||
|  |     canvas_set_font(canvas, FontPrimary); | ||||||
|  |     canvas_draw_str(canvas, 2, 10, "Version info:"); | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|  |     canvas_draw_str(canvas, 5, 22, TARGET " " BUILD_DATE); | ||||||
|  |     canvas_draw_str(canvas, 5, 32, GIT_BRANCH); | ||||||
|  |     canvas_draw_str(canvas, 5, 42, GIT_BRANCH_NUM); | ||||||
|  |     canvas_draw_str(canvas, 5, 52, GIT_COMMIT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_draw_stats(Canvas* canvas, Dolphin* dolphin) { | ||||||
|  |     canvas_set_font(canvas, FontPrimary); | ||||||
|  |     canvas_draw_str(canvas, 2, 10, "Dolphin stats:"); | ||||||
|  | 
 | ||||||
|  |     char buffer[64]; | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|  |     snprintf(buffer, 64, "Icounter: %ld", dolphin_state_get_icounter(dolphin->state)); | ||||||
|  |     canvas_draw_str(canvas, 5, 22, buffer); | ||||||
|  |     snprintf(buffer, 64, "Butthurt: %ld", dolphin_state_get_butthurt(dolphin->state)); | ||||||
|  |     canvas_draw_str(canvas, 5, 32, buffer); | ||||||
|  |     canvas_draw_str(canvas, 5, 40, "< > change icounter"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_input_callback(InputEvent* event, void* context) { | ||||||
|  |     Dolphin* dolphin = context; | ||||||
|  | 
 | ||||||
|  |     if(!event->state) return; | ||||||
|  | 
 | ||||||
|  |     if(event->input == InputOk) { | ||||||
|  |         with_value_mutex( | ||||||
|  |             dolphin->menu_vm, (Menu * menu) { menu_ok(menu); }); | ||||||
|  |     } else if(event->input == InputUp) { | ||||||
|  |         if(dolphin->screen != DolphinScreenStats) { | ||||||
|  |             dolphin->screen++; | ||||||
|  |         } | ||||||
|  |     } else if(event->input == InputDown) { | ||||||
|  |         if(dolphin->screen != DolphinScreenDebug) { | ||||||
|  |             dolphin->screen--; | ||||||
|  |         } | ||||||
|  |     } else if(event->input == InputBack) { | ||||||
|  |         dolphin->screen = DolphinScreenIdle; | ||||||
|  |     } else if(event->input == InputLeft) { | ||||||
|  |         dolphin_deed(dolphin, DolphinDeedIButtonEmulate); | ||||||
|  |     } else if(event->input == InputRight) { | ||||||
|  |         dolphin_deed(dolphin, DolphinDeedWrong); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     widget_update(dolphin->widget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Dolphin* dolphin_alloc() { | ||||||
|  |     Dolphin* dolphin = furi_alloc(sizeof(Dolphin)); | ||||||
|  | 
 | ||||||
|  |     dolphin->icon = assets_icons_get(I_Flipper_young_80x60); | ||||||
|  |     icon_start_animation(dolphin->icon); | ||||||
|  | 
 | ||||||
|  |     dolphin->widget = widget_alloc(); | ||||||
|  |     widget_draw_callback_set(dolphin->widget, dolphin_draw_callback, dolphin); | ||||||
|  |     widget_input_callback_set(dolphin->widget, dolphin_input_callback, dolphin); | ||||||
|  | 
 | ||||||
|  |     dolphin->menu_vm = furi_open("menu"); | ||||||
|  |     furi_check(dolphin->menu_vm); | ||||||
|  | 
 | ||||||
|  |     dolphin->state = dolphin_state_alloc(); | ||||||
|  | 
 | ||||||
|  |     dolphin->screen = DolphinScreenIdle; | ||||||
|  | 
 | ||||||
|  |     dolphin->event_queue = osMessageQueueNew(8, sizeof(DolphinEvent), NULL); | ||||||
|  |     furi_check(dolphin->event_queue); | ||||||
|  |     return dolphin; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) { | ||||||
|  |     DolphinEvent event; | ||||||
|  |     event.type = DolphinEventTypeDeed; | ||||||
|  |     event.deed = deed; | ||||||
|  |     furi_check(osMessageQueuePut(dolphin->event_queue, &event, 0, osWaitForever) == osOK); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_task() { | ||||||
|  |     Dolphin* dolphin = dolphin_alloc(); | ||||||
|  | 
 | ||||||
|  |     Gui* gui = furi_open("gui"); | ||||||
|  |     gui_add_widget(gui, dolphin->widget, GuiLayerNone); | ||||||
|  | 
 | ||||||
|  |     if(!furi_create("dolphin", dolphin)) { | ||||||
|  |         printf("[dolphin_task] cannot create the dolphin record\n"); | ||||||
|  |         furiac_exit(NULL); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furiac_ready(); | ||||||
|  | 
 | ||||||
|  |     DolphinEvent event; | ||||||
|  |     while(1) { | ||||||
|  |         furi_check(osMessageQueueGet(dolphin->event_queue, &event, NULL, osWaitForever) == osOK); | ||||||
|  |         if(event.type == DolphinEventTypeDeed) { | ||||||
|  |             dolphin_state_on_deed(dolphin->state, event.deed); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								applications/dolphin/dolphin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								applications/dolphin/dolphin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "dolphin_deed.h" | ||||||
|  | 
 | ||||||
|  | typedef struct Dolphin Dolphin; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Deed complete notification. Call it on deed completion. | ||||||
|  |  * See dolphin_deed.h for available deeds. In futures it will become part of assets. | ||||||
|  |  */ | ||||||
|  | void dolphin_deed(Dolphin* dolphin, DolphinDeed deed); | ||||||
							
								
								
									
										12
									
								
								applications/dolphin/dolphin_deed.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/dolphin/dolphin_deed.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | #include "dolphin_deed.h" | ||||||
|  | 
 | ||||||
|  | static const DolphinDeedWeight dolphin_deed_weights[DolphinDeedMax] = { | ||||||
|  |     {1, 2, 60}, | ||||||
|  |     {1, 2, 60}, | ||||||
|  |     {1, 2, 60}, | ||||||
|  |     {-1, 2, 60}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const DolphinDeedWeight* dolphin_deed_weight(DolphinDeed deed) { | ||||||
|  |     return &dolphin_deed_weights[deed]; | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								applications/dolphin/dolphin_deed.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								applications/dolphin/dolphin_deed.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | /* Countable deed that affects icounter*/ | ||||||
|  | typedef enum { | ||||||
|  |     // iButton
 | ||||||
|  |     DolphinDeedIButtonRead, | ||||||
|  |     DolphinDeedIButtonWrite, | ||||||
|  |     DolphinDeedIButtonEmulate, | ||||||
|  |     // for debug
 | ||||||
|  |     DolphinDeedWrong, | ||||||
|  |     // Special value, do not use
 | ||||||
|  |     DolphinDeedMax | ||||||
|  | } DolphinDeed; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     int32_t icounter; // how many icounter get by Deed
 | ||||||
|  |     uint32_t limit_value; // how many deeds in limit interval
 | ||||||
|  |     uint32_t limit_interval; // interval, in minutes
 | ||||||
|  | } DolphinDeedWeight; | ||||||
|  | 
 | ||||||
|  | const DolphinDeedWeight* dolphin_deed_weight(DolphinDeed deed); | ||||||
							
								
								
									
										51
									
								
								applications/dolphin/dolphin_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								applications/dolphin/dolphin_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "dolphin.h" | ||||||
|  | #include "dolphin_state.h" | ||||||
|  | 
 | ||||||
|  | #include <flipper_v2.h> | ||||||
|  | 
 | ||||||
|  | #include <gui/gui.h> | ||||||
|  | #include <gui/widget.h> | ||||||
|  | #include <gui/canvas.h> | ||||||
|  | #include <menu/menu.h> | ||||||
|  | 
 | ||||||
|  | #include <assets_icons.h> | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     DolphinEventTypeDeed, | ||||||
|  | } DolphinEventType; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     DolphinEventType type; | ||||||
|  |     union { | ||||||
|  |         DolphinDeed deed; | ||||||
|  |     }; | ||||||
|  | } DolphinEvent; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     DolphinScreenDebug, | ||||||
|  |     DolphinScreenIdle, | ||||||
|  |     DolphinScreenStats, | ||||||
|  | } DolphinScreen; | ||||||
|  | 
 | ||||||
|  | struct Dolphin { | ||||||
|  |     Icon* icon; | ||||||
|  |     Widget* widget; | ||||||
|  |     ValueMutex* menu_vm; | ||||||
|  |     // State
 | ||||||
|  |     DolphinState* state; | ||||||
|  |     DolphinScreen screen; | ||||||
|  |     // Internal message queue
 | ||||||
|  |     osMessageQueueId_t event_queue; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void dolphin_draw_callback(Canvas* canvas, void* context); | ||||||
|  | void dolphin_draw_idle(Canvas* canvas, Dolphin* dolphin); | ||||||
|  | void dolphin_draw_debug(Canvas* canvas, Dolphin* dolphin); | ||||||
|  | void dolphin_draw_stats(Canvas* canvas, Dolphin* dolphin); | ||||||
|  | void dolphin_input_callback(InputEvent* event, void* context); | ||||||
|  | 
 | ||||||
|  | Dolphin* dolphin_alloc(); | ||||||
							
								
								
									
										52
									
								
								applications/dolphin/dolphin_state.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								applications/dolphin/dolphin_state.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #include "dolphin_state.h" | ||||||
|  | #include <flipper_v2.h> | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uint32_t ibutton; | ||||||
|  |     uint32_t nfc; | ||||||
|  |     uint32_t ir; | ||||||
|  |     uint32_t rfid; | ||||||
|  | } DolphinLimit; | ||||||
|  | 
 | ||||||
|  | struct DolphinState { | ||||||
|  |     uint32_t icounter; | ||||||
|  |     uint32_t butthurt; | ||||||
|  | 
 | ||||||
|  |     DolphinLimit limit; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | DolphinState* dolphin_state_alloc() { | ||||||
|  |     DolphinState* dolphin_state = furi_alloc(sizeof(DolphinState)); | ||||||
|  |     return dolphin_state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_state_release(DolphinState* dolphin_state) { | ||||||
|  |     free(dolphin_state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_state_save(DolphinState* dolphin_state) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_state_load(DolphinState* dolphin_state) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_state_clear(DolphinState* dolphin_state) { | ||||||
|  |     memset(dolphin_state, 0, sizeof(DolphinState)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { | ||||||
|  |     const DolphinDeedWeight* deed_weight = dolphin_deed_weight(deed); | ||||||
|  |     int32_t icounter = dolphin_state->icounter + deed_weight->icounter; | ||||||
|  | 
 | ||||||
|  |     if(icounter >= 0) { | ||||||
|  |         dolphin_state->icounter = icounter; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) { | ||||||
|  |     return dolphin_state->icounter; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state) { | ||||||
|  |     return dolphin_state->butthurt; | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								applications/dolphin/dolphin_state.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								applications/dolphin/dolphin_state.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "dolphin_deed.h" | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | typedef struct DolphinState DolphinState; | ||||||
|  | 
 | ||||||
|  | DolphinState* dolphin_state_alloc(); | ||||||
|  | 
 | ||||||
|  | void dolphin_state_release(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
|  | void dolphin_state_save(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
|  | void dolphin_state_load(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
|  | void dolphin_state_clear(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
|  | void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state); | ||||||
|  | 
 | ||||||
|  | uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state); | ||||||
| @ -1,67 +0,0 @@ | |||||||
| #include "irukagotchi.h" |  | ||||||
| 
 |  | ||||||
| #include <flipper_v2.h> |  | ||||||
| 
 |  | ||||||
| #include <gui/gui.h> |  | ||||||
| #include <gui/widget.h> |  | ||||||
| #include <gui/canvas.h> |  | ||||||
| #include <menu/menu.h> |  | ||||||
| 
 |  | ||||||
| #include <assets_icons.h> |  | ||||||
| 
 |  | ||||||
| struct Irukagotchi { |  | ||||||
|     Icon* icon; |  | ||||||
|     Widget* widget; |  | ||||||
|     ValueMutex* menu_vm; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void irukagotchi_draw_callback(Canvas* canvas, void* context) { |  | ||||||
|     Irukagotchi* irukagotchi = context; |  | ||||||
| 
 |  | ||||||
|     canvas_clear(canvas); |  | ||||||
|     canvas_set_color(canvas, ColorBlack); |  | ||||||
|     canvas_draw_icon(canvas, 128 - 80, 0, irukagotchi->icon); |  | ||||||
|     canvas_set_font(canvas, FontSecondary); |  | ||||||
|     canvas_draw_str(canvas, 2, 10, TARGET " " BUILD_DATE); |  | ||||||
|     canvas_draw_str(canvas, 2, 22, GIT_BRANCH); |  | ||||||
|     canvas_draw_str(canvas, 2, 34, GIT_BRANCH_NUM); |  | ||||||
|     canvas_draw_str(canvas, 2, 46, GIT_COMMIT); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void irukagotchi_input_callback(InputEvent* event, void* context) { |  | ||||||
|     Irukagotchi* irukagotchi = context; |  | ||||||
| 
 |  | ||||||
|     if(!event->state || event->input != InputOk) return; |  | ||||||
| 
 |  | ||||||
|     with_value_mutex( |  | ||||||
|         irukagotchi->menu_vm, (Menu * menu) { menu_ok(menu); }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Irukagotchi* irukagotchi_alloc() { |  | ||||||
|     Irukagotchi* irukagotchi = furi_alloc(sizeof(Irukagotchi)); |  | ||||||
| 
 |  | ||||||
|     irukagotchi->icon = assets_icons_get(I_Flipper_young_80x60); |  | ||||||
|     icon_start_animation(irukagotchi->icon); |  | ||||||
| 
 |  | ||||||
|     irukagotchi->widget = widget_alloc(); |  | ||||||
|     widget_draw_callback_set(irukagotchi->widget, irukagotchi_draw_callback, irukagotchi); |  | ||||||
|     widget_input_callback_set(irukagotchi->widget, irukagotchi_input_callback, irukagotchi); |  | ||||||
| 
 |  | ||||||
|     irukagotchi->menu_vm = furi_open("menu"); |  | ||||||
|     furi_check(irukagotchi->menu_vm); |  | ||||||
| 
 |  | ||||||
|     return irukagotchi; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void irukagotchi_task() { |  | ||||||
|     Irukagotchi* irukagotchi = irukagotchi_alloc(); |  | ||||||
| 
 |  | ||||||
|     Gui* gui = furi_open("gui"); |  | ||||||
|     gui_add_widget(gui, irukagotchi->widget, GuiLayerNone); |  | ||||||
| 
 |  | ||||||
|     furiac_ready(); |  | ||||||
| 
 |  | ||||||
|     while(1) { |  | ||||||
|         osDelay(osWaitForever); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| typedef struct Irukagotchi Irukagotchi; |  | ||||||
| Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 643 B | 
| @ -16,6 +16,12 @@ void api_hal_bt_dump_state(string_t buffer); | |||||||
| /* Get BT/BLE system component state */ | /* Get BT/BLE system component state */ | ||||||
| bool api_hal_bt_is_alive(); | bool api_hal_bt_is_alive(); | ||||||
| 
 | 
 | ||||||
|  | /* Lock shared access to flash controller */ | ||||||
|  | void api_hal_bt_lock_flash(); | ||||||
|  | 
 | ||||||
|  | /* Unlock shared access to flash controller */ | ||||||
|  | void api_hal_bt_unlock_flash(); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -14,3 +14,4 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | |||||||
| #include "api-hal-vcp.h" | #include "api-hal-vcp.h" | ||||||
| #include "api-hal-uid.h" | #include "api-hal-uid.h" | ||||||
| #include "api-hal-bt.h" | #include "api-hal-bt.h" | ||||||
|  | #include "api-hal-flash.h" | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| #include <api-hal-bt.h> | #include <api-hal-bt.h> | ||||||
| #include <app_entry.h> | #include <app_entry.h> | ||||||
| #include <ble.h> | #include <ble.h> | ||||||
|  | #include <stm32wbxx.h> | ||||||
|  | #include <shci.h> | ||||||
|  | #include <cmsis_os2.h> | ||||||
| 
 | 
 | ||||||
| void api_hal_bt_init() { | void api_hal_bt_init() { | ||||||
|     // Explicitly tell that we are in charge of CLK48 domain
 |     // Explicitly tell that we are in charge of CLK48 domain
 | ||||||
| @ -31,7 +34,39 @@ void api_hal_bt_dump_state(string_t buffer) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| bool api_hal_bt_is_alive() { | bool api_hal_bt_is_alive() { | ||||||
|     return APPE_Status() == BleGlueStatusStarted; |     return APPE_Status() == BleGlueStatusStarted; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool api_hal_bt_wait_transition() { | ||||||
|  |     if (APPE_Status() == BleGlueStatusUninitialized) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     while (APPE_Status() != BleGlueStatusStarted) { | ||||||
|  |         osDelay(1); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_bt_lock_flash() { | ||||||
|  |     if (!api_hal_bt_wait_transition()) { | ||||||
|  |         HAL_FLASH_Unlock(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) { | ||||||
|  |         osDelay(1); | ||||||
|  |     } | ||||||
|  |     SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); | ||||||
|  |     HAL_FLASH_Unlock(); | ||||||
|  |     while(LL_FLASH_IsOperationSuspended()) {}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_bt_unlock_flash() { | ||||||
|  |     if (!api_hal_bt_wait_transition()) { | ||||||
|  |         HAL_FLASH_Lock(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); | ||||||
|  |     HAL_FLASH_Lock(); | ||||||
|  |     HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID); | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								firmware/targets/f4/api-hal/api-hal-flash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								firmware/targets/f4/api-hal/api-hal-flash.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | #include <api-hal-flash.h> | ||||||
|  | #include <api-hal-bt.h> | ||||||
|  | #include <stm32wbxx.h> | ||||||
|  | 
 | ||||||
|  | void api_hal_flash_write_dword(size_t address, uint64_t data) { | ||||||
|  |     api_hal_bt_lock_flash(); | ||||||
|  |     HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data); | ||||||
|  |     api_hal_bt_unlock_flash(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_flash_write_row(size_t address, size_t source_address) { | ||||||
|  |     api_hal_bt_lock_flash(); | ||||||
|  |     HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, source_address); | ||||||
|  |     api_hal_bt_unlock_flash(); | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								firmware/targets/f4/api-hal/api-hal-flash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								firmware/targets/f4/api-hal/api-hal-flash.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Write double word (64 bits) | ||||||
|  |  * Locking operation, uses HSEM to manage shared access. | ||||||
|  |  * @param address - destination address, must be double word aligned. | ||||||
|  |  * @param data - data to write | ||||||
|  |  */ | ||||||
|  | void api_hal_flash_write_dword(size_t address, uint64_t data); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Write page (4096 bytes or 64 rows of double words). | ||||||
|  |  * Locking operation, uses HSEM to manage shared access. | ||||||
|  |  * @param address - destination address, must be page aligned | ||||||
|  |  * @param source_address - source address | ||||||
|  |  */ | ||||||
|  | void api_hal_flash_write_page(size_t address, size_t source_address); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく