1 /*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * Development of the code in this file was sponsored by Microbric Pty Ltd
5 *
6 * The MIT License (MIT)
7 *
8 * Copyright (c) 2013-2015 Damien P. George
9 * Copyright (c) 2016 Paul Sokolovsky
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "ulog/ulog.h"
35
36 #include "py/builtin.h"
37 #include "py/mperrno.h"
38 #include "py/obj.h"
39 #include "py/runtime.h"
40 #include "py/gc.h"
41 #include "py/stackctrl.h"
42
43 #include "utility.h"
44 #include "ulog/ulog.h"
45 #include "aos_hal_timer.h"
46
47 #define LOG_TAG "machine_timer"
48
49 #define TIMER_MODE_ONE_SHOT (TIMER_RELOAD_MANU)
50 #define TIMER_MODE_PERIODIC (TIMER_RELOAD_AUTO)
51 #define TIMER_DEFAULT_PERIOD (1000000U)
52 typedef struct _machine_timer_obj_t {
53 mp_obj_base_t base;
54 mp_uint_t port;
55 timer_dev_t *device;
56 mp_obj_t callback;
57 } machine_timer_obj_t;
58
59 const mp_obj_type_t machine_timer_type;
60
61 STATIC void machine_timer_disable(machine_timer_obj_t *self);
62
machine_timer_get_devive(machine_timer_obj_t * self)63 STATIC timer_dev_t *machine_timer_get_devive(machine_timer_obj_t *self) {
64 if (self == NULL) {
65 LOGE(LOG_TAG, "machine_timer_obj is NULL\n");
66 return NULL;
67 }
68
69 if(self->device != NULL) {
70 return self->device;
71 } else {
72 timer_dev_t *device = aos_calloc(1, sizeof(timer_dev_t));
73 if (NULL == device) {
74 LOGE(LOG_TAG, "%s: timer_dev_t calloc failed;\n", __func__);
75 goto fail;
76 }
77 device->port = self->port;
78 self->device = device;
79 }
80
81 return self->device;
82
83 fail:
84 self->device = NULL;
85 return NULL;
86 }
87
machine_timer_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)88 STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in,
89 mp_print_kind_t kind) {
90 machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
91 mp_printf(print, "period=%d, ", self->device->config.period);
92 mp_printf(print, "reload_mode=%d, ", self->device->config.reload_mode);
93 }
94
machine_timer_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)95 STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
96 size_t n_kw, const mp_obj_t *args) {
97 mp_arg_check_num(n_args, n_kw, 1, 1, false);
98 mp_uint_t port = mp_obj_get_int(args[0]);
99
100 machine_timer_obj_t *machine_obj = m_new_obj(machine_timer_obj_t);
101 if (!machine_obj) {
102 mp_raise_OSError(ENOMEM);
103 return mp_const_none;
104 }
105 machine_obj->base.type = &machine_timer_type;
106 machine_obj->port = port;
107 machine_obj->device = NULL;
108
109 return MP_OBJ_FROM_PTR(machine_obj);
110 }
111
machine_timer_disable(machine_timer_obj_t * self)112 STATIC void machine_timer_disable(machine_timer_obj_t *self) {
113 timer_dev_t *tim = machine_timer_get_devive(self);
114 aos_hal_timer_stop(tim);
115 }
116
machine_timer_isr(void * self_in)117 STATIC void machine_timer_isr(void *self_in) {
118 machine_timer_obj_t *self = (machine_timer_obj_t*)self_in;
119 mp_obj_t callback = self->callback;
120 if (self->callback != mp_const_none) {
121 callback_to_python(self->callback, self);
122 }
123 }
124
machine_timer_enable(machine_timer_obj_t * self)125 STATIC void machine_timer_enable(machine_timer_obj_t *self) {
126 timer_dev_t *tim = machine_timer_get_devive(self);
127 if(tim != NULL) {
128 aos_hal_timer_init(tim);
129 aos_hal_timer_start(tim);
130 }
131 }
132
machine_timer_init_helper(machine_timer_obj_t * self,mp_uint_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)133 STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self,
134 mp_uint_t n_args,
135 const mp_obj_t *pos_args,
136 mp_map_t *kw_args) {
137 enum
138 {
139 ARG_index,
140 ARG_mode,
141 ARG_callback,
142 ARG_period,
143 };
144 static const mp_arg_t allowed_args[] = {
145 {MP_QSTR_index, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
146 {MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC}},
147 {MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none}},
148 {MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_DEFAULT_PERIOD}},
149 };
150
151 machine_timer_disable(self);
152
153 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
154 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
155 allowed_args, args);
156
157 if (self == NULL || self->device == NULL) {
158 LOGE(LOG_TAG, "%s: hal_timer_init failed\n", __func__);
159 return mp_const_none;
160 }
161
162 self->callback = args[ARG_callback].u_obj;
163 self->device->port = (int8_t)args[ARG_index].u_int;
164 self->device->config.reload_mode = args[ARG_mode].u_int;
165 self->device->config.period = (uint32_t)args[ARG_period].u_int * 1000UL;
166 self->device->config.arg = self;
167 self->device->config.cb = machine_timer_isr;
168
169 machine_timer_enable(self);
170 return mp_const_none;
171 }
172
machine_timer_deinit(mp_obj_t self_in)173 STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
174 machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
175 machine_timer_disable(self);
176 timer_dev_t *tim = machine_timer_get_devive(self);
177 if(tim != NULL) {
178 aos_free(tim);
179 self->device = NULL;
180 }
181 aos_hal_timer_stop(tim);
182 return mp_const_none;
183 }
184 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
185
machine_timer_init(mp_uint_t n_args,const mp_obj_t * args,mp_map_t * kw_args)186 STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args,
187 mp_map_t *kw_args) {
188 return machine_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
189 }
190 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
191
machine_timer_period(mp_obj_t self_in,mp_const_obj_t period)192 STATIC mp_obj_t machine_timer_period(mp_obj_t self_in, mp_const_obj_t period)
193 {
194 machine_timer_obj_t *self = self_in;
195 if(self_in == NULL) {
196 mp_raise_OSError(ENOENT);
197 return mp_const_none;
198 } else {
199 self->device->config.period = mp_obj_get_int(period);
200 }
201 timer_config_t para = self->device->config;
202
203 timer_dev_t *tim = machine_timer_get_devive(self);
204 int32_t ret = aos_hal_timer_para_chg(tim, para);
205 return MP_OBJ_NEW_SMALL_INT(ret);
206 }
207 STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_timer_period_obj, machine_timer_period);
208
machine_timer_start(mp_obj_t self_in)209 STATIC mp_obj_t machine_timer_start(mp_obj_t self_in) {
210 machine_timer_obj_t *self = self_in;
211 timer_dev_t *tim = machine_timer_get_devive(self);
212 int32_t ret = aos_hal_timer_start(tim);
213 return MP_OBJ_NEW_SMALL_INT(ret);
214 }
215 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_start_obj, machine_timer_start);
216
machine_timer_stop(mp_obj_t self_in)217 STATIC mp_obj_t machine_timer_stop(mp_obj_t self_in) {
218 machine_timer_obj_t *self = self_in;
219 timer_dev_t *tim = machine_timer_get_devive(self);
220 aos_hal_timer_stop(tim);
221 return mp_const_none;
222 }
223 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop);
224
machine_timer_value(mp_obj_t self_in)225 STATIC mp_obj_t machine_timer_value(mp_obj_t self_in) {
226 machine_timer_obj_t *self = self_in;
227 double result = 1.0;
228
229 LOGI(LOG_TAG, "hardware timer doesn't support value get, default to 1s");
230
231 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result * 1000)); // value in ms
232 }
233 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value);
234
235 STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
236 {MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj)},
237 {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj)},
238 {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj)},
239 {MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_start_obj)},
240 {MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj)},
241 {MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&machine_timer_period_obj)},
242 {MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_timer_value_obj)},
243
244 {MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONE_SHOT)},
245 {MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC)},
246 };
247 STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
248
249 const mp_obj_type_t machine_timer_type = {
250 {&mp_type_type},
251 .name = MP_QSTR_Timer,
252 .print = machine_timer_print,
253 .make_new = machine_timer_make_new,
254 .locals_dict = (mp_obj_t)&machine_timer_locals_dict,
255 };
256