1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2017 Nick Moore
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 
28 #include <stdio.h>
29 
30 #include "py/runtime.h"
31 #include "py/mphal.h"
32 #include "modmachine.h"
33 
34 #include "ulog/ulog.h"
35 #include "aos_hal_adc.h"
36 
37 #define LOG_TAG "machine_adc"
38 
39 #define SAMPLEING_CYCLE  1200
40 
41 enum {
42     ADC_CHANNEL_0,
43     ADC_CHANNEL_1,
44     ADC_CHANNEL_MAX
45 };
46 
47 enum {
48     ADC_WIDTH_9Bit,
49     ADC_WIDTH_10Bit,
50     ADC_WIDTH_11Bit,
51     ADC_WIDTH_12Bit,
52     ADC_WIDTH_13Bit,
53 };
54 
55 typedef struct _madc_obj_t {
56     mp_obj_base_t base;
57     adc_dev_t dev;
58     uint8_t adc_bit_width;
59     uint8_t channel_id;
60 } madc_obj_t;
61 
62 const mp_obj_type_t machine_adc_type;
63 
64 STATIC madc_obj_t madc_obj[] = {
65     {{&machine_adc_type}, {ADC_CHANNEL_0, { SAMPLEING_CYCLE }, NULL}, ADC_WIDTH_12Bit, ADC_CHANNEL_0},
66     {{&machine_adc_type}, {ADC_CHANNEL_1, { SAMPLEING_CYCLE }, NULL}, ADC_WIDTH_12Bit, ADC_CHANNEL_1},
67 };
68 
madc_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)69 STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
70     mp_arg_check_num(n_args, n_kw, 1, 1, true);
71 
72     int32_t channel_id = mp_obj_get_int(args[0]);
73     madc_obj_t *self = NULL;
74     for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) {
75         if (channel_id == madc_obj[i].channel_id) {
76             self = &madc_obj[i];
77             break;
78         }
79     }
80     if (!self) {
81         mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("ChannelId[%d] Should Smaller Than %d"), channel_id, ADC_CHANNEL_MAX);
82     }
83 
84     int status = aos_hal_adc_init(&self->dev);
85     if(status != 0) {
86       mp_raise_ValueError(MP_ERROR_TEXT("Failed to init ADC, parameter error"));
87     }
88 
89     return MP_OBJ_FROM_PTR(self);
90 }
91 
madc_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)92 STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
93     madc_obj_t *self = MP_OBJ_TO_PTR(self_in);
94     mp_printf(print, "ADC(Channel(%u))", self->channel_id);
95 }
96 
97 // read_u16()
madc_read_u16(mp_obj_t self_in)98 STATIC mp_obj_t madc_read_u16(mp_obj_t self_in) {
99     madc_obj_t *self = MP_OBJ_TO_PTR(self_in);
100     uint32_t output = 0;
101     int status = aos_hal_adc_value_get(&self->dev, &output, 0);
102     if (status != 0) {
103         LOGE(LOG_TAG, "ADC read fail with status=%d\n", status);
104     }
105     return MP_OBJ_NEW_SMALL_INT(output);
106 }
107 STATIC MP_DEFINE_CONST_FUN_OBJ_1(madc_read_u16_obj, madc_read_u16);
108 
109 // Legacy method
madc_read(mp_obj_t self_in)110 STATIC mp_obj_t madc_read(mp_obj_t self_in) {
111     return madc_read_u16(self_in);
112 }
113 MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read);
114 
madc_atten(mp_obj_t self_in,mp_obj_t atten_in)115 STATIC mp_obj_t madc_atten(mp_obj_t self_in, mp_obj_t atten_in) {
116     madc_obj_t *self = MP_OBJ_TO_PTR(self_in);
117     int32_t atten = mp_obj_get_int(atten_in);
118 
119     mp_raise_NotImplementedError(MP_ERROR_TEXT("attenuation not supported"));
120 }
121 MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten);
122 
madc_width(mp_obj_t self_in,mp_obj_t width_in)123 STATIC mp_obj_t madc_width(mp_obj_t self_in, mp_obj_t width_in) {
124     madc_obj_t *self = MP_OBJ_TO_PTR(self_in);
125     uint8_t width = mp_obj_get_int(width_in);
126     switch (width) {
127         case ADC_WIDTH_9Bit:
128             self->adc_bit_width = 9;
129             break;
130         case ADC_WIDTH_10Bit:
131             self->adc_bit_width = 10;
132             break;
133         case ADC_WIDTH_11Bit:
134             self->adc_bit_width = 11;
135             break;
136         case ADC_WIDTH_12Bit:
137             self->adc_bit_width = 12;
138             break;
139         case ADC_WIDTH_13Bit:
140             self->adc_bit_width = 13;
141             break;
142         default:
143             break;
144     }
145     return mp_const_none;
146 }
147 MP_DEFINE_CONST_FUN_OBJ_2(madc_width_obj, madc_width);
148 
149 STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = {
150     { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&madc_read_u16_obj) },
151     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) },
152     { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) },
153     { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) },
154 
155     { MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) },
156     { MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) },
157     { MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) },
158     { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) },
159     { MP_ROM_QSTR(MP_QSTR_WIDTH_13BIT), MP_ROM_INT(ADC_WIDTH_13Bit) },
160 };
161 
162 STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table);
163 
164 const mp_obj_type_t machine_adc_type = {
165     { &mp_type_type },
166     .name = MP_QSTR_ADC,
167     .print = madc_print,
168     .make_new = madc_make_new,
169     .locals_dict = (mp_obj_t)&madc_locals_dict,
170 };
171