5252#include "mpexception.h"
5353
5454
55- /// \moduleref pyb
56- /// \class ADC - analog to digital conversion: read analog values on a pin
57- ///
58- /// Usage:
59- ///
60- /// adc = pyb.ADC('GP5') # create an adc object on the given pin (GP2, GP3, GP4 o GP5)
61- /// adc.read() # read channel value
62- ///
63- /// The sample rate is fixed to 62.5KHz and the resolution to 12 bits.
64-
65-
6655/******************************************************************************
6756 DECLARE CONSTANTS
6857 ******************************************************************************/
7160/******************************************************************************
7261 DEFINE TYPES
7362 ******************************************************************************/
63+ typedef struct {
64+ mp_obj_base_t base ;
65+ bool enabled ;
66+ } pyb_adc_obj_t ;
67+
7468typedef struct {
7569 mp_obj_base_t base ;
7670 pin_obj_t * pin ;
7771 byte channel ;
7872 byte id ;
79- } pyb_adc_obj_t ;
73+ bool enabled ;
74+ } pyb_adc_channel_obj_t ;
75+
8076
8177/******************************************************************************
8278 DECLARE PRIVATE DATA
8379 ******************************************************************************/
84- STATIC pyb_adc_obj_t pyb_adc_obj [PYB_ADC_NUM_CHANNELS ] = { {.pin = & pin_GP2 , .channel = ADC_CH_0 , .id = 1 }, {.pin = & pin_GP3 , .channel = ADC_CH_1 , .id = 2 },
85- {.pin = & pin_GP4 , .channel = ADC_CH_2 , .id = 2 }, {.pin = & pin_GP5 , .channel = ADC_CH_3 , .id = 4 } };
80+ STATIC pyb_adc_channel_obj_t pyb_adc_channel_obj [PYB_ADC_NUM_CHANNELS ] = { {.pin = & pin_GP2 , .channel = ADC_CH_0 , .id = 0 , .enabled = false},
81+ {.pin = & pin_GP3 , .channel = ADC_CH_1 , .id = 1 , .enabled = false},
82+ {.pin = & pin_GP4 , .channel = ADC_CH_2 , .id = 2 , .enabled = false},
83+ {.pin = & pin_GP5 , .channel = ADC_CH_3 , .id = 3 , .enabled = false} };
84+ STATIC pyb_adc_obj_t pyb_adc_obj = {.enabled = false};
85+
86+ STATIC const mp_obj_type_t pyb_adc_channel_type ;
87+
88+ /******************************************************************************
89+ DECLARE PRIVATE FUNCTIONS
90+ ******************************************************************************/
91+ STATIC mp_obj_t adc_channel_deinit (mp_obj_t self_in );
8692
8793/******************************************************************************
8894 DEFINE PUBLIC FUNCTIONS
8995 ******************************************************************************/
90- STATIC void pybadc_init (pyb_adc_obj_t * self ) {
91- // configure the pin in analog mode
92- pin_config (self -> pin , -1 , PIN_TYPE_ANALOG , PIN_TYPE_STD , -1 , PIN_STRENGTH_2MA );
93- // enable the ADC channel
94- MAP_ADCChannelEnable (ADC_BASE , self -> channel );
96+ STATIC void pyb_adc_init (pyb_adc_obj_t * self ) {
9597 // enable and configure the timer
9698 MAP_ADCTimerConfig (ADC_BASE , (1 << 17 ) - 1 );
9799 MAP_ADCTimerEnable (ADC_BASE );
98100 // enable the ADC peripheral
99101 MAP_ADCEnable (ADC_BASE );
102+ self -> enabled = true;
103+ }
104+
105+ STATIC void pyb_adc_check_init (void ) {
106+ // not initialized
107+ if (!pyb_adc_obj .enabled ) {
108+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_request_not_possible ));
109+ }
110+ }
111+
112+ STATIC void pyb_adc_channel_init (pyb_adc_channel_obj_t * self ) {
113+ // the ADC block must be enabled first
114+ pyb_adc_check_init ();
115+ // configure the pin in analog mode
116+ pin_config (self -> pin , -1 , PIN_TYPE_ANALOG , PIN_TYPE_STD , -1 , PIN_STRENGTH_2MA );
117+ // enable the ADC channel
118+ MAP_ADCChannelEnable (ADC_BASE , self -> channel );
119+ self -> enabled = true;
120+ }
121+
122+ STATIC void pyb_adc_deinit_all_channels (void ) {
123+ for (int i = 0 ; i < PYB_ADC_NUM_CHANNELS ; i ++ ) {
124+ adc_channel_deinit (& pyb_adc_channel_obj [i ]);
125+ }
100126}
101127
102128/******************************************************************************/
103129/* Micro Python bindings : adc object */
104130
105131STATIC void adc_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
106132 pyb_adc_obj_t * self = self_in ;
107- mp_printf (print , "<ADC1 channel=%u on %q>" , self -> id , self -> pin -> name );
133+ if (self -> enabled ) {
134+ mp_printf (print , "ADC(0, bits=12)" );
135+ } else {
136+ mp_printf (print , "ADC(0)" );
137+ }
108138}
109139
110- /// \classmethod \constructor(pin)
111- /// Create an ADC object associated with the given pin.
112- /// This allows you to then read analog values on that pin.
113- STATIC mp_obj_t adc_make_new (mp_obj_t type_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * args ) {
114- // check number of arguments
115- mp_arg_check_num (n_args , n_kw , 1 , 1 , false);
116-
117- // the argument passed is the pin
118- const pin_obj_t * pin = (pin_obj_t * )pin_find (args [0 ]);
119- for (int32_t idx = 0 ; idx < PYB_ADC_NUM_CHANNELS ; idx ++ ) {
120- if (pin == pyb_adc_obj [idx ].pin ) {
121- pyb_adc_obj_t * self = & pyb_adc_obj [idx ];
122- self -> base .type = & pyb_adc_type ;
123- pybadc_init (self );
124- // register it with the sleep module
125- pybsleep_add ((const mp_obj_t )self , (WakeUpCB_t )pybadc_init );
126- return self ;
127- }
140+ STATIC const mp_arg_t pyb_adc_init_args [] = {
141+ { MP_QSTR_id , MP_ARG_INT , {.u_int = 0 } },
142+ { MP_QSTR_bits , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 12 } },
143+ };
144+ STATIC mp_obj_t adc_make_new (mp_obj_t type_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * all_args ) {
145+ // parse args
146+ mp_map_t kw_args ;
147+ mp_map_init_fixed_table (& kw_args , n_kw , all_args + n_args );
148+ mp_arg_val_t args [MP_ARRAY_SIZE (pyb_adc_init_args )];
149+ mp_arg_parse_all (n_args , all_args , & kw_args , MP_ARRAY_SIZE (args ), pyb_adc_init_args , args );
150+
151+ // check the peripheral id
152+ if (args [0 ].u_int != 0 ) {
153+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_resource_not_avaliable ));
128154 }
129- nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
130- }
131155
132- /// \method read()
133- /// Read the value on the analog pin and return it. The returned value
134- /// will be between 0 and 4095.
135- STATIC mp_obj_t adc_read (mp_obj_t self_in ) {
136- pyb_adc_obj_t * self = self_in ;
137- uint32_t sample ;
156+ // check the number of bits
157+ if (args [1 ].u_int != 12 ) {
158+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
159+ }
138160
139- // wait until a new value is available
140- while (!MAP_ADCFIFOLvlGet (ADC_BASE , self -> channel ));
141- // read the sample
142- sample = MAP_ADCFIFORead (ADC_BASE , self -> channel );
143- // the 12 bit sampled value is stored in bits [13:2]
144- return MP_OBJ_NEW_SMALL_INT ((sample & 0x3FFF ) >> 2 );
145- }
146- STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_read_obj , adc_read );
161+ // setup the object
162+ pyb_adc_obj_t * self = & pyb_adc_obj ;
163+ self -> base .type = & pyb_adc_type ;
147164
148- /// \method init()
149- /// Enable the adc channel
150- STATIC mp_obj_t adc_init (mp_obj_t self_in ) {
151- pyb_adc_obj_t * self = self_in ;
165+ // initialize and register with the sleep module
166+ pyb_adc_init (self );
167+ pybsleep_add ((const mp_obj_t )self , (WakeUpCB_t )pyb_adc_init );
168+ return self ;
169+ }
152170
153- pybadc_init (self );
171+ STATIC mp_obj_t adc_init (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
172+ // parse args
173+ mp_arg_val_t args [MP_ARRAY_SIZE (pyb_adc_init_args ) - 1 ];
174+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (args ), & pyb_adc_init_args [1 ], args );
175+ // check the number of bits
176+ if (args [0 ].u_int != 12 ) {
177+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
178+ }
179+ pyb_adc_init (pos_args [0 ]);
154180 return mp_const_none ;
155181}
156- STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_init_obj , adc_init );
182+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (adc_init_obj , 1 , adc_init );
157183
158- /// \method deinit()
159- /// Disable the adc channel
160184STATIC mp_obj_t adc_deinit (mp_obj_t self_in ) {
161185 pyb_adc_obj_t * self = self_in ;
162-
163- MAP_ADCChannelDisable (ADC_BASE , self -> channel );
186+ // first deinit all channels
187+ pyb_adc_deinit_all_channels ();
188+ MAP_ADCDisable (ADC_BASE );
189+ self -> enabled = false;
164190 // unregister it with the sleep module
165191 pybsleep_remove ((const mp_obj_t )self );
166192 return mp_const_none ;
167193}
168194STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_deinit_obj , adc_deinit );
169195
196+ STATIC mp_obj_t adc_channel (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
197+ STATIC const mp_arg_t pyb_adc_channel_args [] = {
198+ { MP_QSTR_id , MP_ARG_OBJ , {.u_obj = mp_const_none } },
199+ { MP_QSTR_pin , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
200+ };
201+
202+ // parse args
203+ mp_arg_val_t args [MP_ARRAY_SIZE (pyb_adc_channel_args )];
204+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (args ), pyb_adc_channel_args , args );
205+
206+ uint ch_id ;
207+ if (args [0 ].u_obj != mp_const_none ) {
208+ ch_id = mp_obj_get_int (args [0 ].u_obj );
209+ if (ch_id >= PYB_ADC_NUM_CHANNELS ) {
210+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_os_resource_not_avaliable ));
211+ }
212+ else if (args [1 ].u_obj != mp_const_none ) {
213+ uint pin_ch_id = pin_find_peripheral_type (args [1 ].u_obj , PIN_FN_ADC , 0 );
214+ if (ch_id != pin_ch_id ) {
215+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
216+ }
217+ }
218+ } else {
219+ ch_id = pin_find_peripheral_type (args [1 ].u_obj , PIN_FN_ADC , 0 );
220+ }
221+
222+ // setup the object
223+ pyb_adc_channel_obj_t * self = & pyb_adc_channel_obj [ch_id ];
224+ self -> base .type = & pyb_adc_channel_type ;
225+ pyb_adc_channel_init (self );
226+ // register it with the sleep module
227+ pybsleep_add ((const mp_obj_t )self , (WakeUpCB_t )pyb_adc_channel_init );
228+ return self ;
229+ }
230+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (adc_channel_obj , 1 , adc_channel );
231+
170232STATIC const mp_map_elem_t adc_locals_dict_table [] = {
171- { MP_OBJ_NEW_QSTR (MP_QSTR_read ), (mp_obj_t )& adc_read_obj },
172233 { MP_OBJ_NEW_QSTR (MP_QSTR_init ), (mp_obj_t )& adc_init_obj },
173234 { MP_OBJ_NEW_QSTR (MP_QSTR_deinit ), (mp_obj_t )& adc_deinit_obj },
235+ { MP_OBJ_NEW_QSTR (MP_QSTR_channel ), (mp_obj_t )& adc_channel_obj },
174236};
175237
176238STATIC MP_DEFINE_CONST_DICT (adc_locals_dict , adc_locals_dict_table );
@@ -183,3 +245,69 @@ const mp_obj_type_t pyb_adc_type = {
183245 .locals_dict = (mp_obj_t )& adc_locals_dict ,
184246};
185247
248+ STATIC void adc_channel_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
249+ pyb_adc_channel_obj_t * self = self_in ;
250+ if (self -> enabled ) {
251+ mp_printf (print , "ADCChannel(%u, pin=%q)" , self -> id , self -> pin -> name );
252+ } else {
253+ mp_printf (print , "ADCChannel(%u)" , self -> id );
254+ }
255+ }
256+
257+ STATIC mp_obj_t adc_channel_init (mp_obj_t self_in ) {
258+ pyb_adc_channel_obj_t * self = self_in ;
259+ // re-enable it
260+ pyb_adc_channel_init (self );
261+ return mp_const_none ;
262+ }
263+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_channel_init_obj , adc_channel_init );
264+
265+ STATIC mp_obj_t adc_channel_deinit (mp_obj_t self_in ) {
266+ pyb_adc_channel_obj_t * self = self_in ;
267+
268+ MAP_ADCChannelDisable (ADC_BASE , self -> channel );
269+ // unregister it with the sleep module
270+ pybsleep_remove ((const mp_obj_t )self );
271+ self -> enabled = false;
272+ return mp_const_none ;
273+ }
274+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_channel_deinit_obj , adc_channel_deinit );
275+
276+ STATIC mp_obj_t adc_channel_value (mp_obj_t self_in ) {
277+ pyb_adc_channel_obj_t * self = self_in ;
278+ uint32_t value ;
279+
280+ // the channel must be enabled
281+ if (!self -> enabled ) {
282+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , mpexception_os_request_not_possible ));
283+ }
284+
285+ // wait until a new value is available
286+ while (!MAP_ADCFIFOLvlGet (ADC_BASE , self -> channel ));
287+ // read the sample
288+ value = MAP_ADCFIFORead (ADC_BASE , self -> channel );
289+ // the 12 bit sampled value is stored in bits [13:2]
290+ return MP_OBJ_NEW_SMALL_INT ((value & 0x3FFF ) >> 2 );
291+ }
292+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (adc_channel_value_obj , adc_channel_value );
293+
294+ STATIC mp_obj_t adc_channel_call (mp_obj_t self_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * args ) {
295+ mp_arg_check_num (n_args , n_kw , 0 , 0 , false);
296+ return adc_channel_value (self_in );
297+ }
298+
299+ STATIC const mp_map_elem_t adc_channel_locals_dict_table [] = {
300+ { MP_OBJ_NEW_QSTR (MP_QSTR_init ), (mp_obj_t )& adc_channel_init_obj },
301+ { MP_OBJ_NEW_QSTR (MP_QSTR_deinit ), (mp_obj_t )& adc_channel_deinit_obj },
302+ { MP_OBJ_NEW_QSTR (MP_QSTR_value ), (mp_obj_t )& adc_channel_value_obj },
303+ };
304+
305+ STATIC MP_DEFINE_CONST_DICT (adc_channel_locals_dict , adc_channel_locals_dict_table );
306+
307+ STATIC const mp_obj_type_t pyb_adc_channel_type = {
308+ { & mp_type_type },
309+ .name = MP_QSTR_ADCChannel ,
310+ .print = adc_channel_print ,
311+ .call = adc_channel_call ,
312+ .locals_dict = (mp_obj_t )& adc_channel_locals_dict ,
313+ };
0 commit comments