فهرست منبع

add new app and update readme

MX 2 سال پیش
والد
کامیت
d6e42ff93e

+ 3 - 2
ReadMe.md

@@ -13,7 +13,7 @@ Apps contains changes needed to compile them on latest firmware, fixes has been
 
 The Flipper and its community wouldn't be as rich as it is without your contributions and support. Thank you for all you have done.
 
-### Apps checked & updated at `20 Aug 04:37 GMT +3`
+### Apps checked & updated at `23 Aug 19:40 GMT +3`
 
 
 # Default pack
@@ -151,7 +151,8 @@ Games:
 - [Wii EC Analyser (by csBlueChip)](https://github.com/csBlueChip/FlipperZero_WiiEC)
 - [Wire Tester (by unixispower)](https://gitlab.com/unixispower/flipper-wire-tester)
 - [Atomic Dice Roller (by nmrr)](https://github.com/nmrr/flipperzero-atomicdiceroller)
-- [NRF24 Channel Scanner (by Sil333033)](https://github.com/Flipper-XFW/Xtreme-Firmware/commit/8015ea29a2d4e788b6dee5f7f967dd001534214c)
+- [NRF24 Channel Scanner (by htotoo)](https://github.com/htotoo/NRF24ChannelScanner)
+- [Mx2125 - Step Counter (by grugnoymeme)](https://github.com/grugnoymeme/flipperzero-stepcounter-fap)
 
 ## Infrared
 - [IR Remote (by Hong5489)](https://github.com/Hong5489/ir_remote) - improvements [(by friebel)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/535) - Hold Option, RAW support [(by d4ve10)](https://github.com/d4ve10/ir_remote/tree/infrared_hold_option)

+ 2 - 2
base_pack/picopass/application.fam

@@ -9,8 +9,8 @@ App(
         "gui",
     ],
     stack_size=4 * 1024,
-    fap_description="App to communicate with NFC tags using the PicoPass format",
-    fap_version="1.1",
+    fap_description="App to communicate with NFC tags using the PicoPass(iClass) format",
+    fap_version="1.2",
     fap_icon="125_10px.png",
     fap_category="NFC",
     fap_libs=["mbedtls"],

+ 11 - 3
base_pack/picopass/picopass_device.c

@@ -356,8 +356,8 @@ ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pa
     return ERR_NONE;
 }
 
-ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* record) {
-    uint32_t* halves = (uint32_t*)data;
+ReturnCode picopass_device_parse_wiegand(uint8_t* credential, PicopassWiegandRecord* record) {
+    uint32_t* halves = (uint32_t*)credential;
     if(halves[0] == 0) {
         uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
         record->bitLength = 31 - leading0s;
@@ -367,8 +367,16 @@ ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* r
     }
     FURI_LOG_D(TAG, "bitLength: %d", record->bitLength);
 
+    // Remove sentinel bit from credential.  Byteswapping to handle array of bytes vs 64bit value
+    uint64_t sentinel = __builtin_bswap64(1ULL << record->bitLength);
+    uint64_t swapped = 0;
+    memcpy(&swapped, credential, sizeof(uint64_t));
+    swapped = swapped ^ sentinel;
+    memcpy(credential, &swapped, sizeof(uint64_t));
+    FURI_LOG_D(TAG, "PACS: (%d) %016llx", record->bitLength, swapped);
+
     if(record->bitLength == 26) {
-        uint8_t* v4 = data + 4;
+        uint8_t* v4 = credential + 4;
         uint32_t bot = v4[3] | (v4[2] << 8) | (v4[1] << 16) | (v4[0] << 24);
 
         record->CardNumber = (bot >> 1) & 0xFFFF;

+ 21 - 0
non_catalog_apps/step_counter/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 47LeCoste
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 21 - 0
non_catalog_apps/step_counter/README.md

@@ -0,0 +1,21 @@
+# WIP-flipperzero-StepCounter-fap
+This is a simple StepCounter/Pedometer for FlipperZero using a Memsic2125 module. 
+> Thanks to @jamisonderek for the tutorial on how to implement Memsic2125 module on Flipper Zero, and for the support.
+
+# Links  
+<img src="https://raw.githubusercontent.com/grugnoymeme/flipperzero-StepCounter-fap/main/images/memsic_2125_chip.jpg" width="200" />
+
+| Mx2125 | Name | Purpose | Flipper |
+|--------|------|---------|---------|
+|Pin 1 | Tout | Temperature Out | not connected|
+|Pin 2 | Yout | Y-axis PWM Out (100Hz, duty cycle = value) | C0|
+|Pin 3 | GND | Ground | GND|
+|Pin 4 | GND | Ground | GND|
+|Pin 5 | Xout | X-axis PWM Out (100Hz, duty cycle = value) | C1|
+|Pin 6 | Vdd | Drain voltage (3.3V to 5V DC) | 3v3|
+
+# Screenshots   
+![Main menu view](https://raw.githubusercontent.com/grugnoymeme/flipperzero-StepCounter-fap/main/images/menu_view.png "main menu view")
+
+![Main screen](https://raw.githubusercontent.com/grugnoymeme/flipperzero-StepCounter-fap/main/images/main_screen.png "main screen view")
+

+ 17 - 0
non_catalog_apps/step_counter/application.fam

@@ -0,0 +1,17 @@
+App(
+    appid="stepcounter",
+    name="[Mx2125] Step Counter",
+    fap_version=(1,0),
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="step_counter_app",
+    requires=[
+	"gui", 
+	"input"
+	],
+    stack_size=2 * 1024,
+    fap_icon="steps.png",
+    fap_category="GPIO",
+    fap_author="47lecoste a.k.a. grugnoymeme",
+    fap_description="Step Counter/Pedometer using Memsic2125 module.",
+    fap_weburl="https://github.com/grugnoymeme/flipperzero-stepcounter-fap"
+)

+ 156 - 0
non_catalog_apps/step_counter/stepcounter.c

@@ -0,0 +1,156 @@
+#include <furi.h>
+#include <furi_hal.h>
+#include <furi_hal_gpio.h>
+#include <furi_hal_resources.h>
+#include <gui/gui.h>
+#include <input/input.h>
+#include <locale/locale.h>
+#include <notification/notification.h>
+#include <notification/notification_messages.h>
+
+#define TAG_MEMSIC "memsic_2125_app"
+#define TAG_COUNTER "step_counter_app"
+
+typedef struct {
+    const GpioPin* pin;
+    bool prevState;
+    uint32_t stepCount;
+    bool counting;
+    uint32_t time_of_last_high_pulse;
+    uint32_t time_of_high_to_high;
+} StepCounterData;
+
+typedef enum {
+    StepCounterEventTypeStep,
+    StepCounterEventTypeKey,
+} StepCounterEventType;
+
+typedef struct {
+    StepCounterEventType type;
+    InputEvent input_event;
+} StepCounterEvent;
+
+typedef struct {
+    FuriMessageQueue* queue;
+    StepCounterData* data;
+    ViewPort* view_port;
+} StepCounterContext;
+
+const GpioPin* const gpio_accelerometer = &gpio_ext_pc0;
+
+void step_callback(void* ctx) {
+	StepCounterContext* context = (StepCounterContext*)ctx;
+    StepCounterData* stepData = context->data;
+    
+    FuriHalCortexTimer timer = furi_hal_cortex_timer_get(0);
+	uint32_t now = timer.start;
+
+	if (furi_hal_gpio_read(stepData->pin)) { 
+	  if (stepData->time_of_last_high_pulse != 0) {
+		 stepData->time_of_high_to_high = now - stepData->time_of_last_high_pulse;
+	  }
+	  stepData->time_of_last_high_pulse = now;
+	} else {
+	  uint32_t high_duration = now - stepData->time_of_last_high_pulse;
+	  bool current_state = high_duration < (stepData->time_of_high_to_high >> 1);
+
+	  if(current_state != stepData->prevState) {
+		  stepData->prevState = current_state;
+		  stepData->stepCount++;
+
+		 StepCounterEvent event = {.type = StepCounterEventTypeStep};
+		 furi_message_queue_put(context->queue, &event, 0);
+	  }
+   }
+}
+
+static void input_callback(InputEvent* input_event, FuriMessageQueue* queue) {
+    StepCounterEvent event = {
+        .type = StepCounterEventTypeKey,
+        .input_event.key = input_event->key,
+        .input_event.type = input_event->type,
+    };
+    furi_message_queue_put(queue, &event, FuriWaitForever);
+}
+
+static void render_callback(Canvas* canvas, void* ctx) {
+    StepCounterContext* stepContext = (StepCounterContext*)ctx;
+    StepCounterData* stepData = stepContext->data;
+
+    char stepText[20];
+    snprintf(stepText, sizeof(stepText), "Steps: %ld", stepData->stepCount);
+    canvas_draw_str_aligned(canvas, 1, 1, AlignLeft, AlignTop, stepText);
+
+    char buttonText[10];
+    snprintf(buttonText, sizeof(buttonText), stepData->counting ? "STOP" : "START");
+    canvas_draw_str_aligned(
+        canvas,
+        canvas_width(canvas) / 2,
+        canvas_height(canvas) - 1,
+        AlignCenter,
+        AlignBottom,
+        buttonText);
+}
+
+int32_t step_counter_app(void* p) {
+    UNUSED(p);
+
+    StepCounterContext* stepContext = malloc(sizeof(StepCounterContext));
+    stepContext->data = malloc(sizeof(StepCounterData));
+    stepContext->data->pin = gpio_accelerometer;
+    stepContext->data->prevState = furi_hal_gpio_read(stepContext->data->pin);
+    stepContext->data->stepCount = 0;
+    stepContext->data->counting = false;
+
+    stepContext->queue = furi_message_queue_alloc(8, sizeof(StepCounterEvent));
+
+    furi_hal_gpio_init(
+        stepContext->data->pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh);
+    furi_hal_gpio_add_int_callback(stepContext->data->pin, step_callback, stepContext);
+
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, render_callback, stepContext);
+    view_port_input_callback_set(view_port, input_callback, stepContext->queue);
+
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+    StepCounterEvent event;
+    bool processing = true;
+    do {
+        if(furi_message_queue_get(stepContext->queue, &event, FuriWaitForever) == FuriStatusOk) {
+            switch(event.type) {
+            case StepCounterEventTypeKey:
+                if(event.input_event.type == InputTypeShort &&
+                   event.input_event.key == InputKeyBack) {
+                    processing = false;
+                } else if(
+                    event.input_event.type == InputTypeShort &&
+                    event.input_event.key == InputKeyOk) {
+                    stepContext->data->counting = !stepContext->data->counting;
+                    view_port_update(view_port);
+                }
+                break;
+            case StepCounterEventTypeStep:
+                view_port_update(view_port);
+                break;
+            default:
+                break;
+            }
+            view_port_update(view_port);
+        } else {
+            processing = false;
+        }
+    } while(processing);
+
+    furi_hal_gpio_remove_int_callback(stepContext->data->pin);
+    view_port_enabled_set(view_port, false);
+    gui_remove_view_port(gui, view_port);
+    view_port_free(view_port);
+    furi_record_close(RECORD_GUI);
+    furi_message_queue_free(stepContext->queue);
+    free(stepContext->data);
+    free(stepContext);
+
+    return 0;
+}

BIN
non_catalog_apps/step_counter/steps.png