Oliver Fabel 1 год назад
Родитель
Сommit
204bcdea1b

+ 1 - 1
lib/micropython

@@ -1 +1 @@
-Subproject commit 8772835d303ad98f749cc4f643b7394b26986ecb
+Subproject commit bcdb22c8be76c4e8651571a1447ebb2767a0e5b9

+ 11 - 1
lib/micropython-port/mp_flipper_context.h

@@ -1,7 +1,17 @@
+#include <stdint.h>
+
 #include <furi.h>
 #include <gui/gui.h>
 #include <dialogs/dialogs.h>
 
+#include <mp_flipper_modflipperzero.h>
+
+#define MP_FLIPPER_GPIO_PIN_OFF     (1 << 15)
+#define MP_FLIPPER_GPIO_PIN_BLOCKED (1 << 7)
+#define MP_FLIPPER_GPIO_PIN_PWM     ((MP_FLIPPER_GPIO_PIN_BLOCKED) | (1 << 8))
+
+typedef uint16_t mp_flipper_gpio_pin_t;
+
 typedef struct {
     Gui* gui;
     ViewPort* view_port;
@@ -13,5 +23,5 @@ typedef struct {
     const char* dialog_message_button_center;
     const char* dialog_message_button_right;
     FuriHalAdcHandle* adc_handle;
-    bool* gpio_pins_used;
+    mp_flipper_gpio_pin_t* gpio_pins;
 } mp_flipper_context_t;

+ 10 - 6
lib/micropython-port/mp_flipper_modflipperzero_adc.c

@@ -27,17 +27,21 @@ inline static FuriHalAdcChannel decode_pin_to_adc_channel(uint8_t pin) {
 inline uint16_t mp_flipper_adc_read_pin(uint8_t raw_pin) {
     mp_flipper_context_t* ctx = mp_flipper_context;
 
-    furi_check(ctx->adc_handle, "missing ADC handle");
-
     FuriHalAdcChannel channel = decode_pin_to_adc_channel(raw_pin);
 
-    return furi_hal_adc_read(ctx->adc_handle, channel);
+    if(channel == FuriHalAdcChannelNone) {
+        return 0;
+    }
+
+    if(ctx->gpio_pins[raw_pin] != MP_FLIPPER_GPIO_MODE_ANALOG) {
+        return 0;
+    }
+
+    return ctx->adc_handle ? furi_hal_adc_read(ctx->adc_handle, channel) : 0;
 }
 
 inline float mp_flipper_adc_convert_to_voltage(uint16_t value) {
     mp_flipper_context_t* ctx = mp_flipper_context;
 
-    furi_check(ctx->adc_handle, "missing ADC handle");
-
-    return furi_hal_adc_convert_to_voltage(ctx->adc_handle, value);
+    return ctx->adc_handle ? furi_hal_adc_convert_to_voltage(ctx->adc_handle, value) : 0.0f;
 }

+ 53 - 20
lib/micropython-port/mp_flipper_modflipperzero_gpio.c

@@ -5,6 +5,8 @@
 
 #include "mp_flipper_context.h"
 
+#define NO_VALUE (-1)
+
 static const GpioPin* decode_pin(uint8_t pin) {
     switch(pin) {
     case MP_FLIPPER_GPIO_PIN_PC0:
@@ -24,7 +26,7 @@ static const GpioPin* decode_pin(uint8_t pin) {
     case MP_FLIPPER_GPIO_PIN_PA7:
         return &gpio_ext_pa7;
     default:
-        furi_crash("unknown GPIO pin");
+        return NULL;
     }
 }
 
@@ -49,7 +51,7 @@ static inline const GpioMode decode_mode(uint8_t mode) {
         return GpioModeInterruptRiseFall;
     }
 
-    furi_crash("unknown GPIO mode");
+    return NO_VALUE;
 }
 
 static inline const GpioPull decode_pull(uint8_t pull) {
@@ -61,7 +63,7 @@ static inline const GpioPull decode_pull(uint8_t pull) {
     case MP_FLIPPER_GPIO_PULL_DOWN:
         return GpioPullDown;
     default:
-        furi_crash("unknown GPIO pull");
+        return NO_VALUE;
     }
 }
 
@@ -76,24 +78,30 @@ static inline const GpioSpeed decode_speed(uint8_t speed) {
     case MP_FLIPPER_GPIO_SPEED_VERY_HIGH:
         return GpioSpeedVeryHigh;
     default:
-        furi_crash("unknown GPIO speed");
+        return NO_VALUE;
     }
 }
 
-inline void mp_flipper_gpio_init_pin(
+inline bool mp_flipper_gpio_init_pin(
     uint8_t raw_pin,
     uint8_t raw_mode,
     uint8_t raw_pull,
     uint8_t raw_speed) {
     mp_flipper_context_t* ctx = mp_flipper_context;
 
-    furi_check(raw_pin < MP_FLIPPER_GPIO_PINS);
-
     const GpioPin* pin = decode_pin(raw_pin);
     const GpioMode mode = decode_mode(raw_mode);
     const GpioPull pull = decode_pull(raw_pull);
     const GpioSpeed speed = decode_speed(raw_speed);
 
+    if(pin == NULL || mode == NO_VALUE || pull == NO_VALUE || speed == NO_VALUE) {
+        return false;
+    }
+
+    if(ctx->gpio_pins[raw_pin] & MP_FLIPPER_GPIO_PIN_BLOCKED) {
+        return false;
+    }
+
     furi_hal_gpio_init(pin, mode, pull, speed);
 
     if(raw_mode & (MP_FLIPPER_GPIO_MODE_INTERRUPT_FALL | MP_FLIPPER_GPIO_MODE_INTERRUPT_RISE)) {
@@ -104,39 +112,64 @@ inline void mp_flipper_gpio_init_pin(
         furi_hal_gpio_remove_int_callback(pin);
     }
 
-    if(raw_mode == MP_FLIPPER_GPIO_MODE_ANALOG && ctx->adc_handle == NULL) {
+    if(raw_mode == MP_FLIPPER_GPIO_MODE_ANALOG) {
         ctx->adc_handle = furi_hal_adc_acquire();
 
         furi_hal_adc_configure(ctx->adc_handle);
     }
 
-    ctx->gpio_pins_used[raw_pin] = true;
+    ctx->gpio_pins[raw_pin] = raw_mode;
+
+    return true;
 }
 
 inline void mp_flipper_gpio_deinit_pin(uint8_t raw_pin) {
-    mp_flipper_context_t* ctx = mp_flipper_context;
-
-    furi_check(raw_pin < MP_FLIPPER_GPIO_PINS);
+    const mp_flipper_context_t* ctx = mp_flipper_context;
 
-    if(ctx->gpio_pins_used[raw_pin]) {
-        const GpioPin* pin = decode_pin(raw_pin);
+    const GpioPin* pin = decode_pin(raw_pin);
 
-        furi_hal_gpio_disable_int_callback(pin);
-        furi_hal_gpio_remove_int_callback(pin);
-        furi_hal_gpio_init_simple(pin, GpioModeAnalog);
+    if(pin == NULL) {
+        return;
+    }
 
-        ctx->gpio_pins_used[raw_pin] = false;
+    if(ctx->gpio_pins[raw_pin] & (MP_FLIPPER_GPIO_PIN_BLOCKED | MP_FLIPPER_GPIO_PIN_OFF)) {
+        return;
     }
+
+    furi_hal_gpio_disable_int_callback(pin);
+    furi_hal_gpio_remove_int_callback(pin);
+    furi_hal_gpio_init_simple(pin, GpioModeAnalog);
+
+    ctx->gpio_pins[raw_pin] = MP_FLIPPER_GPIO_PIN_OFF;
 }
 
 inline void mp_flipper_gpio_set_pin(uint8_t raw_pin, bool state) {
+    const mp_flipper_context_t* ctx = mp_flipper_context;
+
     const GpioPin* pin = decode_pin(raw_pin);
 
-    furi_hal_gpio_write(pin, state);
+    if(pin == NULL) {
+        return;
+    }
+
+    if(ctx->gpio_pins[raw_pin] == MP_FLIPPER_GPIO_MODE_OUTPUT_PUSH_PULL ||
+       ctx->gpio_pins[raw_pin] == MP_FLIPPER_GPIO_MODE_OUTPUT_OPEN_DRAIN) {
+        furi_hal_gpio_write(pin, state);
+    }
 }
 
 inline bool mp_flipper_gpio_get_pin(uint8_t raw_pin) {
+    const mp_flipper_context_t* ctx = mp_flipper_context;
+
     const GpioPin* pin = decode_pin(raw_pin);
 
-    return furi_hal_gpio_read(pin);
+    if(pin == NULL) {
+        return false;
+    }
+
+    if(ctx->gpio_pins[raw_pin] == MP_FLIPPER_GPIO_MODE_INPUT) {
+        return furi_hal_gpio_read(pin);
+    } else {
+        return false;
+    }
 }

+ 79 - 0
lib/micropython-port/mp_flipper_modflipperzero_pwm.c

@@ -0,0 +1,79 @@
+#include <furi_hal.h>
+#include <furi_hal_pwm.h>
+
+#include <mp_flipper_modflipperzero.h>
+#include <mp_flipper_runtime.h>
+
+#include "mp_flipper_context.h"
+
+#define NO_VALUE (-1)
+
+inline static const FuriHalPwmOutputId decode_pin_to_output_id(uint8_t pin) {
+    switch(pin) {
+    case MP_FLIPPER_GPIO_PIN_PA4:
+        return FuriHalPwmOutputIdLptim2PA4;
+    case MP_FLIPPER_GPIO_PIN_PA7:
+        return FuriHalPwmOutputIdTim1PA7;
+    default:
+        return NO_VALUE;
+    }
+}
+
+inline bool mp_flipper_pwm_start(uint8_t raw_pin, uint32_t frequency, uint8_t duty) {
+    const mp_flipper_context_t* ctx = mp_flipper_context;
+
+    FuriHalPwmOutputId channel = decode_pin_to_output_id(raw_pin);
+
+    if(channel == NO_VALUE) {
+        return false;
+    }
+
+    if(ctx->gpio_pins[raw_pin] != MP_FLIPPER_GPIO_PIN_OFF &&
+       ctx->gpio_pins[raw_pin] != MP_FLIPPER_GPIO_PIN_PWM) {
+        return false;
+    }
+
+    if(ctx->gpio_pins[raw_pin] == MP_FLIPPER_GPIO_PIN_OFF) {
+        furi_hal_pwm_start(channel, frequency, duty);
+    } else {
+        furi_hal_pwm_set_params(channel, frequency, duty);
+    }
+
+    ctx->gpio_pins[raw_pin] = MP_FLIPPER_GPIO_PIN_PWM;
+
+    return true;
+}
+
+inline void mp_flipper_pwm_stop(uint8_t raw_pin) {
+    const mp_flipper_context_t* ctx = mp_flipper_context;
+
+    FuriHalPwmOutputId channel = decode_pin_to_output_id(raw_pin);
+
+    if(channel == NO_VALUE) {
+        return;
+    }
+
+    if(ctx->gpio_pins[raw_pin] != MP_FLIPPER_GPIO_PIN_PWM) {
+        return;
+    }
+
+    furi_hal_pwm_stop(channel);
+
+    ctx->gpio_pins[raw_pin] = MP_FLIPPER_GPIO_PIN_OFF;
+}
+
+inline bool mp_flipper_pwm_is_running(uint8_t raw_pin) {
+    const mp_flipper_context_t* ctx = mp_flipper_context;
+
+    FuriHalPwmOutputId channel = decode_pin_to_output_id(raw_pin);
+
+    if(channel == NO_VALUE) {
+        return false;
+    }
+
+    if(ctx->gpio_pins[raw_pin] != MP_FLIPPER_GPIO_PIN_PWM) {
+        return false;
+    }
+
+    return furi_hal_pwm_is_running(channel);
+}

+ 7 - 3
lib/micropython-port/mp_flipper_runtime.c

@@ -86,10 +86,10 @@ void* mp_flipper_context_alloc() {
 
     ctx->adc_handle = NULL;
 
-    ctx->gpio_pins_used = malloc(MP_FLIPPER_GPIO_PINS * sizeof(bool));
+    ctx->gpio_pins = malloc(MP_FLIPPER_GPIO_PINS * sizeof(mp_flipper_gpio_pin_t));
 
     for(uint8_t pin = 0; pin < MP_FLIPPER_GPIO_PINS; pin++) {
-        ctx->gpio_pins_used[pin] = false;
+        ctx->gpio_pins[pin] = MP_FLIPPER_GPIO_PIN_OFF;
     }
 
     return ctx;
@@ -121,7 +121,11 @@ void mp_flipper_context_free(void* context) {
         mp_flipper_gpio_deinit_pin(pin);
     }
 
-    free(ctx->gpio_pins_used);
+    // stop running PWM output
+    mp_flipper_pwm_stop(MP_FLIPPER_GPIO_PIN_PA4);
+    mp_flipper_pwm_stop(MP_FLIPPER_GPIO_PIN_PA7);
+
+    free(ctx->gpio_pins);
 
     free(ctx);
 }