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

+ 5 - 0
CHANGELOG.md

@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 
 ## [Unreleased]
 ## [Unreleased]
 
 
+### Added
+
+* Floating point support
+* Basic speaker support for `flipperzero` module
+
 ## [0.2.0-alpha.1] - 2024-04-03
 ## [0.2.0-alpha.1] - 2024-04-03
 
 
 ### Added
 ### Added

+ 0 - 6
Makefile.micropython

@@ -1,9 +1,3 @@
-# This file is part of the MicroPython project, http://micropython.org/
-# The MIT License (MIT)
-# Copyright (c) 2022-2023 Damien P. George
-#
-# This file is intended to be included by a Makefile in a custom project.
-
 # Set the build output directory for the generated files.
 # Set the build output directory for the generated files.
 BUILD = build-embed
 BUILD = build-embed
 
 

+ 20 - 2
application.fam

@@ -22,7 +22,16 @@ App(
             name="micropython-build",
             name="micropython-build",
             cflags=[
             cflags=[
                 "-Wno-error",
                 "-Wno-error",
-                "-w"
+                "-w",
+                #
+                # required for floating point support
+                #
+                "-mcpu=cortex-m4",
+                "-mfloat-abi=hard",
+                "-mfpu=fpv4-sp-d16",
+                "-mthumb",
+                "-fsingle-precision-constant",
+                "-fno-math-errno",
             ],
             ],
             cincludes=["."]
             cincludes=["."]
         ),
         ),
@@ -30,7 +39,16 @@ App(
             name="micropython-port",
             name="micropython-port",
             cflags=[
             cflags=[
                 "-Wno-error",
                 "-Wno-error",
-                "-w"
+                "-w",
+                #
+                # required for floating point support
+                #
+                "-mcpu=cortex-m4",
+                "-mfloat-abi=hard",
+                "-mfpu=fpv4-sp-d16",
+                "-mthumb",
+                "-fsingle-precision-constant",
+                "-fno-math-errno",
             ],
             ],
             cincludes=["."]
             cincludes=["."]
         ),
         ),

+ 25 - 0
examples/flipperzero_speaker_test.py

@@ -0,0 +1,25 @@
+import time
+import flipperzero
+
+def play_frequency(frequency: float):
+  volume = 0.8
+
+  flipperzero.speaker_start(frequency, volume)
+
+  for _ in range(0, 150):
+    volume *= 0.9945679
+
+    flipperzero.speaker_set_volume(volume)
+
+    time.sleep_ms(1)
+
+  flipperzero.speaker_stop()
+
+play_frequency(100.0)
+play_frequency(200.0)
+play_frequency(300.0)
+play_frequency(500.0)
+play_frequency(800.0)
+play_frequency(1300.0)
+play_frequency(2100.0)
+play_frequency(3400.0)

+ 1 - 1
lib/micropython-port/file_reader.c

@@ -5,7 +5,7 @@
 
 
 #include <py/reader.h>
 #include <py/reader.h>
 
 
