Skip to content

Commit 259ae8a

Browse files
committed
atmel-samd: Initial ADC support.
1 parent 3cb4938 commit 259ae8a

File tree

13 files changed

+3691
-55
lines changed

13 files changed

+3691
-55
lines changed

atmel-samd/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ INC += $(addprefix -Iasf/sam0/,\
4747
drivers/extint/ \
4848
drivers/port \
4949
drivers/system \
50+
drivers/adc/adc_sam_d_r \
5051
drivers/system/clock \
5152
drivers/system/clock/clock_samd21_r21_da \
5253
drivers/system/interrupt \
@@ -97,6 +98,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
9798
drivers/sercom/sercom_interrupt.c \
9899
drivers/sercom/usart/usart.c \
99100
drivers/sercom/usart/usart_interrupt.c \
101+
drivers/adc/adc_sam_d_r/adc.c \
100102
drivers/system/clock/clock_samd21_r21_da/clock.c \
101103
drivers/system/clock/clock_samd21_r21_da/gclk.c \
102104
drivers/system/interrupt/system_interrupt.c \
@@ -108,6 +110,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
108110
)
109111

110112
SRC_C = \
113+
adc.c \
111114
main.c \
112115
modmachine.c \
113116
modutime.c \

atmel-samd/adc.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdio.h>
28+
#include <string.h>
29+
30+
#include "py/nlr.h"
31+
#include "py/runtime.h"
32+
#include "py/binary.h"
33+
#include "py/mphal.h"
34+
#include "adc.h"
35+
#include "pin.h"
36+
37+
#include "asf/sam0/drivers/adc/adc.h"
38+
39+
/// \moduleref machine
40+
/// \class ADC - analog to digital conversion: read analog values on a pin
41+
///
42+
/// Usage:
43+
///
44+
/// adc = machine.ADC(pin) # create an analog object from a pin
45+
/// val = adc.read() # read an analog value
46+
47+
typedef struct {
48+
mp_obj_base_t base;
49+
pin_obj_t * pin;
50+
struct adc_module adc_instance;
51+
} adc_obj_t;
52+
53+
/******************************************************************************/
54+
/* Micro Python bindings : adc object (single channel) */
55+
56+
STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
57+
adc_obj_t *self = self_in;
58+
mp_print_str(print, "<ADC on ");
59+
mp_obj_print_helper(print, self->pin, PRINT_STR);
60+
}
61+
62+
63+
STATIC void adc_init_single(adc_obj_t *adc_obj) {
64+
struct adc_config config_adc;
65+
adc_get_config_defaults(&config_adc);
66+
67+
config_adc.positive_input = adc_obj->pin->adc_input;
68+
config_adc.resolution = ADC_RESOLUTION_CUSTOM;
69+
config_adc.accumulate_samples = ADC_ACCUMULATE_SAMPLES_16;
70+
config_adc.divide_result = ADC_DIVIDE_RESULT_16;
71+
config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128;
72+
73+
adc_init(&adc_obj->adc_instance, ADC, &config_adc);
74+
}
75+
76+
/// \classmethod \constructor(pin)
77+
/// Create an ADC object associated with the given pin.
78+
/// This allows you to then read analog values on that pin.
79+
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
80+
// check number of arguments
81+
mp_arg_check_num(n_args, n_kw, 1, 1, false);
82+
83+
// 1st argument is the pin name
84+
mp_obj_t pin_obj = args[0];
85+
86+
const pin_obj_t *pin = pin_find(pin_obj);
87+
if (!pin->has_adc) {
88+
// No ADC function on that pin
89+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have ADC capabilities", pin->name));
90+
}
91+
92+
adc_obj_t *o = m_new_obj(adc_obj_t);
93+
memset(o, 0, sizeof(*o));
94+
o->base.type = &adc_type;
95+
o->pin = pin_obj;
96+
adc_init_single(o);
97+
98+
return o;
99+
}
100+
101+
/// \method read()
102+
/// Read the value on the analog pin and return it. The returned value
103+
/// will be between 0 and 4095.
104+
// TODO(tannewt): Don't turn it all on just for one read. This simplifies
105+
// handling of reading multiple inputs and surviving sleep though so for now its
106+
// ok.
107+
STATIC mp_obj_t mp_adc_read(mp_obj_t self_in) {
108+
adc_obj_t *self = self_in;
109+
110+
adc_enable(&self->adc_instance);
111+
adc_start_conversion(&self->adc_instance);
112+
113+
uint16_t data;
114+
enum status_code status = adc_read(&self->adc_instance, &data);
115+
while (status == STATUS_BUSY) {
116+
status = adc_read(&self->adc_instance, &data);
117+
}
118+
if (status == STATUS_ERR_OVERFLOW) {
119+
// TODO(tannewt): Throw an error.
120+
}
121+
122+
adc_disable(&self->adc_instance);
123+
return mp_obj_new_int(data);
124+
}
125+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, mp_adc_read);
126+
127+
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
128+
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj},
129+
};
130+
131+
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
132+
133+
const mp_obj_type_t adc_type = {
134+
{ &mp_type_type },
135+
.name = MP_QSTR_ADC,
136+
.print = adc_print,
137+
.make_new = adc_make_new,
138+
.locals_dict = (mp_obj_t)&adc_locals_dict,
139+
};

atmel-samd/adc.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
extern const mp_obj_type_t adc_type;

0 commit comments

Comments
 (0)