Skip to content

Commit 03eae48

Browse files
committed
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 <[email protected]>
1 parent 4212799 commit 03eae48

File tree

17 files changed

+371
-257
lines changed

17 files changed

+371
-257
lines changed

docs/library/machine.ADCBlock.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ Methods
3939
Configure the ADC peripheral. *bits* will set the resolution of the
4040
conversion process.
4141

42-
.. method:: ADCBlock.connect(channel)
43-
ADCBlock.connect(source)
44-
ADCBlock.connect(channel, source)
42+
.. method:: ADCBlock.connect(channel, *, ...)
43+
ADCBlock.connect(source, *, ...)
44+
ADCBlock.connect(channel, source, *, ...)
4545
4646
Connect up a channel on the ADC peripheral so it is ready for sampling,
4747
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
@@ -56,3 +56,6 @@ Methods
5656

5757
If both *channel* and *source* are given then they are connected together
5858
and made ready for sampling.
59+
60+
Any additional keyword arguments are used to configure the returned ADC object,
61+
via its :meth:`init <machine.ADC.init>` method.

extmod/extmod.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(MICROPY_SOURCE_EXTMOD
88
${MICROPY_DIR}/shared/libc/printf.c
99
${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c
1010
${MICROPY_EXTMOD_DIR}/machine_adc.c
11+
${MICROPY_EXTMOD_DIR}/machine_adc_block.c
1112
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
1213
${MICROPY_EXTMOD_DIR}/machine_i2c.c
1314
${MICROPY_EXTMOD_DIR}/machine_i2s.c

extmod/extmod.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
SRC_EXTMOD_C += \
55
extmod/machine_adc.c \
6+
extmod/machine_adc_block.c \
67
extmod/machine_bitstream.c \
78
extmod/machine_i2c.c \
89
extmod/machine_i2s.c \

extmod/machine_adc_block.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Jonathan Hogg
7+
* Copyright (c) 2023 Damien P. George
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "py/runtime.h"
29+
30+
#if MICROPY_PY_MACHINE_ADC_BLOCK
31+
32+
#include "py/mphal.h"
33+
#include "extmod/modmachine.h"
34+
35+
// The port must provide implementations of these low-level ADCBlock functions.
36+
STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self);
37+
STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit);
38+
STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits);
39+
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);
40+
41+
// The port provides implementations of the above in this file.
42+
#include MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE
43+
44+
STATIC void machine_adc_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
45+
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(self_in);
46+
mp_machine_adc_block_print(print, self);
47+
}
48+
49+
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) {
50+
enum {
51+
ARG_bits,
52+
};
53+
54+
static const mp_arg_t allowed_args[] = {
55+
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
56+
};
57+
58+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
59+
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
60+
61+
mp_int_t bits = args[ARG_bits].u_int;
62+
mp_machine_adc_block_bits_set(self, bits);
63+
}
64+
65+
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) {
66+
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
67+
mp_int_t unit = mp_obj_get_int(args[0]);
68+
machine_adc_block_obj_t *self = mp_machine_adc_block_get(unit);
69+
if (self == NULL) {
70+
mp_raise_ValueError(MP_ERROR_TEXT("invalid block id"));
71+
}
72+
73+
mp_map_t kw_args;
74+
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
75+
machine_adc_block_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
76+
77+
return MP_OBJ_FROM_PTR(self);
78+
}
79+
80+
STATIC mp_obj_t machine_adc_block_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
81+
machine_adc_block_obj_t *self = pos_args[0];
82+
machine_adc_block_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
83+
return mp_const_none;
84+
}
85+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_block_init);
86+
87+
STATIC mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
88+
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
89+
mp_int_t channel_id = -1;
90+
mp_hal_pin_obj_t pin = -1;
91+
if (n_pos_args == 2) {
92+
if (mp_obj_is_int(pos_args[1])) {
93+
channel_id = mp_obj_get_int(pos_args[1]);
94+
} else {
95+
pin = mp_hal_get_pin_obj(pos_args[1]);
96+
}
97+
} else if (n_pos_args == 3) {
98+
channel_id = mp_obj_get_int(pos_args[1]);
99+
pin = mp_hal_get_pin_obj(pos_args[2]);
100+
} else {
101+
mp_raise_TypeError(MP_ERROR_TEXT("too many positional args"));
102+
}
103+
104+
machine_adc_obj_t *adc = mp_machine_adc_block_connect(self, channel_id, pin, kw_args);
105+
if (adc == NULL) {
106+
mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC"));
107+
}
108+
109+
return MP_OBJ_FROM_PTR(adc);
110+
}
111+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_connect_obj, 2, machine_adc_block_connect);
112+
113+
STATIC const mp_rom_map_elem_t machine_adc_block_locals_dict_table[] = {
114+
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_block_init_obj) },
115+
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adc_block_connect_obj) },
116+
};
117+
STATIC MP_DEFINE_CONST_DICT(machine_adc_block_locals_dict, machine_adc_block_locals_dict_table);
118+
119+
MP_DEFINE_CONST_OBJ_TYPE(
120+
machine_adc_block_type,
121+
MP_QSTR_ADCBlock,
122+
MP_TYPE_FLAG_NONE,
123+
make_new, machine_adc_block_make_new,
124+
print, machine_adc_block_print,
125+
locals_dict, &machine_adc_block_locals_dict
126+
);
127+
128+
#endif // MICROPY_PY_MACHINE_ADC_BLOCK

