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
97106static 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