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 <damien@micropython.org>
This commit is contained in:
parent
4212799fd8
commit
03eae48847
@ -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 <machine.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 <machine.ADC.init>` method.
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
128
extmod/machine_adc_block.c
Normal file
128
extmod/machine_adc_block.c
Normal file
@ -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
|
@ -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;
|
||||
|
92
ports/esp32/adc.c
Normal file
92
ports/esp32/adc.c
Normal file
@ -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;
|
||||
}
|
60
ports/esp32/adc.h
Normal file
60
ports/esp32/adc.h
Normal file
@ -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
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
72
ports/esp32/machine_adc_block.c
Normal file
72
ports/esp32/machine_adc_block.c
Normal file
@ -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;
|
||||
}
|
@ -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 <stdio.h>
|
||||
|
||||
#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
|
||||
);
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user