1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "aos_hal_gpio.h"
6 #include "board_mgr.h"
7 #include "py/builtin.h"
8 #include "py/gc.h"
9 #include "py/mperrno.h"
10 #include "py/obj.h"
11 #include "py/runtime.h"
12 #include "py/stackctrl.h"
13 #include "ulog/ulog.h"
14 
15 #define LOG_TAG "DRIVER_GPIO"
16 
17 extern const mp_obj_type_t driver_gpio_type;
18 
19 typedef enum {
20     IRQ_RISING_EDGE  = 0x1, /**< Interrupt triggered at input signal's rising edge  */
21     IRQ_FALLING_EDGE = 0x2, /**< Interrupt triggered at input signal's falling edge */
22     IRQ_BOTH_EDGES   = IRQ_RISING_EDGE | IRQ_FALLING_EDGE,
23 } gpio_irq_trigger_params_t;
24 
25 // this is the actual C-structure for our new object
26 typedef struct {
27     // base represents some basic information, like type
28     mp_obj_base_t Base;
29     // a member created by us
30     char *ModuleName;
31     item_handle_t gpio_handle;
32     gpio_dev_t *gpio_device;
33     mp_obj_t callback;
34 } mp_gpio_obj_t;
35 
gpio_driver_irq_handler(int polarity,void * arg)36 void gpio_driver_irq_handler(int polarity, void *arg)
37 {
38     mp_gpio_obj_t *self = (mp_gpio_obj_t *)arg;
39     if (self->callback != mp_const_none) {
40         callback_to_python(self->callback, self);
41     }
42 }
43 
gpio_obj_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)44 void gpio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
45 {
46     mp_gpio_obj_t *self = MP_OBJ_TO_PTR(self_in);
47     mp_printf(print, "ModuleName(%s)", self->ModuleName);
48 }
49 
gpio_obj_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)50 STATIC mp_obj_t gpio_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
51 {
52     mp_gpio_obj_t *driver_obj = m_new_obj(mp_gpio_obj_t);
53     if (!driver_obj) {
54         LOGE(LOG_TAG, "%s: alloc mem failed;\n", __func__);
55         mp_raise_OSError(ENOMEM);
56     }
57 
58     driver_obj->Base.type = &driver_gpio_type;
59     driver_obj->ModuleName = "gpio";
60     driver_obj->gpio_handle.handle = NULL;
61     driver_obj->gpio_device = NULL;
62 
63     return MP_OBJ_FROM_PTR(driver_obj);
64 }
65 
obj_open(size_t n_args,const mp_obj_t * args)66 STATIC mp_obj_t obj_open(size_t n_args, const mp_obj_t *args)
67 {
68     if (n_args != 2) {
69         LOGE(LOG_TAG, "%s: illegal args;\n", __func__);
70         mp_raise_OSError(EINVAL);
71     }
72     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
73     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
74     if (driver_obj == NULL) {
75         LOGE(LOG_TAG, "driver_obj is NULL\n");
76         mp_raise_OSError(EINVAL);
77     }
78 
79     if (driver_obj->gpio_device != NULL) {
80         LOGE(LOG_TAG, "device hass opened\n");
81         return MP_ROM_INT(-ENXIO);
82     }
83 
84     int ret = -1;
85     gpio_dev_t *gpio_device = NULL;
86     char *id = (char *)mp_obj_str_get_str(args[1]);
87 
88     if (id == NULL) {
89         LOGE(LOG_TAG, "%s:illegal par id =%s;\n", __func__, id);
90         mp_raise_OSError(EINVAL);
91     }
92 
93     if (py_board_mgr_init() != 0) {
94         LOGE(LOG_TAG, "%s:py_board_mgr_init failed\n", __func__);
95         mp_raise_OSError(EINVAL);
96     }
97 
98     if (py_board_attach_item(MODULE_GPIO, id, &(driver_obj->gpio_handle)) != 0) {
99         LOGE(LOG_TAG, "%s: py_board_attach_item failed ret = %d;\n", __func__, ret);
100         py_board_disattach_item(MODULE_GPIO, &(driver_obj->gpio_handle));
101         mp_raise_OSError(EINVAL);
102     }
103 
104     gpio_device = py_board_get_node_by_handle(MODULE_GPIO, &(driver_obj->gpio_handle));
105     if (NULL == gpio_device) {
106         LOGE(LOG_TAG, "%s: py_board_get_node_by_handle failed;\n", __func__);
107         py_board_disattach_item(MODULE_GPIO, &(driver_obj->gpio_handle));
108         gpio_device = NULL;
109         mp_raise_OSError(EINVAL);
110     }
111     driver_obj->gpio_device = gpio_device;
112 
113 
114     ret = aos_hal_gpio_init(gpio_device);
115     if (ret) {
116         mp_raise_OSError(ret);
117     }
118 
119     return MP_ROM_INT(0);
120 }
121 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(gpio_obj_open, 2, obj_open);
122 
obj_close(size_t n_args,const mp_obj_t * args)123 STATIC mp_obj_t obj_close(size_t n_args, const mp_obj_t *args)
124 {
125     int ret = -1;
126     if (n_args < 1) {
127         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
128         return MP_ROM_INT(-EINVAL);
129     }
130     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
131     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
132     if (driver_obj == NULL) {
133         LOGE(LOG_TAG, "driver_obj is NULL\n");
134         return MP_ROM_INT(-EINVAL);
135     }
136     if (NULL == driver_obj->gpio_device) {
137         LOGE(LOG_TAG, "driver_obj has closed\n");
138         return MP_ROM_INT(-ENXIO);
139     }
140 
141     ret = aos_hal_gpio_finalize(driver_obj->gpio_device);
142     if (ret != 0) {
143         LOGE(LOG_TAG, "%s: aos_hal_gpio_finalize failed;\n", __func__);
144         return MP_ROM_INT(-EINVAL);
145     }
146     py_board_disattach_item(MODULE_GPIO, &(driver_obj->gpio_handle));
147     driver_obj->gpio_device = NULL;
148     return MP_ROM_INT(0);
149 }
150 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(gpio_obj_close, 1, obj_close);
151 
obj_read(size_t n_args,const mp_obj_t * args)152 STATIC mp_obj_t obj_read(size_t n_args, const mp_obj_t *args)
153 {
154     int ret = -1;
155     uint32_t level = 0;
156     if (n_args < 1) {
157         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
158         return MP_ROM_INT(-EINVAL);
159     }
160     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
161     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
162     if (NULL == driver_obj) {
163         LOGE(LOG_TAG, "driver_obj is NULL\n");
164         return MP_ROM_INT(-EINVAL);
165     }
166     if (NULL == driver_obj->gpio_device) {
167         LOGE(LOG_TAG, "driver_obj has closed\n");
168         return MP_ROM_INT(-ENXIO);
169     }
170 
171     level = aos_hal_gpio_get(driver_obj->gpio_device);
172 
173     return MP_ROM_INT(level);
174 }
175 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(gpio_obj_read, 1, obj_read);
176 
obj_write(size_t n_args,const mp_obj_t * args)177 STATIC mp_obj_t obj_write(size_t n_args, const mp_obj_t *args)
178 {
179     int ret = -1;
180     uint32_t level = 0;
181     if (n_args < 2) {
182         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
183         return MP_ROM_INT(-EINVAL);
184     }
185     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
186     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
187     if (NULL == driver_obj) {
188         LOGE(LOG_TAG, "driver_obj is NULL\n");
189         return MP_ROM_INT(-EINVAL);
190     }
191     if (NULL == driver_obj->gpio_device) {
192         LOGE(LOG_TAG, "driver_obj has closed\n");
193         return MP_ROM_INT(-ENXIO);
194     }
195 
196     level = (uint32_t)mp_obj_get_int(args[1]);
197 
198     if (level) {
199         ret = aos_hal_gpio_output_high(driver_obj->gpio_device);
200     } else {
201         ret = aos_hal_gpio_output_low(driver_obj->gpio_device);
202     }
203 
204     return MP_ROM_INT(ret);
205 }
206 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(gpio_obj_write, 2, obj_write);
207 
obj_toggle(size_t n_args,const mp_obj_t * args)208 STATIC mp_obj_t obj_toggle(size_t n_args, const mp_obj_t *args)
209 {
210     int ret = -1;
211     if (n_args < 1) {
212         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
213         return MP_ROM_INT(-EINVAL);
214     }
215     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
216     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
217     if (driver_obj == NULL) {
218         LOGE(LOG_TAG, "driver_obj is NULL\n");
219         return MP_ROM_INT(-EINVAL);
220     }
221 
222     ret = aos_hal_gpio_output_toggle(driver_obj->gpio_device);
223     if (ret == -1) {
224         LOGE(LOG_TAG, "aos_hal_gpio_output_toggle failed\n");
225     }
226 
227     return MP_ROM_INT(ret);
228 }
229 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(gpio_obj_toggle, 1, obj_toggle);
230 
obj_on(size_t n_args,const mp_obj_t * args)231 STATIC mp_obj_t obj_on(size_t n_args, const mp_obj_t *args)
232 {
233     int ret = -1;
234     uint32_t irq_edge = 0;
235     if (n_args < 2 || args[1] == mp_const_none) {
236         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
237         return MP_ROM_INT(-EINVAL);
238     }
239     mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
240     mp_gpio_obj_t *driver_obj = (mp_gpio_obj_t *)self;
241     if (driver_obj == NULL) {
242         LOGE(LOG_TAG, "driver_obj is NULL\n");
243         return MP_ROM_INT(-EINVAL);
244     }
245     if (driver_obj->gpio_device == NULL) {
246         LOGE(LOG_TAG, "driver_obj has closed\n");
247         return MP_ROM_INT(-ENXIO);
248     }
249 
250     driver_obj->callback = args[1];
251 
252     // judge callback function if callback == None disable IQR
253     // ret = aos_hal_gpio_clear_irq(driver_obj->gpio_device);
254     gpio_params_t *priv = (gpio_params_t *)driver_obj->gpio_device->priv;
255 
256     driver_obj->callback = args[1];
257     if (n_args == 3) {
258         irq_edge = (uint32_t)mp_obj_get_int(args[2]);
259     } else {
260         irq_edge = priv->irq_mode;
261     }
262 
263     ret = aos_hal_gpio_enable_irq(driver_obj->gpio_device, (int8_t)irq_edge, gpio_driver_irq_handler, (void *)driver_obj);
264     if (ret < 0) {
265         LOGE(LOG_TAG, "%s:aos_hal_gpio_enable_irq failed, %d\n", __func__, ret);
266     }
267 
268     return MP_ROM_INT(ret);
269 }
270 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gpio_on_obj, 2, 3, obj_on);
271 
272 
273 STATIC const mp_rom_map_elem_t gpio_locals_dict_table[] = {
274     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_GPIO) },
275     { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&gpio_obj_open) },
276     { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gpio_obj_close) },
277     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&gpio_obj_read) },
278     { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&gpio_obj_write) },
279     { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&gpio_on_obj) },
280     { MP_ROM_QSTR(MP_QSTR_RisingEdge), MP_ROM_INT(IRQ_RISING_EDGE) },
281     { MP_ROM_QSTR(MP_QSTR_FallingEdge), MP_ROM_INT(IRQ_FALLING_EDGE) },
282 };
283 
284 STATIC MP_DEFINE_CONST_DICT(gpio_locals_dict, gpio_locals_dict_table);
285 
286 const mp_obj_type_t driver_gpio_type = {
287     .base = { &mp_type_type },
288     .name = MP_QSTR_GPIO,
289     .print = gpio_obj_print,
290     .make_new = gpio_obj_make_new,
291     .locals_dict = (mp_obj_dict_t *)&gpio_locals_dict,
292 };
293