-#include "state.h"
+#include <mp_flipper_app.h>
 
 
 typedef struct {
 typedef struct {
     size_t pointer;
     size_t pointer;

+ 142 - 0
lib/micropython-port/math.c

@@ -0,0 +1,142 @@
+#include <stdint.h>
+#include <float.h>
+#include <math.h>
+
+#define FORCE_EVAL(x)                            \
+    do {                                         \
+        if(sizeof(x) == sizeof(float)) {         \
+            volatile float __x;                  \
+            __x = (x);                           \
+            (void)__x;                           \
+        } else if(sizeof(x) == sizeof(double)) { \
+            volatile double __x;                 \
+            __x = (x);                           \
+            (void)__x;                           \
+        } else {                                 \
+            volatile long double __x;            \
+            __x = (x);                           \
+            (void)__x;                           \
+        }                                        \
+    } while(0)
+
+float floorf(float x) {
+    union {
+        float f;
+        uint32_t i;
+    } u = {x};
+    int e = (int)(u.i >> 23 & 0xff) - 0x7f;
+    uint32_t m;
+
+    if(e >= 23) return x;
+    if(e >= 0) {
+        m = 0x007fffff >> e;
+        if((u.i & m) == 0) return x;
+        FORCE_EVAL(x + 0x1p120f);
+        if(u.i >> 31) u.i += m;
+        u.i &= ~m;
+    } else {
+        FORCE_EVAL(x + 0x1p120f);
+        if(u.i >> 31 == 0)
+            u.i = 0;
+        else if(u.i << 1)
+            u.f = -1.0;
+    }
+    return u.f;
+}
+
+float fmodf(float x, float y) {
+    union {
+        float f;
+        uint32_t i;
+    } ux = {x}, uy = {y};
+    int ex = ux.i >> 23 & 0xff;
+    int ey = uy.i >> 23 & 0xff;
+    uint32_t sx = ux.i & 0x80000000;
+    uint32_t i;
+    uint32_t uxi = ux.i;
+
+    if(uy.i << 1 == 0 || isnan(y) || ex == 0xff) return (x * y) / (x * y);
+    if(uxi << 1 <= uy.i << 1) {
+        if(uxi << 1 == uy.i << 1) return 0 * x;
+        return x;
+    }
+
+    /* normalize x and y */
+    if(!ex) {
+        for(i = uxi << 9; i >> 31 == 0; ex--, i <<= 1)
+            ;
+        uxi <<= -ex + 1;
+    } else {
+        uxi &= -1U >> 9;
+        uxi |= 1U << 23;
+    }
+    if(!ey) {
+        for(i = uy.i << 9; i >> 31 == 0; ey--, i <<= 1)
+            ;
+        uy.i <<= -ey + 1;
+    } else {
+        uy.i &= -1U >> 9;
+        uy.i |= 1U << 23;
+    }
+
+    /* x mod y */
+    for(; ex > ey; ex--) {
+        i = uxi - uy.i;
+        if(i >> 31 == 0) {
+            if(i == 0) return 0 * x;
+            uxi = i;
+        }
+        uxi <<= 1;
+    }
+    i = uxi - uy.i;
+    if(i >> 31 == 0) {
+        if(i == 0) return 0 * x;
+        uxi = i;
+    }
+    for(; uxi >> 23 == 0; uxi <<= 1, ex--)
+        ;
+
+    /* scale result up */
+    if(ex > 0) {
+        uxi -= 1U << 23;
+        uxi |= (uint32_t)ex << 23;
+    } else {
+        uxi >>= -ex + 1;
+    }
+    uxi |= sx;
+    ux.i = uxi;
+    return ux.f;
+}
+
+float nearbyintf(float x) {
+    union {
+        float f;
+        uint32_t i;
+    } u = {x};
+    int e = u.i >> 23 & 0xff;
+    int s = u.i >> 31;
+    float_t y;
+
+    if(e >= 0x7f + 23) return x;
+    if(s)
+        y = x - 0x1p23f + 0x1p23f;
+    else
+        y = x + 0x1p23f - 0x1p23f;
+    if(y == 0) return s ? -0.0f : 0.0f;
+    return y;
+}
+
+//
+// __aebi_x2x functions are just here to prevent compiler warnings
+//
+double __aeabi_i2d(int x) {
+    return (double)x;
+}
+
+float __aeabi_d2f(double x) {
+    return (float)x;
+}
+
+double __aeabi_f2d(float x) {
+    return (double)x;
+}

+ 26 - 1
lib/micropython-port/modflipperzero.c

@@ -4,7 +4,7 @@
 #include <py/obj.h>
 #include <py/obj.h>
 #include <py/runtime.h>
 #include <py/runtime.h>
 
 
-#include "_modflipperzero.h"
+#include "modflipperzero.h"
 
 
 static mp_obj_t flipperzero_light_set(mp_obj_t light_obj, mp_obj_t brightness_obj) {
 static mp_obj_t flipperzero_light_set(mp_obj_t light_obj, mp_obj_t brightness_obj) {
     mp_int_t light = mp_obj_get_int(light_obj);
     mp_int_t light = mp_obj_get_int(light_obj);
@@ -57,6 +57,28 @@ static mp_obj_t flipperzero_vibro_set(mp_obj_t state) {
 }
 }
 static MP_DEFINE_CONST_FUN_OBJ_1(flipperzero_vibro_set_obj, flipperzero_vibro_set);
 static MP_DEFINE_CONST_FUN_OBJ_1(flipperzero_vibro_set_obj, flipperzero_vibro_set);
 
 
+static mp_obj_t flipperzero_speaker_start(mp_obj_t frequency_obj, mp_obj_t volume_obj) {
+    mp_float_t frequency = mp_obj_get_float(frequency_obj);
+    mp_float_t volume = mp_obj_get_float(volume_obj);
+
+    return mp_flipper_speaker_start(frequency, volume) ? mp_const_true : mp_const_false;
+}
+static MP_DEFINE_CONST_FUN_OBJ_2(flipperzero_speaker_start_obj, flipperzero_speaker_start);
+
+static mp_obj_t flipperzero_speaker_set_volume(mp_obj_t volume_obj) {
+    mp_float_t volume = mp_obj_get_float(volume_obj);
+
+    return mp_flipper_speaker_set_volume(volume) ? mp_const_true : mp_const_false;
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(flipperzero_speaker_set_volume_obj, flipperzero_speaker_set_volume);
+
+static mp_obj_t flipperzero_speaker_stop() {
+    mp_flipper_speaker_stop();
+
+    return mp_flipper_speaker_stop() ? mp_const_true : mp_const_false;
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(flipperzero_speaker_stop_obj, flipperzero_speaker_stop);
+
 static const mp_rom_map_elem_t flipperzero_module_globals_table[] = {
 static const mp_rom_map_elem_t flipperzero_module_globals_table[] = {
     {MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_flipperzero)},
     {MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_flipperzero)},
     {MP_ROM_QSTR(MP_QSTR_LIGHT_RED), MP_ROM_INT(MP_FLIPPER_LED_RED)},
     {MP_ROM_QSTR(MP_QSTR_LIGHT_RED), MP_ROM_INT(MP_FLIPPER_LED_RED)},
@@ -68,6 +90,9 @@ static const mp_rom_map_elem_t flipperzero_module_globals_table[] = {
     {MP_ROM_QSTR(MP_QSTR_light_blink_set_color), MP_ROM_PTR(&flipperzero_light_blink_set_color_obj)},
     {MP_ROM_QSTR(MP_QSTR_light_blink_set_color), MP_ROM_PTR(&flipperzero_light_blink_set_color_obj)},
     {MP_ROM_QSTR(MP_QSTR_light_blink_stop), MP_ROM_PTR(&flipperzero_light_blink_stop_obj)},
     {MP_ROM_QSTR(MP_QSTR_light_blink_stop), MP_ROM_PTR(&flipperzero_light_blink_stop_obj)},
     {MP_ROM_QSTR(MP_QSTR_vibro_set), MP_ROM_PTR(&flipperzero_vibro_set_obj)},
     {MP_ROM_QSTR(MP_QSTR_vibro_set), MP_ROM_PTR(&flipperzero_vibro_set_obj)},
+    {MP_ROM_QSTR(MP_QSTR_speaker_start), MP_ROM_PTR(&flipperzero_speaker_start_obj)},
+    {MP_ROM_QSTR(MP_QSTR_speaker_set_volume), MP_ROM_PTR(&flipperzero_speaker_set_volume_obj)},
+    {MP_ROM_QSTR(MP_QSTR_speaker_stop), MP_ROM_PTR(&flipperzero_speaker_stop_obj)},
 };
 };
 static MP_DEFINE_CONST_DICT(flipperzero_module_globals, flipperzero_module_globals_table);
 static MP_DEFINE_CONST_DICT(flipperzero_module_globals, flipperzero_module_globals_table);
 
 

+ 4 - 0
lib/micropython-port/_modflipperzero.h → lib/micropython-port/modflipperzero.h

@@ -14,3 +14,7 @@ void mp_flipper_light_blink_set_color(uint8_t raw_light);
 void mp_flipper_light_blink_stop();
 void mp_flipper_light_blink_stop();
 
 
 void mp_flipper_vibro(bool state);
 void mp_flipper_vibro(bool state);
+
+bool mp_flipper_speaker_start(float frequency, float volume);
+bool mp_flipper_speaker_set_volume(float volume);
+bool mp_flipper_speaker_stop();

+ 32 - 3
lib/micropython-port/_modflipperzero.c → lib/micropython-port/modflipperzero_impl.c

@@ -1,8 +1,6 @@
-#include <stdbool.h>
-
 #include <furi_hal.h>
 #include <furi_hal.h>
 
 
-#include "_modflipperzero.h"
+#include "modflipperzero.h"
 
 
 static Light decode_light(uint8_t value) {
 static Light decode_light(uint8_t value) {
     Light light = 0;
     Light light = 0;
@@ -40,3 +38,34 @@ inline void mp_flipper_light_blink_stop() {
 inline void mp_flipper_vibro(bool state) {
 inline void mp_flipper_vibro(bool state) {
     furi_hal_vibro_on(state);
     furi_hal_vibro_on(state);
 }
 }
+
+inline bool mp_flipper_speaker_start(float frequency, float volume) {
+    if(furi_hal_speaker_acquire(100)) {
+        furi_hal_speaker_start(frequency, volume);
+
+        return true;
+    }
+
+    return false;
+}
+
+inline bool mp_flipper_speaker_set_volume(float volume) {
+    if(furi_hal_speaker_is_mine()) {
+        furi_hal_speaker_set_volume(volume);
+
+        return true;
+    }
+    return false;
+}
+
+inline bool mp_flipper_speaker_stop() {
+    if(furi_hal_speaker_is_mine()) {
+        furi_hal_speaker_stop();
+
+        furi_hal_speaker_release();
+
+        return true;
+    }
+
+    return false;
+}

+ 1 - 1
lib/micropython-port/mphalport.c

@@ -6,7 +6,7 @@
 #include <py/mphal.h>
 #include <py/mphal.h>
 #include <py/builtin.h>
 #include <py/builtin.h>
 
 
-#include "state.h"
+#include <mp_flipper_app.h>
 
 
 const mp_obj_fun_builtin_var_t mp_builtin_open_obj;
 const mp_obj_fun_builtin_var_t mp_builtin_open_obj;
 
 

+ 1 - 1
mp_flipper_app.c

@@ -4,7 +4,7 @@
 
 
 #include <port/micropython_embed.h>
 #include <port/micropython_embed.h>
 
 
-#include "state.h"
+#include "mp_flipper_app.h"
 
 
 const char* root_module_path;
 const char* root_module_path;
 
 

+ 0 - 0
state.h → mp_flipper_app.h


+ 4 - 0
mpconfigport.h

@@ -36,3 +36,7 @@ typedef long mp_off_t;
 #define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
 #define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
 
 
 #define MICROPY_PY_RANDOM_SEED_INIT_FUNC (mp_flipper_seed_init())
 #define MICROPY_PY_RANDOM_SEED_INIT_FUNC (mp_flipper_seed_init())
+
+#define MICROPY_PY_MATH (0)
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)