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