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