extmod/modmachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128

129129
// A port must provide these types, but they are otherwise opaque.
130130
typedef struct _machine_adc_obj_t machine_adc_obj_t;
131+
typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t;
131132
typedef struct _machine_i2s_obj_t machine_i2s_obj_t;
132133
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
133134
typedef struct _machine_uart_obj_t machine_uart_obj_t;
@@ -200,6 +201,7 @@ extern const machine_mem_obj_t machine_mem32_obj;
200201
// Their Python bindings are implemented in extmod, and their implementation
201202
// is provided by a port.
202203
extern const mp_obj_type_t machine_adc_type;
204+
extern const mp_obj_type_t machine_adc_block_type;
203205
extern const mp_obj_type_t machine_i2c_type;
204206
extern const mp_obj_type_t machine_i2s_type;
205207
extern const mp_obj_type_t machine_mem_type;

ports/esp32/adc.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Nick Moore
7+
* Copyright (c) 2021 Jonathan Hogg
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "py/mphal.h"
29+
#include "adc.h"
30+
#include "driver/adc.h"
31+
32+
#define DEFAULT_VREF 1100
33+
34+
void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits) {
35+
switch (bits) {
36+
#if CONFIG_IDF_TARGET_ESP32
37+
case 9:
38+
self->width = ADC_WIDTH_BIT_9;
39+
break;
40+
case 10:
41+
self->width = ADC_WIDTH_BIT_10;
42+
break;
43+
case 11:
44+
self->width = ADC_WIDTH_BIT_11;
45+
break;
46+
#endif
47+
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
48+
case 12:
49+
self->width = ADC_WIDTH_BIT_12;
50+
break;
51+
#endif
52+
#if CONFIG_IDF_TARGET_ESP32S2
53+
case 13:
54+
self->width = ADC_WIDTH_BIT_13;
55+
break;
56+
#endif
57+
default:
58+
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
59+
}
60+
self->bits = bits;
61+
62+
if (self->unit_id == ADC_UNIT_1) {
63+
adc1_config_width(self->width);
64+
}
65+
for (adc_atten_t atten = ADC_ATTEN_DB_0; atten < ADC_ATTEN_MAX; atten++) {
66+
if (self->characteristics[atten] != NULL) {
67+
esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, self->characteristics[atten]);
68+
}
69+
}
70+
}
71+
72+
mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id) {
73+
int raw;
74+
if (self->unit_id == ADC_UNIT_1) {
75+
raw = adc1_get_raw(channel_id);
76+
} else {
77+
check_esp_err(adc2_get_raw(channel_id, self->width, &raw));
78+
}
79+
return raw;
80+
}
81+
82+
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) {
83+
int raw = madcblock_read_helper(self, channel_id);
84+
esp_adc_cal_characteristics_t *adc_chars = self->characteristics[atten];
85+
if (adc_chars == NULL) {
86+
adc_chars = malloc(sizeof(esp_adc_cal_characteristics_t));
87+
esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, adc_chars);
88+
self->characteristics[atten] = adc_chars;
89+
}
90+
mp_int_t uv = esp_adc_cal_raw_to_voltage(raw, adc_chars) * 1000;
91+
return uv;
92+
}

