diff --git a/drivers/mlx90640/mlx90640.hpp b/drivers/mlx90640/mlx90640.hpp index 69a20b4c..9133c3c2 100644 --- a/drivers/mlx90640/mlx90640.hpp +++ b/drivers/mlx90640/mlx90640.hpp @@ -1,3 +1,4 @@ +#include #include "src/headers/MLX90640_API.h" #include "common/pimoroni_i2c.hpp" @@ -8,13 +9,16 @@ void MLX90640_I2CConfigure(pimoroni::I2C *i2c_instance); namespace pimoroni { class MLX90640 { public: + static const int WIDTH = 32; + static const int HEIGHT = 24; + enum MLX90640_Error { OK = 0, INVALID_BAUDRATE = 1, INVALID_FPS = 2, }; - float mlx90640To[768] = {0.0f}; + float mlx90640To[WIDTH * HEIGHT] = {0.0f}; float emissivity = 1.0f; float reflected_temperature = 8.0f; diff --git a/micropython/modules/breakout_mlx90640/micropython.cmake b/micropython/modules/breakout_mlx90640/micropython.cmake new file mode 100644 index 00000000..0f2875b4 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/micropython.cmake @@ -0,0 +1,21 @@ +add_library(usermod_mlx90640 INTERFACE) + +target_sources(usermod_mlx90640 INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/mlx90640.c + ${CMAKE_CURRENT_LIST_DIR}/mlx90640.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/mlx90640.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/src/functions/MLX90640_API.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/MLX90640_RP2040_I2C_Driver.cpp +) + +target_include_directories(usermod_mlx90640 INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/ + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/src/headers/ +) + +target_compile_definitions(usermod_mlx90640 INTERFACE + MODULE_MLX90640_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_mlx90640) \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.c b/micropython/modules/breakout_mlx90640/mlx90640.c new file mode 100644 index 00000000..5877b4f7 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.c @@ -0,0 +1,45 @@ +#include "mlx90640.h" + + +MP_DEFINE_CONST_FUN_OBJ_2(MLX90640_setup_obj, MLX90640_setup); +MP_DEFINE_CONST_FUN_OBJ_1(MLX90640_get_frame_obj, MLX90640_get_frame); + +STATIC const mp_rom_map_elem_t MLX90640_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_setup), MP_ROM_PTR(&MLX90640_setup_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_frame), MP_ROM_PTR(&MLX90640_get_frame_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(MLX90640_locals_dict, MLX90640_locals_dict_table); + +#ifdef MP_DEFINE_CONST_OBJ_TYPE +MP_DEFINE_CONST_OBJ_TYPE( + MLX90640_MLX90640_type, + MP_QSTR_MLX90640, + MP_TYPE_FLAG_NONE, + make_new, MLX90640_make_new, + locals_dict, (mp_obj_dict_t*)&MLX90640_locals_dict +); +#else +const mp_obj_type_t MLX90640_MLX90640_type = { + { &mp_type_type }, + .name = MP_QSTR_MLX90640, + .make_new = MLX90640_make_new, + .locals_dict = (mp_obj_dict_t*)&MLX90640_locals_dict, +}; +#endif + +STATIC const mp_map_elem_t MLX90640_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_msa301) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MLX90640), (mp_obj_t)&MLX90640_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_MLX90640_globals, MLX90640_globals_table); + +const mp_obj_module_t MLX90640_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_MLX90640_globals, +}; + +#if MICROPY_VERSION <= 70144 +MP_REGISTER_MODULE(MP_QSTR_MLX90640, MLX90640_user_cmodule, MODULE_MLX90640_ENABLED); +#else +MP_REGISTER_MODULE(MP_QSTR_MLX90640, MLX90640_user_cmodule); +#endif \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.cpp b/micropython/modules/breakout_mlx90640/mlx90640.cpp new file mode 100644 index 00000000..36937702 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.cpp @@ -0,0 +1,65 @@ +#include "drivers/mlx90640/mlx90640.hpp" + +#include "micropython/modules/util.hpp" + +using namespace pimoroni; + +extern "C" { +#include "mlx90640.h" +#include "pimoroni_i2c.h" + +typedef struct _ModMLX90640_obj_t { + mp_obj_base_t base; + MLX90640 *breakout; + _PimoroniI2C_obj_t *i2c; + int address; +} ModMLX90640_obj_t; + +mp_obj_t MLX90640_setup(mp_obj_t self_in, mp_obj_t fps) { + _ModMLX90640_obj_t *self = MP_OBJ_TO_PTR2(self_in, _ModMLX90640_obj_t); + + self->breakout->setup(mp_obj_get_int(fps)); + + return mp_const_none; +} + +mp_obj_t MLX90640_get_frame(mp_obj_t self_in) { + _ModMLX90640_obj_t *self = MP_OBJ_TO_PTR2(self_in, _ModMLX90640_obj_t); + + self->breakout->get_frame(); + + mp_obj_list_t *list = MP_OBJ_TO_PTR2(mp_obj_new_list(MLX90640::WIDTH * MLX90640::HEIGHT, NULL), mp_obj_list_t); + + for(auto y = 0u; y < MLX90640::HEIGHT; y++) { + for(auto x = 0u; x < MLX90640::WIDTH; x++) { + int offset = y * MLX90640::WIDTH + x; + float v = self->breakout->mlx90640To[offset]; + list->items[offset] = mp_obj_new_float(v); + } + } + + return list; +} + +mp_obj_t MLX90640_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_i2c, ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_OBJ, {.u_obj = nullptr} }, + { MP_QSTR_address, MP_ARG_INT, {.u_int = MLX90640_DEFAULT_I2C_ADDRESS}} + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _ModMLX90640_obj_t *self = m_new_obj_with_finaliser(_ModMLX90640_obj_t); + self->base.type = &MLX90640_type; + + self->i2c = PimoroniI2C_from_machine_i2c_or_native(args[ARG_i2c].u_obj); + self->address = args[ARG_address].u_int; + + self->breakout = m_new_class(MLX90640, (pimoroni::I2C *)(self->i2c->i2c), self->address); + + return self; +} + +} \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.h b/micropython/modules/breakout_mlx90640/mlx90640.h new file mode 100644 index 00000000..3bf4bc0f --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.h @@ -0,0 +1,7 @@ +#include "py/runtime.h" + +extern const mp_obj_type_t MLX90640_type; + +extern mp_obj_t MLX90640_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t MLX90640_get_frame(mp_obj_t self_in); +extern mp_obj_t MLX90640_setup(mp_obj_t self_in, mp_obj_t fps_in); \ No newline at end of file