Просмотр исходного кода

Merge pokemon_trading from https://github.com/kbembedded/Flipper-Zero-Game-Boy-Pokemon-Trading

# Conflicts:
#	pokemon_trading/application.fam
#	pokemon_trading/lib/flipper-gblink~3ea38b0b1548378127fc0b455939b854546fa23a
#	pokemon_trading/src/scenes/pokemon_gen.c
Willy-JL 1 год назад
Родитель
Сommit
f92a48a154

+ 1 - 1
pokemon_trading/README.md

@@ -1,4 +1,4 @@
-# GAME BOY Pokemon Trading MALVEKE
+# Pokemon Trade Tool for Flipper
 
 ## Watch it in Action
 The video below trades a Bulbasaur from the Flipper to a Game Boy Color with Pokemon Silver. The Game Boy trades its Cyndaquil. The Flipper is then used to modify the Cyndaquil to infect it with Pokerus, modify its EVs and IVs, and have the Cyndaquil hold an Antidote before it is traded back to the Game Boy.

+ 4 - 2
pokemon_trading/application.fam

@@ -1,11 +1,11 @@
 App(
     appid="pokemon",
-    name="[GB] Pokemon Trading",
+    name="[GB] Pokemon Trade Tool",
     apptype=FlipperAppType.EXTERNAL,
     entry_point="pokemon_app",
     requires=["gui"],
     stack_size=2 * 1024,
-    fap_version=[2, 1],
+    fap_version=[2, 2],
     fap_category="GPIO",
     fap_icon="pokemon_10px.png",
     fap_icon_assets="assets",
@@ -16,6 +16,8 @@ App(
     fap_private_libs=[
         Lib(
             name="flipper-gblink",
+            fap_include_paths=["gblink/include", "./"],
+            sources=["gblink/*.c"],
         ),
     ],
 )

+ 4 - 0
pokemon_trading/changelog.md

@@ -1,5 +1,9 @@
 # Changelog - Patch Notes
 
+## Version 2.2
+**New Features**
+- Update to gblink v0.63 which includes saving/loading of pin configurations for the EXT link interface
+
 ## Version 2.1
 **New Features**
 - Add ability to reset trade state without affecting current Pokemon being configured

+ 1 - 1
pokemon_trading/lib/flipper-gblink/.gitsubtree

@@ -1 +1 @@
-https://github.com/kbembedded/flipper-gblink 93931d71fffd0476a591dc18d3263a02e93a169a /
+https://github.com/kbembedded/flipper-gblink ecce5b6363adb067cef424eab09fead2f038baf5 /

+ 2 - 2
pokemon_trading/src/include/pokemon_app.h

@@ -35,8 +35,8 @@ struct pokemon_fap {
      */
     PokemonData* pdata;
 
-    /* Pin definition to actual Game Link Cable interface */
-    struct gblink_pins pins;
+    /* gblink interface */
+    void *gblink_handle;
 };
 
 typedef struct pokemon_fap PokemonFap;

+ 17 - 8
pokemon_trading/src/pokemon_app.c

@@ -5,11 +5,13 @@
 #include <src/include/pokemon_app.h>
 #include <src/include/pokemon_data.h>
 #include <src/views/trade.h>
-#include <src/views/select_pokemon.h>
 #include <src/include/pokemon_char_encode.h>
 
 #include <src/scenes/include/pokemon_scene.h>
 
+#include <gblink/include/gblink_pinconf.h>
+#include <gblink.h>
+
 bool pokemon_custom_event_callback(void* context, uint32_t event) {
     furi_assert(context);
     PokemonFap* pokemon_fap = context;
@@ -37,9 +39,6 @@ PokemonFap* pokemon_alloc() {
     view_dispatcher_attach_to_gui(
         view_dispatcher, (Gui*)furi_record_open(RECORD_GUI), ViewDispatcherTypeFullscreen);
 
-    // Set up pinout defaults
-    memcpy(&pokemon_fap->pins, &common_pinouts[PINOUT_ORIGINAL], sizeof(struct gblink_pins));
-
     // Text input
     pokemon_fap->text_input = text_input_alloc();
     view_dispatcher_add_view(
@@ -66,24 +65,34 @@ PokemonFap* pokemon_alloc() {
     pokemon_fap->scene_manager = scene_manager_alloc(&pokemon_scene_handlers, pokemon_fap);
     scene_manager_next_scene(pokemon_fap->scene_manager, PokemonSceneMainMenu);
 
+    // Allocate gblink before going to main menu
+    pokemon_fap->gblink_handle = gblink_alloc();
+    gblink_pinconf_load(pokemon_fap->gblink_handle);
+
     return pokemon_fap;
 }
 
 void free_app(PokemonFap* pokemon_fap) {
     furi_assert(pokemon_fap);
 
+    // gblink
+    gblink_free(pokemon_fap->gblink_handle);
+
     // Submenu
-    submenu_free(pokemon_fap->submenu);
     view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewSubmenu);
+    submenu_free(pokemon_fap->submenu);
 
-    text_input_free(pokemon_fap->text_input);
+    // text input
     view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewTextInput);
+    text_input_free(pokemon_fap->text_input);
 
-    variable_item_list_free(pokemon_fap->variable_item_list);
+    // Vairable item list
     view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewVariableItem);
+    variable_item_list_free(pokemon_fap->variable_item_list);
 
-    dialog_ex_free(pokemon_fap->dialog_ex);
+    // Dialog ex
     view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewDialogEx);
+    dialog_ex_free(pokemon_fap->dialog_ex);
 
     view_dispatcher_free(pokemon_fap->view_dispatcher);
 

+ 2 - 2
pokemon_trading/src/scenes/pokemon_gen.c

@@ -60,8 +60,8 @@ void pokemon_scene_gen_on_enter(void* context) {
 
         // Trade View
         /* Allocates its own view and adds it to the main view_dispatcher */
-        pokemon_fap->trade =
-            trade_alloc(pdata, &pokemon_fap->pins, pokemon_fap->view_dispatcher, AppViewTrade);
+        pokemon_fap->trade = trade_alloc(
+            pdata, pokemon_fap->gblink_handle, pokemon_fap->view_dispatcher, AppViewTrade);
     }
 
     pkmn_num = pokemon_stat_get(pdata, STAT_NUM, NONE);

+ 58 - 111
pokemon_trading/src/scenes/pokemon_pins.c

@@ -5,25 +5,8 @@
 
 #include <src/scenes/include/pokemon_scene.h>
 
-/* This is a bit of a hack to save some space and not have to refactor this scene.
- * We re-use the name and pin from the global gpio pin definition, but need to
- * skip the two debug pins in the row of header pins.
- *
- * This is hard-coded, not really portable, but saves a couple hundred bytes :D
- *
- * In the future, the right way to do this would be to build our own table of
- * non-debug pins from whatever the current platforms gpio pin definition is.
- */
-#define NUM_PINS 8
-static const GpioPinRecord* named_pins[NUM_PINS] = {
-    &gpio_pins[0],
-    &gpio_pins[1],
-    &gpio_pins[2],
-    &gpio_pins[3],
-    &gpio_pins[4],
-    &gpio_pins[5],
-    &gpio_pins[10],
-    &gpio_pins[11]};
+#include <gblink/include/gblink_pinconf.h>
+#include <gblink/include/gblink.h>
 
 /* This must match gblink's enum order */
 static const char* named_groups[] = {
@@ -33,121 +16,83 @@ static const char* named_groups[] = {
     "",
 };
 
-struct itemlist_builder {
-    VariableItem* named;
-    VariableItem* serin;
-    VariableItem* serout;
-    VariableItem* clk;
-    uint8_t named_index;
-    uint8_t serin_index;
-    uint8_t serout_index;
-    uint8_t clk_index;
-};
-
-/* Just make it a global, whatever */
-static struct itemlist_builder builder = {0};
-static void select_pins_rebuild_list(PokemonFap* pokemon_fap);
-
-static void select_pins_set(PokemonFap* pokemon_fap) {
-    pokemon_fap->pins.serin = named_pins[builder.serin_index]->pin;
-    pokemon_fap->pins.serout = named_pins[builder.serout_index]->pin;
-    pokemon_fap->pins.clk = named_pins[builder.clk_index]->pin;
-}
+static void select_pins_rebuild_list(PokemonFap* pokemon_fap, int mode);
 
-static void select_named_group_callback(VariableItem* item) {
+static void select_pins_default_callback(VariableItem* item) {
     uint8_t index = variable_item_get_current_value_index(item);
     PokemonFap* pokemon_fap = variable_item_get_context(item);
 
     variable_item_set_current_value_text(item, named_groups[index]);
-    builder.named_index = index;
-    select_pins_rebuild_list(pokemon_fap);
-    variable_item_list_set_selected_item(pokemon_fap->variable_item_list, 0);
-}
-
-static void select_pins_serin_callback(VariableItem* item) {
-    uint8_t index = variable_item_get_current_value_index(item);
-    PokemonFap* pokemon_fap = variable_item_get_context(item);
-
-    variable_item_set_current_value_text(item, named_pins[index]->name);
-    builder.serin_index = index;
-    select_pins_rebuild_list(pokemon_fap);
-    variable_item_list_set_selected_item(pokemon_fap->variable_item_list, 1);
-}
-
-static void select_pins_serout_callback(VariableItem* item) {
-    uint8_t index = variable_item_get_current_value_index(item);
-    PokemonFap* pokemon_fap = variable_item_get_context(item);
-
-    variable_item_set_current_value_text(item, named_pins[index]->name);
-    builder.serout_index = index;
-    select_pins_rebuild_list(pokemon_fap);
-    variable_item_list_set_selected_item(pokemon_fap->variable_item_list, 2);
+    gblink_pin_set_default(pokemon_fap->gblink_handle, index);
+    select_pins_rebuild_list(pokemon_fap, index);
 }
 
-static void select_pins_clk_callback(VariableItem* item) {
+static void select_pins_pin_callback(VariableItem* item) {
     uint8_t index = variable_item_get_current_value_index(item);
     PokemonFap* pokemon_fap = variable_item_get_context(item);
+    uint8_t which = variable_item_list_get_selected_item_index(pokemon_fap->variable_item_list);
+    gblink_bus_pins pin;
 
-    variable_item_set_current_value_text(item, named_pins[index]->name);
-    builder.clk_index = index;
-    select_pins_rebuild_list(pokemon_fap);
-    variable_item_list_set_selected_item(pokemon_fap->variable_item_list, 3);
-}
-
-static void select_pins_rebuild_list(PokemonFap* pokemon_fap) {
-    int num;
-
-    /* HACK: TODO: It would be better to do this programmatically, but, I'm kind
-     * of done working on this feature so its going to be hardcoded for now.
-     */
-    switch(builder.named_index) {
-    case 0: // Original
-        num = 1;
-        builder.serin_index = 5;
-        builder.serout_index = 3;
-        builder.clk_index = 4;
+    switch (which) {
+    case 1: // SI
+        pin = PIN_SERIN;
+        break;
+    case 2: // SO
+        pin = PIN_SEROUT;
         break;
-    case 1: // MALVEKE
-        num = 1;
-        builder.serin_index = 1;
-        builder.serout_index = 0;
-        builder.clk_index = 3;
+    case 3: // CLK
+        pin = PIN_CLK;
         break;
     default:
-        num = NUM_PINS;
+        furi_crash();
         break;
     }
 
-    select_pins_set(pokemon_fap);
+    if (index > gblink_pin_get(pokemon_fap->gblink_handle, pin))
+        index = gblink_pin_get_next(index);
+    else
+        index = gblink_pin_get_prev(index);
+    variable_item_set_current_value_index(item, index);
+    variable_item_set_current_value_text(item, gpio_pins[index].name);
+    gblink_pin_set(pokemon_fap->gblink_handle, pin, index);
+}
 
+static void select_pins_rebuild_list(PokemonFap* pokemon_fap, int mode) {
+    int pinnum;
+    int pinmax = gblink_pin_count_max() + 1;
+    VariableItem *item;
+    
     variable_item_list_reset(pokemon_fap->variable_item_list);
 
-    builder.named = variable_item_list_add(
-        pokemon_fap->variable_item_list, "Mode", 3, select_named_group_callback, pokemon_fap);
-    builder.serin = variable_item_list_add(
-        pokemon_fap->variable_item_list, "SI:", num, select_pins_serin_callback, pokemon_fap);
-    builder.serout = variable_item_list_add(
-        pokemon_fap->variable_item_list, "SO:", num, select_pins_serout_callback, pokemon_fap);
-    builder.clk = variable_item_list_add(
-        pokemon_fap->variable_item_list, "CLK:", num, select_pins_clk_callback, pokemon_fap);
-
-    variable_item_set_current_value_index(builder.named, builder.named_index);
-    variable_item_set_current_value_text(builder.named, named_groups[builder.named_index]);
-
-    variable_item_set_current_value_index(builder.serin, (num == 1 ? 0 : builder.serin_index));
-    variable_item_set_current_value_text(builder.serin, named_pins[builder.serin_index]->name);
-
-    variable_item_set_current_value_index(builder.serout, (num == 1 ? 0 : builder.serout_index));
-    variable_item_set_current_value_text(builder.serout, named_pins[builder.serout_index]->name);
-
-    variable_item_set_current_value_index(builder.clk, (num == 1 ? 0 : builder.clk_index));
-    variable_item_set_current_value_text(builder.clk, named_pins[builder.clk_index]->name);
+    item = variable_item_list_add(
+        pokemon_fap->variable_item_list, "Mode", PINOUT_COUNT+1, select_pins_default_callback, pokemon_fap);
+    variable_item_set_current_value_index(item, mode);
+    variable_item_set_current_value_text(item, named_groups[mode]);
+
+    item = variable_item_list_add(
+        pokemon_fap->variable_item_list, "SI:", (mode < PINOUT_COUNT) ? 1 : pinmax, select_pins_pin_callback, pokemon_fap);
+    pinnum = gblink_pin_get(pokemon_fap->gblink_handle, PIN_SERIN);
+    variable_item_set_current_value_index(item, (mode < PINOUT_COUNT) ? 0 : pinnum);
+    variable_item_set_current_value_text(item, gpio_pins[pinnum].name);
+
+    item = variable_item_list_add(
+        pokemon_fap->variable_item_list, "SO:", (mode < PINOUT_COUNT) ? 1 : pinmax, select_pins_pin_callback, pokemon_fap);
+    pinnum = gblink_pin_get(pokemon_fap->gblink_handle, PIN_SEROUT);
+    variable_item_set_current_value_index(item, (mode < PINOUT_COUNT) ? 0 : pinnum);
+    variable_item_set_current_value_text(item, gpio_pins[pinnum].name);
+
+    item = variable_item_list_add(
+        pokemon_fap->variable_item_list, "CLK:", (mode < PINOUT_COUNT) ? 1 : pinmax, select_pins_pin_callback, pokemon_fap);
+    pinnum = gblink_pin_get(pokemon_fap->gblink_handle, PIN_CLK);
+    variable_item_set_current_value_index(item, (mode < PINOUT_COUNT) ? 0 : pinnum);
+    variable_item_set_current_value_text(item, gpio_pins[pinnum].name);
 }
 
 void pokemon_scene_select_pins_on_enter(void* context) {
     PokemonFap* pokemon_fap = (PokemonFap*)context;
+    int def_mode = gblink_pin_get_default(pokemon_fap->gblink_handle);
 
-    select_pins_rebuild_list(pokemon_fap);
+    select_pins_rebuild_list(pokemon_fap, (def_mode < 0) ? PINOUT_COUNT : def_mode);
 
     view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewVariableItem);
 }
@@ -159,5 +104,7 @@ bool pokemon_scene_select_pins_on_event(void* context, SceneManagerEvent event)
 }
 
 void pokemon_scene_select_pins_on_exit(void* context) {
-    UNUSED(context);
+    PokemonFap* pokemon_fap = context;
+
+    gblink_pinconf_save(pokemon_fap->gblink_handle);
 }

+ 7 - 11
pokemon_trading/src/views/trade.c

@@ -221,7 +221,6 @@ struct trade_ctx {
     PokemonData* input_pdata;
     struct patch_list* patch_list;
     void* gblink_handle;
-    struct gblink_pins* gblink_pins;
     PokemonData* pdata;
     NotificationApp* notifications;
 };
@@ -860,7 +859,6 @@ void trade_enter_callback(void* context) {
     furi_assert(context);
     struct trade_ctx* trade = (struct trade_ctx*)context;
     struct trade_model* model;
-    struct gblink_def gblink_def = {0};
 
     model = view_get_model(trade->view);
 
@@ -875,13 +873,11 @@ void trade_enter_callback(void* context) {
 
     view_commit_model(trade->view, true);
 
-    gblink_def.pins = trade->gblink_pins;
-    gblink_def.callback = transferBit;
-    gblink_def.cb_context = trade;
-
-    trade->gblink_handle = gblink_alloc(&gblink_def);
+    gblink_callback_set(trade->gblink_handle, transferBit, trade);
     gblink_nobyte_set(trade->gblink_handle, SERIAL_NO_DATA_BYTE);
 
+    gblink_start(trade->gblink_handle);
+
     /* Every 250 ms, trigger a draw update. 250 ms was chosen so that during
      * the trade process, each update can flip the LED and screen to make the
      * trade animation.
@@ -911,8 +907,8 @@ void trade_exit_callback(void* context) {
     furi_timer_free(trade->draw_timer);
     trade->draw_timer = NULL;
 
-    /* Unset the pin settings */
-    gblink_free(trade->gblink_handle);
+    /* Stop the game boy link */
+    gblink_stop(trade->gblink_handle);
 
     /* Destroy the patch list, it is allocated on the enter callback */
     plist_free(trade->patch_list);
@@ -921,7 +917,7 @@ void trade_exit_callback(void* context) {
 
 void* trade_alloc(
     PokemonData* pdata,
-    struct gblink_pins* gblink_pins,
+    void *gblink_handle,
     ViewDispatcher* view_dispatcher,
     uint32_t view_id) {
     furi_assert(pdata);
@@ -933,8 +929,8 @@ void* trade_alloc(
     trade->pdata = pdata;
     trade->input_pdata = pokemon_data_alloc(pdata->gen);
     trade->patch_list = NULL;
-    trade->gblink_pins = gblink_pins;
     trade->notifications = furi_record_open(RECORD_NOTIFICATION);
+    trade->gblink_handle = gblink_handle;
 
     view_set_context(trade->view, trade);
     view_allocate_model(trade->view, ViewModelTypeLockFree, sizeof(struct trade_model));

+ 1 - 1
pokemon_trading/src/views/trade.h

@@ -8,7 +8,7 @@
 
 void* trade_alloc(
     PokemonData* pdata,
-    struct gblink_pins* gblink_pins,
+    void *gblink_handle,
     ViewDispatcher* view_dispatcher,
     uint32_t view_id);