40
40
41
41
// Number of active ADC channels.
42
42
volatile uint8_t active_channel_count ;
43
+
44
+ // Shared between all the instances. Allocated only when needed.
43
45
struct adc_module * adc_instance = NULL ;
46
+ struct adc_config * config_adc = NULL ;
44
47
45
48
void common_hal_analogio_analogin_construct (analogio_analogin_obj_t * self ,
46
49
const mcu_pin_obj_t * pin ) {
@@ -53,23 +56,24 @@ void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
53
56
self -> pin = pin ;
54
57
55
58
if (adc_instance == NULL ) {
56
- struct adc_config config_adc ;
57
- adc_get_config_defaults (& config_adc );
58
-
59
- config_adc .reference = ADC_REFERENCE_INTVCC1 ;
60
- config_adc .gain_factor = ADC_GAIN_FACTOR_DIV2 ;
61
- config_adc .positive_input = self -> pin -> adc_input ;
62
- config_adc .resolution = ADC_RESOLUTION_16BIT ;
63
- config_adc .clock_prescaler = ADC_CLOCK_PRESCALER_DIV128 ;
64
-
65
- // Allocate the instance on the heap so we only use the memory when we
59
+ // Allocate strucs on the heap so we only use the memory when we
66
60
// need it.
67
61
adc_instance = gc_alloc (sizeof (struct adc_module ), false);
62
+ config_adc = gc_alloc (sizeof (struct adc_config ), false);
63
+
64
+ adc_get_config_defaults (config_adc );
68
65
69
- adc_init (adc_instance , ADC , & config_adc );
66
+ config_adc -> reference = ADC_REFERENCE_INTVCC1 ;
67
+ config_adc -> gain_factor = ADC_GAIN_FACTOR_DIV2 ;
68
+ config_adc -> positive_input = self -> pin -> adc_input ;
69
+ config_adc -> resolution = ADC_RESOLUTION_16BIT ;
70
+ config_adc -> clock_prescaler = ADC_CLOCK_PRESCALER_DIV128 ;
71
+
72
+ adc_init (adc_instance , ADC , config_adc );
70
73
}
71
74
72
75
self -> adc_instance = adc_instance ;
76
+ self -> config_adc = config_adc ;
73
77
active_channel_count ++ ;
74
78
}
75
79
@@ -78,9 +82,11 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
78
82
if (active_channel_count == 0 ) {
79
83
adc_reset (adc_instance );
80
84
gc_free (adc_instance );
81
- // Set our reference to NULL so the GC doesn't mistakenly see the
82
- // pointer in memory.
85
+ gc_free (config_adc );
86
+ // Set our references to NULL so the GC doesn't mistakenly see the
87
+ // pointers in memory.
83
88
adc_instance = NULL ;
89
+ config_adc = NULL ;
84
90
}
85
91
reset_pin (self -> pin -> pin );
86
92
}
@@ -94,16 +100,35 @@ void analogin_reset() {
94
100
}
95
101
96
102
uint16_t common_hal_analogio_analogin_get_value (analogio_analogin_obj_t * self ) {
97
- adc_set_positive_input (adc_instance , self -> pin -> adc_input );
103
+ // Something else might have used the ADC in a different way,
104
+ // so we have to completely re-initialize it.
105
+ // ADC must have been disabled before adc_init() is called.
106
+ adc_init (adc_instance , ADC , config_adc );
107
+ config_adc -> positive_input = self -> pin -> adc_input ;
98
108
99
109
adc_enable (adc_instance );
100
- adc_start_conversion (adc_instance );
110
+
111
+ // Read twice and discard first result, as recommended in section 14 of
112
+ // http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
113
+ // "Discard the first conversion result whenever there is a change in ADC configuration
114
+ // like voltage reference / ADC channel change"
115
+ // Empirical observation shows the first reading is quite different than subsequent ones.
101
116
102
117
uint16_t data ;
103
- enum status_code status = adc_read (adc_instance , & data );
104
- while (status == STATUS_BUSY ) {
118
+ enum status_code status ;
119
+
120
+ adc_start_conversion (adc_instance );
121
+ do {
105
122
status = adc_read (adc_instance , & data );
123
+ } while (status == STATUS_BUSY );
124
+ if (status == STATUS_ERR_OVERFLOW ) {
125
+ // TODO(tannewt): Throw an error.
106
126
}
127
+
128
+ adc_start_conversion (adc_instance );
129
+ do {
130
+ status = adc_read (adc_instance , & data );
131
+ } while (status == STATUS_BUSY );
107
132
if (status == STATUS_ERR_OVERFLOW ) {
108
133
// TODO(tannewt): Throw an error.
109
134
}
0 commit comments