From 03eae48847c61985afece342df971f149c8ffa42 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 25 Oct 2023 19:13:11 +1100 Subject: [PATCH] extmod/machine_adc_block: Factor esp32 ADCBlock bindings to common code. This is a code factoring to have the Python bindings in one location, and all the ports use those same bindings. At this stage only esp32 implements this class, so the code for the bindings comes from that port. The documentation is also updated to reflect the esp32's behaviour of ADCBlock.connect(). Signed-off-by: Damien George --- docs/library/machine.ADCBlock.rst | 9 +- extmod/extmod.cmake | 1 + extmod/extmod.mk | 1 + extmod/machine_adc_block.c | 128 +++++++++++++++++++ extmod/modmachine.h | 2 + ports/esp32/adc.c | 92 ++++++++++++++ ports/esp32/adc.h | 60 +++++++++ ports/esp32/esp32_common.cmake | 2 +- ports/esp32/machine_adc.c | 10 +- ports/esp32/machine_adc.h | 16 --- ports/esp32/machine_adc_block.c | 72 +++++++++++ ports/esp32/machine_adcblock.c | 204 ------------------------------ ports/esp32/machine_adcblock.h | 22 ---- ports/esp32/modmachine.c | 4 +- ports/esp32/modmachine.h | 1 - ports/esp32/mpconfigport.h | 3 +- ports/renesas-ra/modmachine.h | 1 - 17 files changed, 371 insertions(+), 257 deletions(-) create mode 100644 extmod/machine_adc_block.c create mode 100644 ports/esp32/adc.c create mode 100644 ports/esp32/adc.h delete mode 100644 ports/esp32/machine_adc.h create mode 100644 ports/esp32/machine_adc_block.c delete mode 100644 ports/esp32/machine_adcblock.c delete mode 100644 ports/esp32/machine_adcblock.h diff --git a/docs/library/machine.ADCBlock.rst b/docs/library/machine.ADCBlock.rst index 56a468dd62..eb94362d55 100644 --- a/docs/library/machine.ADCBlock.rst +++ b/docs/library/machine.ADCBlock.rst @@ -39,9 +39,9 @@ Methods Configure the ADC peripheral. *bits* will set the resolution of the conversion process. -.. method:: ADCBlock.connect(channel) - ADCBlock.connect(source) - ADCBlock.connect(channel, source) +.. method:: ADCBlock.connect(channel, *, ...) + ADCBlock.connect(source, *, ...) + ADCBlock.connect(channel, source, *, ...) Connect up a channel on the ADC peripheral so it is ready for sampling, and return an :ref:`ADC ` object that represents that connection. @@ -56,3 +56,6 @@ Methods If both *channel* and *source* are given then they are connected together and made ready for sampling. + + Any additional keyword arguments are used to configure the returned ADC object, + via its :meth:`init ` method. diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index a1a0a9f736..5bfdf65513 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -8,6 +8,7 @@ set(MICROPY_SOURCE_EXTMOD ${MICROPY_DIR}/shared/libc/printf.c ${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c ${MICROPY_EXTMOD_DIR}/machine_adc.c + ${MICROPY_EXTMOD_DIR}/machine_adc_block.c ${MICROPY_EXTMOD_DIR}/machine_bitstream.c ${MICROPY_EXTMOD_DIR}/machine_i2c.c ${MICROPY_EXTMOD_DIR}/machine_i2s.c diff --git a/extmod/extmod.mk b/extmod/extmod.mk index c4b2c3d9c5..a04856bce2 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -3,6 +3,7 @@ SRC_EXTMOD_C += \ extmod/machine_adc.c \ + extmod/machine_adc_block.c \ extmod/machine_bitstream.c \ extmod/machine_i2c.c \ extmod/machine_i2s.c \ diff --git a/extmod/machine_adc_block.c b/extmod/machine_adc_block.c new file mode 100644 index 0000000000..f80e2dae4c --- /dev/null +++ b/extmod/machine_adc_block.c @@ -0,0 +1,128 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jonathan Hogg + * Copyright (c) 2023 Damien P. George + * + * 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. + */ + +#include "py/runtime.h" + +#if MICROPY_PY_MACHINE_ADC_BLOCK + +#include "py/mphal.h" +#include "extmod/modmachine.h" + +// The port must provide implementations of these low-level ADCBlock functions. +STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self); +STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit); +STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits); +STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t pin, mp_map_t *kw_args); + +// The port provides implementations of the above in this file. +#include MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE + +STATIC void machine_adc_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_machine_adc_block_print(print, self); +} + +STATIC void machine_adc_block_init_helper(machine_adc_block_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_bits, + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t bits = args[ARG_bits].u_int; + mp_machine_adc_block_bits_set(self, bits); +} + +STATIC mp_obj_t machine_adc_block_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) { + mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true); + mp_int_t unit = mp_obj_get_int(args[0]); + machine_adc_block_obj_t *self = mp_machine_adc_block_get(unit); + if (self == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid block id")); + } + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args); + machine_adc_block_init_helper(self, n_pos_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t machine_adc_block_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + machine_adc_block_obj_t *self = pos_args[0]; + machine_adc_block_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_block_init); + +STATIC mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_int_t channel_id = -1; + mp_hal_pin_obj_t pin = -1; + if (n_pos_args == 2) { + if (mp_obj_is_int(pos_args[1])) { + channel_id = mp_obj_get_int(pos_args[1]); + } else { + pin = mp_hal_get_pin_obj(pos_args[1]); + } + } else if (n_pos_args == 3) { + channel_id = mp_obj_get_int(pos_args[1]); + pin = mp_hal_get_pin_obj(pos_args[2]); + } else { + mp_raise_TypeError(MP_ERROR_TEXT("too many positional args")); + } + + machine_adc_obj_t *adc = mp_machine_adc_block_connect(self, channel_id, pin, kw_args); + if (adc == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC")); + } + + return MP_OBJ_FROM_PTR(adc); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_connect_obj, 2, machine_adc_block_connect); + +STATIC const mp_rom_map_elem_t machine_adc_block_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_block_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adc_block_connect_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_adc_block_locals_dict, machine_adc_block_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_block_type, + MP_QSTR_ADCBlock, + MP_TYPE_FLAG_NONE, + make_new, machine_adc_block_make_new, + print, machine_adc_block_print, + locals_dict, &machine_adc_block_locals_dict + ); + +#endif // MICROPY_PY_MACHINE_ADC_BLOCK diff --git a/extmod/modmachine.h b/extmod/modmachine.h index 6cace4f851..0744ef7889 100644 --- a/extmod/modmachine.h +++ b/extmod/modmachine.h @@ -128,6 +128,7 @@ // A port must provide these types, but they are otherwise opaque. typedef struct _machine_adc_obj_t machine_adc_obj_t; +typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t; typedef struct _machine_i2s_obj_t machine_i2s_obj_t; typedef struct _machine_pwm_obj_t machine_pwm_obj_t; typedef struct _machine_uart_obj_t machine_uart_obj_t; @@ -200,6 +201,7 @@ extern const machine_mem_obj_t machine_mem32_obj; // Their Python bindings are implemented in extmod, and their implementation // is provided by a port. extern const mp_obj_type_t machine_adc_type; +extern const mp_obj_type_t machine_adc_block_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_i2s_type; extern const mp_obj_type_t machine_mem_type; diff --git a/ports/esp32/adc.c b/ports/esp32/adc.c new file mode 100644 index 0000000000..c5886624ec --- /dev/null +++ b/ports/esp32/adc.c @@ -0,0 +1,92 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Nick Moore + * Copyright (c) 2021 Jonathan Hogg + * + * 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. + */ + +#include "py/mphal.h" +#include "adc.h" +#include "driver/adc.h" + +#define DEFAULT_VREF 1100 + +void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits) { + switch (bits) { + #if CONFIG_IDF_TARGET_ESP32 + case 9: + self->width = ADC_WIDTH_BIT_9; + break; + case 10: + self->width = ADC_WIDTH_BIT_10; + break; + case 11: + self->width = ADC_WIDTH_BIT_11; + break; + #endif + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + case 12: + self->width = ADC_WIDTH_BIT_12; + break; + #endif + #if CONFIG_IDF_TARGET_ESP32S2 + case 13: + self->width = ADC_WIDTH_BIT_13; + break; + #endif + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); + } + self->bits = bits; + + if (self->unit_id == ADC_UNIT_1) { + adc1_config_width(self->width); + } + for (adc_atten_t atten = ADC_ATTEN_DB_0; atten < ADC_ATTEN_MAX; atten++) { + if (self->characteristics[atten] != NULL) { + esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, self->characteristics[atten]); + } + } +} + +mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id) { + int raw; + if (self->unit_id == ADC_UNIT_1) { + raw = adc1_get_raw(channel_id); + } else { + check_esp_err(adc2_get_raw(channel_id, self->width, &raw)); + } + return raw; +} + +mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) { + int raw = madcblock_read_helper(self, channel_id); + esp_adc_cal_characteristics_t *adc_chars = self->characteristics[atten]; + if (adc_chars == NULL) { + adc_chars = malloc(sizeof(esp_adc_cal_characteristics_t)); + esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, adc_chars); + self->characteristics[atten] = adc_chars; + } + mp_int_t uv = esp_adc_cal_raw_to_voltage(raw, adc_chars) * 1000; + return uv; +} diff --git a/ports/esp32/adc.h b/ports/esp32/adc.h new file mode 100644 index 0000000000..ae5c0d3c37 --- /dev/null +++ b/ports/esp32/adc.h @@ -0,0 +1,60 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * Development of the code in this file was sponsored by Microbric Pty Ltd + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Damien P. George + * + * 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. + */ +#ifndef MICROPY_INCLUDED_ESP32_ADC_H +#define MICROPY_INCLUDED_ESP32_ADC_H + +#include "py/runtime.h" +#include "esp_adc_cal.h" + +#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM + +typedef struct _machine_adc_block_obj_t { + mp_obj_base_t base; + adc_unit_t unit_id; + mp_int_t bits; + adc_bits_width_t width; + esp_adc_cal_characteristics_t *characteristics[ADC_ATTEN_MAX]; +} machine_adc_block_obj_t; + +typedef struct _machine_adc_obj_t { + mp_obj_base_t base; + machine_adc_block_obj_t *block; + adc_channel_t channel_id; + gpio_num_t gpio_id; +} machine_adc_obj_t; + +extern machine_adc_block_obj_t madcblock_obj[]; + +void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits); +mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id); +mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten); + +const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id); +void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + +#endif // MICROPY_INCLUDED_ESP32_ADC_H diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake index f66c59e341..40ae98822d 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -53,6 +53,7 @@ list(APPEND MICROPY_SOURCE_DRIVERS ) list(APPEND MICROPY_SOURCE_PORT + adc.c main.c ppp_set_auth.c uart.c @@ -66,7 +67,6 @@ list(APPEND MICROPY_SOURCE_PORT machine_timer.c machine_pin.c machine_touchpad.c - machine_adcblock.c machine_dac.c machine_i2c.c modmachine.c diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index 42746cb4bd..b5233e4dda 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -28,13 +28,9 @@ // This file is never compiled standalone, it's included directly from // extmod/machine_adc.c via MICROPY_PY_MACHINE_ADC_INCLUDEFILE. -#include "esp_log.h" - -#include "driver/gpio.h" -#include "driver/adc.h" - #include "py/mphal.h" -#include "machine_adc.h" +#include "adc.h" +#include "driver/adc.h" #define ADCBLOCK1 (&madcblock_obj[0]) #define ADCBLOCK2 (&madcblock_obj[1]) @@ -136,7 +132,7 @@ static inline void madc_atten_set(const machine_adc_obj_t *self, adc_atten_t att madc_obj_atten[self - &madc_obj[0]] = atten + 1; } -const machine_adc_obj_t *madc_search_helper(madcblock_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) { +const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) { for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) { const machine_adc_obj_t *adc = &madc_obj[i]; if ((block == NULL || block == adc->block) && (channel_id == -1 || channel_id == adc->channel_id) && (gpio_id == -1 || gpio_id == adc->gpio_id)) { diff --git a/ports/esp32/machine_adc.h b/ports/esp32/machine_adc.h deleted file mode 100644 index 6d06486c30..0000000000 --- a/ports/esp32/machine_adc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MICROPY_INCLUDED_MACHINE_ADC_H -#define MICROPY_INCLUDED_MACHINE_ADC_H - -#include "machine_adcblock.h" - -typedef struct _machine_adc_obj_t { - mp_obj_base_t base; - madcblock_obj_t *block; - adc_channel_t channel_id; - gpio_num_t gpio_id; -} machine_adc_obj_t; - -const machine_adc_obj_t *madc_search_helper(madcblock_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id); -void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - -#endif // MICROPY_INCLUDED_MACHINE_ADC_H diff --git a/ports/esp32/machine_adc_block.c b/ports/esp32/machine_adc_block.c new file mode 100644 index 0000000000..f2975ff2f2 --- /dev/null +++ b/ports/esp32/machine_adc_block.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jonathan Hogg + * + * 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. + */ + +// This file is never compiled standalone, it's included directly from +// extmod/machine_adc_block.c via MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE. + +#include "py/mphal.h" +#include "adc.h" +#include "driver/adc.h" + +machine_adc_block_obj_t madcblock_obj[] = { + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + {{&machine_adc_block_type}, ADC_UNIT_1, 12, -1, {0}}, + {{&machine_adc_block_type}, ADC_UNIT_2, 12, -1, {0}}, + #elif CONFIG_IDF_TARGET_ESP32S2 + {{&machine_adc_block_type}, ADC_UNIT_1, 13, -1, {0}}, + {{&machine_adc_block_type}, ADC_UNIT_2, 13, -1, {0}}, + #endif +}; + +STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self) { + mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bits); +} + +STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits) { + if (bits != -1) { + madcblock_bits_helper(self, bits); + } else if (self->width == -1) { + madcblock_bits_helper(self, self->bits); + } +} + +STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit) { + for (int i = 0; i < MP_ARRAY_SIZE(madcblock_obj); i++) { + if (unit == madcblock_obj[i].unit_id) { + return &madcblock_obj[i]; + } + } + return NULL; +} + +STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t gpio_id, mp_map_t *kw_args) { + const machine_adc_obj_t *adc = madc_search_helper(self, channel_id, gpio_id); + if (adc == NULL) { + return NULL; + } + madc_init_helper(adc, 0, NULL, kw_args); + return (machine_adc_obj_t *)adc; +} diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c deleted file mode 100644 index 8d5296e2e5..0000000000 --- a/ports/esp32/machine_adcblock.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Jonathan Hogg - * - * 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. - */ - -#include - -#include "esp_log.h" - -#include "driver/gpio.h" -#include "driver/adc.h" - -#include "py/runtime.h" -#include "py/mphal.h" -#include "modmachine.h" -#include "machine_adc.h" -#include "machine_adcblock.h" - -#define DEFAULT_VREF 1100 - -madcblock_obj_t madcblock_obj[] = { - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - {{&machine_adcblock_type}, ADC_UNIT_1, 12, -1, {0}}, - {{&machine_adcblock_type}, ADC_UNIT_2, 12, -1, {0}}, - #elif CONFIG_IDF_TARGET_ESP32S2 - {{&machine_adcblock_type}, ADC_UNIT_1, 13, -1, {0}}, - {{&machine_adcblock_type}, ADC_UNIT_2, 13, -1, {0}}, - #endif -}; - -STATIC void madcblock_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - madcblock_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bits); -} - -void madcblock_bits_helper(madcblock_obj_t *self, mp_int_t bits) { - switch (bits) { - #if CONFIG_IDF_TARGET_ESP32 - case 9: - self->width = ADC_WIDTH_BIT_9; - break; - case 10: - self->width = ADC_WIDTH_BIT_10; - break; - case 11: - self->width = ADC_WIDTH_BIT_11; - break; - #endif - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - case 12: - self->width = ADC_WIDTH_BIT_12; - break; - #endif - #if CONFIG_IDF_TARGET_ESP32S2 - case 13: - self->width = ADC_WIDTH_BIT_13; - break; - #endif - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); - } - self->bits = bits; - - if (self->unit_id == ADC_UNIT_1) { - adc1_config_width(self->width); - } - for (adc_atten_t atten = ADC_ATTEN_DB_0; atten < ADC_ATTEN_MAX; atten++) { - if (self->characteristics[atten] != NULL) { - esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, self->characteristics[atten]); - } - } -} - -STATIC void madcblock_init_helper(madcblock_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { - ARG_bits, - }; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t bits = args[ARG_bits].u_int; - if (bits != -1) { - madcblock_bits_helper(self, bits); - } else if (self->width == -1) { - madcblock_bits_helper(self, self->bits); - } -} - -STATIC mp_obj_t madcblock_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) { - mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true); - adc_unit_t unit = mp_obj_get_int(args[0]); - madcblock_obj_t *self = NULL; - for (int i = 0; i < MP_ARRAY_SIZE(madcblock_obj); i++) { - if (unit == madcblock_obj[i].unit_id) { - self = &madcblock_obj[i]; - break; - } - } - if (!self) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid block id")); - } - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args); - madcblock_init_helper(self, n_pos_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t madcblock_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - madcblock_obj_t *self = pos_args[0]; - madcblock_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madcblock_init_obj, 1, madcblock_init); - -STATIC mp_obj_t madcblock_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - madcblock_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - adc_channel_t channel_id = -1; - gpio_num_t gpio_id = -1; - if (n_pos_args == 2) { - if (mp_obj_is_int(pos_args[1])) { - channel_id = mp_obj_get_int(pos_args[1]); - } else { - gpio_id = machine_pin_get_id(pos_args[1]); - } - } else if (n_pos_args == 3) { - channel_id = mp_obj_get_int(pos_args[1]); - gpio_id = machine_pin_get_id(pos_args[2]); - } else { - mp_raise_TypeError(MP_ERROR_TEXT("too many positional args")); - } - - const machine_adc_obj_t *adc = madc_search_helper(self, channel_id, gpio_id); - if (adc != NULL) { - madc_init_helper(adc, 0, pos_args + n_pos_args, kw_args); - return MP_OBJ_FROM_PTR(adc); - } - mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC")); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madcblock_connect_obj, 2, madcblock_connect); - -mp_int_t madcblock_read_helper(madcblock_obj_t *self, adc_channel_t channel_id) { - int raw; - if (self->unit_id == ADC_UNIT_1) { - raw = adc1_get_raw(channel_id); - } else { - check_esp_err(adc2_get_raw(channel_id, self->width, &raw)); - } - return raw; -} - -mp_int_t madcblock_read_uv_helper(madcblock_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) { - int raw = madcblock_read_helper(self, channel_id); - esp_adc_cal_characteristics_t *adc_chars = self->characteristics[atten]; - if (adc_chars == NULL) { - adc_chars = malloc(sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, adc_chars); - self->characteristics[atten] = adc_chars; - } - mp_int_t uv = esp_adc_cal_raw_to_voltage(raw, adc_chars) * 1000; - return uv; -} - -STATIC const mp_rom_map_elem_t madcblock_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&madcblock_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&madcblock_connect_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(madcblock_locals_dict, madcblock_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - machine_adcblock_type, - MP_QSTR_ADCBlock, - MP_TYPE_FLAG_NONE, - make_new, madcblock_make_new, - print, madcblock_print, - locals_dict, &madcblock_locals_dict - ); diff --git a/ports/esp32/machine_adcblock.h b/ports/esp32/machine_adcblock.h deleted file mode 100644 index 7c9249b072..0000000000 --- a/ports/esp32/machine_adcblock.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MICROPY_INCLUDED_MACHINE_ADCBLOCK_H -#define MICROPY_INCLUDED_MACHINE_ADCBLOCK_H - -#include "esp_adc_cal.h" - -#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM - -typedef struct _madcblock_obj_t { - mp_obj_base_t base; - adc_unit_t unit_id; - mp_int_t bits; - adc_bits_width_t width; - esp_adc_cal_characteristics_t *characteristics[ADC_ATTEN_MAX]; -} madcblock_obj_t; - -extern madcblock_obj_t madcblock_obj[]; - -extern void madcblock_bits_helper(madcblock_obj_t *self, mp_int_t bits); -extern mp_int_t madcblock_read_helper(madcblock_obj_t *self, adc_channel_t channel_id); -extern mp_int_t madcblock_read_uv_helper(madcblock_obj_t *self, adc_channel_t channel_id, adc_atten_t atten); - -#endif // MICROPY_INCLUDED_MACHINE_ADCBLOCK_H diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 1e83935a8b..461ddacdad 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -312,7 +312,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_PY_MACHINE_ADC { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #endif - { MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adcblock_type) }, + #if MICROPY_PY_MACHINE_ADC_BLOCK + { MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adc_block_type) }, + #endif #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, #endif diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 7b26df609d..06a1d7b0e2 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -10,7 +10,6 @@ typedef enum { } wake_type_t; extern const mp_obj_type_t machine_touchpad_type; -extern const mp_obj_type_t machine_adcblock_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index b4ec082092..706baae5b2 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -99,10 +99,11 @@ #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_ADC_INCLUDEFILE "ports/esp32/machine_adc.c" #define MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH (1) -#define MICROPY_PY_MACHINE_ADC_BLOCK (1) #define MICROPY_PY_MACHINE_ADC_INIT (1) #define MICROPY_PY_MACHINE_ADC_READ (1) #define MICROPY_PY_MACHINE_ADC_READ_UV (1) +#define MICROPY_PY_MACHINE_ADC_BLOCK (1) +#define MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE "ports/esp32/machine_adc_block.c" #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_BITSTREAM (1) #define MICROPY_PY_MACHINE_PULSE (1) diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h index 9bb3196b37..22d1fc475e 100644 --- a/ports/renesas-ra/modmachine.h +++ b/ports/renesas-ra/modmachine.h @@ -30,7 +30,6 @@ #include "py/obj.h" extern const mp_obj_type_t machine_touchpad_type; -extern const mp_obj_type_t machine_adcblock_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_sdcard_type;