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 "k_api.h"
35 #include "py/builtin.h"
36 #include "py/mperrno.h"
37 #include "py/obj.h"
38 #include "py/runtime.h"
39 #include "py/gc.h"
40 #include "py/stackctrl.h"
41
42 #include "ulog/ulog.h"
43 #include "aos/kernel.h"
44
45 #define LOG_TAG "machine_sw_timer"
46
47 #define TIMER_MODE_ONE_SHOT (0)
48 #define TIMER_MODE_PERIODIC (AOS_TIMER_REPEAT)
49 #define TIMER_DEFAULT_PERIOD (1000000U)
50
51 typedef struct _machine_soft_timer_obj_t {
52 mp_obj_base_t base;
53 mp_uint_t port;
54 mp_uint_t period;
55 mp_uint_t reload_mode;
56 void* arg;
57 aos_timer_t timerId;
58 mp_obj_t callback;
59 } machine_soft_timer_obj_t;
60
61 const mp_obj_type_t mp_machine_soft_timer_type;
62
machine_soft_timer_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)63 STATIC void machine_soft_timer_print(const mp_print_t *print, mp_obj_t self_in,
64 mp_print_kind_t kind) {
65 machine_soft_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
66 mp_printf(print, "period=%d, ", self->period);
67 mp_printf(print, "reload_mode=%d, ", self->reload_mode);
68 }
69
machine_soft_timer_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)70 STATIC mp_obj_t machine_soft_timer_make_new(const mp_obj_type_t *type, size_t n_args,
71 size_t n_kw, const mp_obj_t *args) {
72 mp_arg_check_num(n_args, n_kw, 1, 1, false);
73 mp_uint_t port = mp_obj_get_int(args[0]);
74
75 machine_soft_timer_obj_t *swtimer_obj = m_new_obj(machine_soft_timer_obj_t);
76 if (!swtimer_obj) {
77 mp_raise_OSError(ENOMEM);
78 return mp_const_none;
79 }
80 swtimer_obj->base.type = &mp_machine_soft_timer_type;
81 swtimer_obj->port = port;
82 swtimer_obj->timerId = NULL;
83 swtimer_obj->callback = NULL;
84
85 return MP_OBJ_FROM_PTR(swtimer_obj);
86 }
87
machine_soft_timer_enable(machine_soft_timer_obj_t * self)88 STATIC void machine_soft_timer_enable(machine_soft_timer_obj_t *self) {
89 aos_timer_t tim = self->timerId;
90 aos_timer_start(&tim);
91 }
92
machine_soft_timer_disable(machine_soft_timer_obj_t * self)93 STATIC void machine_soft_timer_disable(machine_soft_timer_obj_t *self) {
94 aos_timer_t tim = self->timerId;
95 aos_timer_stop(&tim);
96 }
97
machine_soft_timer_isr(void * timer,void * self_in)98 STATIC void machine_soft_timer_isr(void *timer, void *self_in) {
99 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
100 mp_obj_t callback = self->callback;
101 if (self->callback != mp_const_none) {
102 callback_to_python(self->callback, self);
103 }
104 }
105
machine_soft_timer_init_helper(machine_soft_timer_obj_t * self,mp_uint_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)106 STATIC mp_obj_t machine_soft_timer_init_helper(machine_soft_timer_obj_t *self,
107 mp_uint_t n_args,
108 const mp_obj_t *pos_args,
109 mp_map_t *kw_args) {
110 enum
111 {
112 ARG_index,
113 ARG_mode,
114 ARG_callback,
115 ARG_period,
116 };
117 static const mp_arg_t allowed_args[] = {
118 {MP_QSTR_index, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
119 {MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = AOS_TIMER_REPEAT | AOS_TIMER_AUTORUN}},
120 {MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none}},
121 {MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_DEFAULT_PERIOD}},
122 };
123
124 machine_soft_timer_disable(self);
125
126 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
127 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
128 allowed_args, args);
129
130 if (self == NULL) {
131 LOGD(LOG_TAG, "%s: machine_soft_timer_init_helper failed \n", __func__);
132 return mp_const_none;
133 }
134
135 self->callback = args[ARG_callback].u_obj;
136 self->port = (int8_t)args[ARG_index].u_int;
137 self->reload_mode = args[ARG_mode].u_int;
138 self->period = (uint32_t)args[ARG_period].u_int;
139 self->arg = (void*)self;
140
141 int32_t status = aos_timer_create(&self->timerId,
142 machine_soft_timer_isr,
143 self->arg,
144 self->period,
145 (self->reload_mode | AOS_TIMER_AUTORUN));
146 if (status != 0) {
147 LOGE(LOG_TAG, "%s, %d, aos_timer_create failed\n", __func__, __LINE__);
148 return mp_const_none;
149 }
150
151 return mp_const_none;
152 }
153
machine_soft_timer_deinit(mp_obj_t self_in)154 STATIC mp_obj_t machine_soft_timer_deinit(mp_obj_t self_in) {
155 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
156 machine_soft_timer_disable(self);
157 aos_timer_free(&self->timerId);
158 return mp_const_none;
159 }
160 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_soft_timer_deinit_obj, machine_soft_timer_deinit);
161
machine_soft_timer_init(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)162 STATIC mp_obj_t machine_soft_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
163 return machine_soft_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
164 }
165 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_soft_timer_init_obj, 1, machine_soft_timer_init);
166
machine_soft_timer_period(mp_obj_t self_in,mp_obj_t period)167 STATIC mp_obj_t machine_soft_timer_period(mp_obj_t self_in, mp_obj_t period) {
168 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
169 if(self_in == NULL) {
170 mp_raise_OSError(ENOENT);
171 return mp_const_none;
172 } else {
173 self->period = mp_obj_get_int(period);
174 }
175
176 int32_t ret = aos_timer_change(&self->timerId, self->period);
177 return MP_OBJ_NEW_SMALL_INT(ret);
178 }
179 STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_soft_timer_period_obj, machine_soft_timer_period);
180
machine_soft_timer_start(mp_obj_t self_in)181 STATIC mp_obj_t machine_soft_timer_start(mp_obj_t self_in) {
182 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
183 int32_t ret = aos_timer_start(&self->timerId);
184 return MP_OBJ_NEW_SMALL_INT(ret);
185 }
186 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_soft_timer_start_obj, machine_soft_timer_start);
187
machine_soft_timer_stop(mp_obj_t self_in)188 STATIC mp_obj_t machine_soft_timer_stop(mp_obj_t self_in) {
189 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
190 aos_timer_stop(&self->timerId);
191 return mp_const_none;
192 }
193 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_soft_timer_stop_obj, machine_soft_timer_stop);
194
machine_soft_timer_value(mp_obj_t self_in)195 STATIC mp_obj_t machine_soft_timer_value(mp_obj_t self_in) {
196 machine_soft_timer_obj_t *self = (machine_soft_timer_obj_t *)MP_OBJ_TO_PTR(self_in);
197
198 uint64_t time_ns[4] = {0};
199 aos_timer_gettime(&self->timerId, time_ns);
200
201 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(time_ns[0] * 1000 + time_ns[1] / 10000000)); // value in ms
202 }
203 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_soft_timer_value_obj, machine_soft_timer_value);
204
205 STATIC const mp_rom_map_elem_t machine_soft_timer_locals_dict_table[] = {
206 {MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_soft_timer_deinit_obj)},
207 {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_soft_timer_init_obj)},
208 {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_soft_timer_deinit_obj)},
209 {MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_soft_timer_start_obj)},
210 {MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_soft_timer_stop_obj)},
211 {MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&machine_soft_timer_period_obj)},
212 {MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_soft_timer_value_obj)},
213
214 {MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONE_SHOT)},
215 {MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC)},
216 };
217 STATIC MP_DEFINE_CONST_DICT(machine_soft_timer_locals_dict, machine_soft_timer_locals_dict_table);
218
219 const mp_obj_type_t mp_machine_soft_timer_type = {
220 {&mp_type_type},
221 .name = MP_QSTR_SoftTimer,
222 .print = machine_soft_timer_print,
223 .make_new = machine_soft_timer_make_new,
224 .locals_dict = (mp_obj_t)&machine_soft_timer_locals_dict,
225 };
226