Skip to content

Commit 615aaf8

Browse files
committed
samd/machine_adc.c: Add attenuation setting to constructor.
Signed-off-by: Rick Sorensen <[email protected]>
1 parent f498a16 commit 615aaf8

File tree

1 file changed

+42
-4
lines changed

1 file changed

+42
-4
lines changed

ports/samd/machine_adc.c

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
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+
/*
32+
* RJS Note:
33+
* if MCU_SAMD21_SETVREF is defined
34+
* PA03 will be set to output,high for vref=3
35+
*
36+
* if RJS_DEBUG_PRINT is defined print init data
37+
*/
38+
3139
#include "py/mphal.h"
3240
#include "sam.h"
3341
#include "pin_af.h"
@@ -39,6 +47,7 @@ typedef struct _machine_adc_obj_t {
3947
uint8_t avg;
4048
uint8_t bits;
4149
uint8_t vref;
50+
uint8_t attenu;
4251
} machine_adc_obj_t;
4352

4453
#define DEFAULT_ADC_BITS 12
@@ -89,18 +98,19 @@ static void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_p
8998
(void)kind;
9099
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
91100

92-
mp_printf(print, "ADC(%q, device=%u, channel=%u, bits=%u, average=%u, vref=%d)",
101+
mp_printf(print, "ADC(%q, device=%u, channel=%u, bits=%u, average=%u, vref=%d, attenu=%d)",
93102
pin_find_by_id(self->id)->name, self->adc_config.device,
94-
self->adc_config.channel, self->bits, 1 << self->avg, self->vref);
103+
self->adc_config.channel, self->bits, 1 << self->avg, self->vref, self->attenu);
95104
}
96105

97106
static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
98-
enum { ARG_id, ARG_bits, ARG_average, ARG_vref };
107+
enum { ARG_id, ARG_bits, ARG_average, ARG_vref, ARG_attenu };
99108
static const mp_arg_t allowed_args[] = {
100109
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
101110
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = DEFAULT_ADC_BITS} },
102111
{ MP_QSTR_average, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_AVG} },
103112
{ MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_VREF} },
113+
{ MP_QSTR_attenu, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, // //RJS Gain .. non zero if DIV2
104114
};
105115

106116
// Parse the arguments.
@@ -127,6 +137,7 @@ static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args
127137
if (0 <= vref && vref < sizeof(adc_vref_table)) {
128138
self->vref = vref;
129139
}
140+
self->attenu = args[ARG_attenu].u_int; // RJS Gain
130141

131142
// flag the device/channel as being in use.
132143
busy_flags |= (1 << (self->adc_config.device * 16 + self->adc_config.channel));
@@ -142,9 +153,18 @@ static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
142153
Adc *adc = adc_bases[self->adc_config.device];
143154
// Set the reference voltage. Default: external AREFA.
144155
adc->REFCTRL.reg = adc_vref_table[self->vref];
156+
157+
uint32_t attenu = 0; // RJS Gain ... for DIV2 if desired.
158+
#if defined(MCU_SAMD21)
159+
// RJS Gain if vref == VDD/2, use gain DV2 to normalize to VDD
160+
if ((adc_vref_table[self->vref] == ADC_REFCTRL_REFSEL_INTVCC1_Val) && (self->attenu != 0)) {
161+
attenu = ADC_INPUTCTRL_GAIN_DIV2; // _Val is simp 4bit value 0XF .. now shifted to upper bits
162+
}
163+
#endif
145164
// Set Input channel and resolution
146165
// Select the pin as positive input and gnd as negative input reference, non-diff mode by default
147-
adc->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | self->adc_config.channel;
166+
adc->INPUTCTRL.reg = attenu | ADC_INPUTCTRL_MUXNEG_GND | self->adc_config.channel;
167+
// end RJS
148168
// set resolution. Scale 8-16 to 0 - 4 for table access.
149169
adc->CTRLB.bit.RESSEL = resolution[(self->bits - 8) / 2];
150170
// Measure input voltage
@@ -172,6 +192,21 @@ static void adc_init(machine_adc_obj_t *self) {
172192
Adc *adc = adc_bases[self->adc_config.device];
173193

174194
init_flags[self->adc_config.device] = true;
195+
#if defined(MCU_SAMD21_SETVREF)
196+
// RJS SAMD XIAO ... set VREFA pin high
197+
198+
if (adc_vref_table[self->vref] == ADC_REFCTRL_REFSEL_AREFA_Val) {
199+
int id = 3;// mp_hal_get_pin_obj("PA03"); // get VREF pin
200+
mp_hal_clr_pin_mux(id); // reset before writing
201+
mp_hal_pin_write(id, 1); // set high
202+
mp_hal_pin_output(id); // as output
203+
// if set, does not work .. ref not set ..
204+
// mp_hal_set_pin_mux(id,ALT_FCT_VREF); // now define pmux as VREF
205+
#if defined(RJS_DEBUG_PRINT)
206+
mp_printf(MP_PYTHON_PRINTER, "VREFA(3) set id=%d to output, val=1, no pmux\n", id);
207+
#endif
208+
}
209+
#endif
175210

176211
#if defined(MCU_SAMD21)
177212
// Configuration SAMD21
@@ -243,6 +278,9 @@ static void adc_init(machine_adc_obj_t *self) {
243278

244279
#endif
245280
}
281+
#if defined(RJS_DEBUG_PRINT)
282+
mp_printf(MP_PYTHON_PRINTER, "Setting id=%d PMUX to ADC\n", self->id);
283+
#endif
246284
// Set the port as given in self->id as ADC
247285
mp_hal_set_pin_mux(self->id, ALT_FCT_ADC);
248286
}

0 commit comments

Comments
 (0)