@@ -450,9 +450,116 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
450450}
451451STATIC MP_DEFINE_CONST_FUN_OBJ_3 (adc_read_timed_obj , adc_read_timed );
452452
453+ // read_timed_multi((adcx, adcy, ...), (bufx, bufy, ...), timer)
454+ //
455+ // Read analog values from multiple ADC's into buffers at a rate set by the
456+ // timer. The ADC values have 12-bit resolution and are stored directly into
457+ // the corresponding buffer if its element size is 16 bits or greater, otherwise
458+ // the sample resolution will be reduced to 8 bits.
459+ //
460+ // This function should not allocate any heap memory.
461+ STATIC mp_obj_t adc_read_timed_multi (mp_obj_t adc_array_in , mp_obj_t buf_array_in , mp_obj_t tim_in ) {
462+ size_t nadcs , nbufs ;
463+ mp_obj_t * adc_array , * buf_array ;
464+ mp_obj_get_array (adc_array_in , & nadcs , & adc_array );
465+ mp_obj_get_array (buf_array_in , & nbufs , & buf_array );
466+
467+ if (nadcs < 1 ) {
468+ mp_raise_ValueError ("need at least 1 ADC" );
469+ }
470+ if (nadcs != nbufs ) {
471+ mp_raise_ValueError ("length of ADC and buffer lists differ" );
472+ }
473+
474+ // Get buf for first ADC, get word size, check other buffers match in type
475+ mp_buffer_info_t bufinfo ;
476+ mp_get_buffer_raise (buf_array [0 ], & bufinfo , MP_BUFFER_WRITE );
477+ size_t typesize = mp_binary_get_size ('@' , bufinfo .typecode , NULL );
478+ for (uint array_index = 0 ; array_index < nbufs ; array_index ++ ) {
479+ mp_buffer_info_t bufinfo_curr ;
480+ mp_get_buffer_raise (buf_array [array_index ], & bufinfo_curr , MP_BUFFER_WRITE );
481+ if ((bufinfo .len != bufinfo_curr .len ) || (bufinfo .typecode != bufinfo_curr .typecode )) {
482+ mp_raise_ValueError ("size and type of buffers must match" );
483+ }
484+ }
485+
486+ // Use the supplied timer object as the sampling time base
487+ TIM_HandleTypeDef * tim ;
488+ tim = pyb_timer_get_handle (tim_in );
489+
490+ // Start adc; this is slow so wait for it to start
491+ pyb_obj_adc_t * adc0 = adc_array [0 ];
492+ adc_config_channel (& adc0 -> handle , adc0 -> channel );
493+ HAL_ADC_Start (& adc0 -> handle );
494+ // Wait for sample to complete and discard
495+ #define READ_TIMED_TIMEOUT (10) // in ms
496+ adc_wait_for_eoc_or_timeout (READ_TIMED_TIMEOUT );
497+ // Read (and discard) value
498+ uint value = ADCx -> DR ;
499+
500+ // Ensure first sample is on a timer tick
501+ __HAL_TIM_CLEAR_FLAG (tim , TIM_FLAG_UPDATE );
502+ while (__HAL_TIM_GET_FLAG (tim , TIM_FLAG_UPDATE ) == RESET ) {
503+ }
504+ __HAL_TIM_CLEAR_FLAG (tim , TIM_FLAG_UPDATE );
505+
506+ // Overrun check: assume success
507+ bool success = true;
508+ size_t nelems = bufinfo .len / typesize ;
509+ for (size_t elem_index = 0 ; elem_index < nelems ; elem_index ++ ) {
510+ if (__HAL_TIM_GET_FLAG (tim , TIM_FLAG_UPDATE ) != RESET ) {
511+ // Timer has already triggered
512+ success = false;
513+ } else {
514+ // Wait for the timer to trigger so we sample at the correct frequency
515+ while (__HAL_TIM_GET_FLAG (tim , TIM_FLAG_UPDATE ) == RESET ) {
516+ }
517+ }
518+ __HAL_TIM_CLEAR_FLAG (tim , TIM_FLAG_UPDATE );
519+
520+ for (size_t array_index = 0 ; array_index < nadcs ; array_index ++ ) {
521+ pyb_obj_adc_t * adc = adc_array [array_index ];
522+ // configure the ADC channel
523+ adc_config_channel (& adc -> handle , adc -> channel );
524+ // for the first sample we need to turn the ADC on
525+ // ADC is started: set the "start sample" bit
526+ #if defined(STM32F4 ) || defined(STM32F7 )
527+ ADCx -> CR2 |= (uint32_t )ADC_CR2_SWSTART ;
528+ #elif defined(STM32L4 )
529+ SET_BIT (ADCx -> CR , ADC_CR_ADSTART );
530+ #else
531+ #error Unsupported processor
532+ #endif
533+ // wait for sample to complete
534+ #define READ_TIMED_TIMEOUT (10) // in ms
535+ adc_wait_for_eoc_or_timeout (READ_TIMED_TIMEOUT );
536+
537+ // read value
538+ value = ADCx -> DR ;
539+
540+ // store values in buffer
541+ if (typesize == 1 ) {
542+ value >>= 4 ;
543+ }
544+ mp_buffer_info_t bufinfo_curr ; // Get buf for current ADC
545+ mp_get_buffer_raise (buf_array [array_index ], & bufinfo_curr , MP_BUFFER_WRITE );
546+ mp_binary_set_val_array_from_int (bufinfo_curr .typecode , bufinfo_curr .buf , elem_index , value );
547+ }
548+ }
549+
550+ // Turn the ADC off
551+ adc0 = adc_array [0 ];
552+ HAL_ADC_Stop (& adc0 -> handle );
553+
554+ return mp_obj_new_bool (success );
555+ }
556+ STATIC MP_DEFINE_CONST_FUN_OBJ_3 (adc_read_timed_multi_fun_obj , adc_read_timed_multi );
557+ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ (adc_read_timed_multi_obj , MP_ROM_PTR (& adc_read_timed_multi_fun_obj ));
558+
453559STATIC const mp_rom_map_elem_t adc_locals_dict_table [] = {
454560 { MP_ROM_QSTR (MP_QSTR_read ), MP_ROM_PTR (& adc_read_obj ) },
455561 { MP_ROM_QSTR (MP_QSTR_read_timed ), MP_ROM_PTR (& adc_read_timed_obj ) },
562+ { MP_ROM_QSTR (MP_QSTR_read_timed_multi ), MP_ROM_PTR (& adc_read_timed_multi_obj ) },
456563};
457564
458565STATIC MP_DEFINE_CONST_DICT (adc_locals_dict , adc_locals_dict_table );
0 commit comments