ports/esp32/adc.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* Development of the code in this file was sponsored by Microbric Pty Ltd
5+
*
6+
* The MIT License (MIT)
7+
*
8+
* Copyright (c) 2023 Damien P. George
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in
18+
* all copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26+
* THE SOFTWARE.
27+
*/
28+
#ifndef MICROPY_INCLUDED_ESP32_ADC_H
29+
#define MICROPY_INCLUDED_ESP32_ADC_H
30+
31+
#include "py/runtime.h"
32+
#include "esp_adc_cal.h"
33+
34+
#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM
35+
36+
typedef struct _machine_adc_block_obj_t {
37+
mp_obj_base_t base;
38+
adc_unit_t unit_id;
39+
mp_int_t bits;
40+
adc_bits_width_t width;
41+
esp_adc_cal_characteristics_t *characteristics[ADC_ATTEN_MAX];
42+
} machine_adc_block_obj_t;
43+
44+
typedef struct _machine_adc_obj_t {
45+
mp_obj_base_t base;
46+
machine_adc_block_obj_t *block;
47+
adc_channel_t channel_id;
48+
gpio_num_t gpio_id;
49+
} machine_adc_obj_t;
50+
51+
extern machine_adc_block_obj_t madcblock_obj[];
52+
53+
void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits);
54+
mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id);
55+
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten);
56+
57+
const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id);
58+
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);
59+
60+
#endif // MICROPY_INCLUDED_ESP32_ADC_H

ports/esp32/esp32_common.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ list(APPEND MICROPY_SOURCE_DRIVERS
5353
)
5454

5555
list(APPEND MICROPY_SOURCE_PORT
56+
adc.c
5657
main.c
5758
ppp_set_auth.c
5859
uart.c
@@ -66,7 +67,6 @@ list(APPEND MICROPY_SOURCE_PORT
6667
machine_timer.c
6768
machine_pin.c
6869
machine_touchpad.c
69-
machine_adcblock.c
7070
machine_dac.c
7171
machine_i2c.c
7272
modmachine.c

ports/esp32/machine_adc.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,9 @@
2828
// This file is never compiled standalone, it's included directly from
2929
// extmod/machine_adc.c via MICROPY_PY_MACHINE_ADC_INCLUDEFILE.
3030

31-
#include "esp_log.h"
32-
33-
#include "driver/gpio.h"
34-
#include "driver/adc.h"
35-
3631
#include "py/mphal.h"
37-
#include "machine_adc.h"
32+
#include "adc.h"
33+
#include "driver/adc.h"
3834

3935
#define ADCBLOCK1 (&madcblock_obj[0])
4036
#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
136132
madc_obj_atten[self - &madc_obj[0]] = atten + 1;
137133
}
138134

139-
const machine_adc_obj_t *madc_search_helper(madcblock_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) {
135+
const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) {
140136
for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) {
141137
const machine_adc_obj_t *adc = &madc_obj[i];
142138
if ((block == NULL || block == adc->block) && (channel_id == -1 || channel_id == adc->channel_id) && (gpio_id == -1 || gpio_id == adc->gpio_id)) {

ports/esp32/machine_adc.h

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)