blob: c26c633967659fbe5248f88133a5eead4c1a8e46 [file] [log] [blame]
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +02001/*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013-2015 Damien P. George
Paul Sokolovsky71930862016-01-05 21:23:23 +02007 * Copyright (c) 2016 Paul Sokolovsky
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +02008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#include <stdint.h>
Paul Sokolovsky31ad1bb2016-08-07 16:20:01 +030029#include <stdio.h>
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +020030
31#include "py/obj.h"
Paul Sokolovsky71930862016-01-05 21:23:23 +020032#include "py/runtime.h"
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +020033#include "extmod/machine_mem.h"
Paul Sokolovsky287180a2017-01-01 19:17:00 +030034#include "extmod/machine_signal.h"
Damien Georgecff2b7a2016-05-31 14:06:50 +010035#include "extmod/machine_pulse.h"
Damien Georgea5254932016-04-12 13:55:20 +010036#include "extmod/machine_i2c.h"
Paul Sokolovsky8bc3fc22016-11-06 01:30:19 +030037#include "modmachine.h"
Paul Sokolovsky71930862016-01-05 21:23:23 +020038
Damien George9a368ae2016-05-20 13:30:33 +010039#include "xtirq.h"
Paul Sokolovsky71930862016-01-05 21:23:23 +020040#include "os_type.h"
41#include "osapi.h"
Paul Sokolovsky98b727c2016-02-06 01:36:17 +020042#include "etshal.h"
Damien George32d7cf62016-04-21 11:43:37 +010043#include "ets_alt_task.h"
Damien Georgef7be8032016-02-17 15:19:03 +000044#include "user_interface.h"
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +020045
46#if MICROPY_PY_MACHINE
47
Damien George32d7cf62016-04-21 11:43:37 +010048//#define MACHINE_WAKE_IDLE (0x01)
49//#define MACHINE_WAKE_SLEEP (0x02)
50#define MACHINE_WAKE_DEEPSLEEP (0x04)
51
Paul Sokolovsky263aaa72016-08-28 14:48:49 +030052extern const mp_obj_type_t esp_wdt_type;
53
Damien Georgef7be8032016-02-17 15:19:03 +000054STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
55 if (n_args == 0) {
56 // get
57 return mp_obj_new_int(system_get_cpu_freq() * 1000000);
58 } else {
59 // set
60 mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
61 if (freq != 80 && freq != 160) {
62 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
63 "frequency can only be either 80Mhz or 160MHz"));
64 }
65 system_update_cpu_freq(freq);
66 return mp_const_none;
67 }
68}
69STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
70
Paul Sokolovsky81fd5682016-04-05 00:20:25 +030071STATIC mp_obj_t machine_reset(void) {
72 system_restart();
73 return mp_const_none;
74}
75STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
76
Paul Sokolovsky050e6452016-04-15 22:07:28 +030077STATIC mp_obj_t machine_reset_cause(void) {
78 return MP_OBJ_NEW_SMALL_INT(system_get_rst_info()->reason);
79}
80STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
81
Paul Sokolovskyde125022016-04-05 00:57:49 +030082STATIC mp_obj_t machine_unique_id(void) {
83 uint32_t id = system_get_chip_id();
84 return mp_obj_new_bytes((byte*)&id, sizeof(id));
85}
86STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
87
Paul Sokolovskyc2070d72016-08-07 15:51:04 +030088STATIC mp_obj_t machine_idle(void) {
Paul Sokolovsky52784bf2016-10-04 21:20:47 +030089 uint32_t t = mp_hal_ticks_cpu();
Paul Sokolovskyc2070d72016-08-07 15:51:04 +030090 asm("waiti 0");
Paul Sokolovsky52784bf2016-10-04 21:20:47 +030091 t = mp_hal_ticks_cpu() - t;
92 return MP_OBJ_NEW_SMALL_INT(t);
Paul Sokolovskyc2070d72016-08-07 15:51:04 +030093}
94STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
95
Paul Sokolovsky31ad1bb2016-08-07 16:20:01 +030096STATIC mp_obj_t machine_sleep(void) {
97 printf("Warning: not yet implemented\n");
98 return mp_const_none;
99}
100STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
101
Damien George32d7cf62016-04-21 11:43:37 +0100102STATIC mp_obj_t machine_deepsleep(void) {
103 // default to sleep forever
104 uint32_t sleep_us = 0;
105
106 // see if RTC.ALARM0 should wake the device
107 if (pyb_rtc_alarm0_wake & MACHINE_WAKE_DEEPSLEEP) {
108 uint64_t t = pyb_rtc_get_us_since_2000();
109 if (pyb_rtc_alarm0_expiry <= t) {
110 sleep_us = 1; // alarm already expired so wake immediately
111 } else {
112 uint64_t delta = pyb_rtc_alarm0_expiry - t;
113 if (delta <= 0xffffffff) {
114 // sleep for the desired time
115 sleep_us = delta;
116 } else {
117 // overflow, just set to maximum sleep time
118 sleep_us = 0xffffffff;
119 }
120 }
121 }
122
puuuee125812016-06-04 00:21:26 +0900123 // prepare for RTC reset at wake up
124 rtc_prepare_deepsleep(sleep_us);
Damien George32d7cf62016-04-21 11:43:37 +0100125 // put the device in a deep-sleep state
126 system_deep_sleep_set_option(0); // default power down mode; TODO check this
127 system_deep_sleep(sleep_us);
128
129 for (;;) {
130 // we must not return
131 ets_loop_iter();
132 }
133
134 return mp_const_none;
135}
136STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
137
Paul Sokolovsky71930862016-01-05 21:23:23 +0200138typedef struct _esp_timer_obj_t {
139 mp_obj_base_t base;
140 os_timer_t timer;
141 mp_obj_t callback;
142} esp_timer_obj_t;
143
144const mp_obj_type_t esp_timer_type;
145
146STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
147 esp_timer_obj_t *self = self_in;
148 mp_printf(print, "Timer(%p)", &self->timer);
149}
150
Paul Sokolovskyeac22e22017-01-04 16:10:42 +0300151STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Paul Sokolovsky71930862016-01-05 21:23:23 +0200152 mp_arg_check_num(n_args, n_kw, 1, 1, false);
153 esp_timer_obj_t *tim = m_new_obj(esp_timer_obj_t);
154 tim->base.type = &esp_timer_type;
155 return tim;
156}
157
158STATIC void esp_timer_cb(void *arg) {
159 esp_timer_obj_t *self = arg;
Damien George31ea1582017-02-20 17:59:18 +1100160 mp_sched_schedule(self->callback, self);
Paul Sokolovsky71930862016-01-05 21:23:23 +0200161}
162
163STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
164 static const mp_arg_t allowed_args[] = {
165// { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
166 { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
167 { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
168 { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
169 };
170
171 // parse args
172 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
173 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
174
175 self->callback = args[2].u_obj;
Paul Sokolovskyf39bcb32016-01-07 18:58:52 +0200176 // Be sure to disarm timer before making any changes
177 os_timer_disarm(&self->timer);
Paul Sokolovsky71930862016-01-05 21:23:23 +0200178 os_timer_setfn(&self->timer, esp_timer_cb, self);
179 os_timer_arm(&self->timer, args[0].u_int, args[1].u_int);
180
181 return mp_const_none;
182}
183
184STATIC mp_obj_t esp_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
185 return esp_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
186}
187STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_timer_init_obj, 1, esp_timer_init);
188
189STATIC mp_obj_t esp_timer_deinit(mp_obj_t self_in) {
190 esp_timer_obj_t *self = self_in;
191 os_timer_disarm(&self->timer);
192 return mp_const_none;
193}
194STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_timer_deinit_obj, esp_timer_deinit);
195
196STATIC const mp_map_elem_t esp_timer_locals_dict_table[] = {
197 { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&esp_timer_deinit_obj },
198 { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&esp_timer_init_obj },
199// { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&esp_timer_callback_obj },
Paul Sokolovskyc70637b2016-03-04 22:26:59 +0200200 { MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(false) },
201 { MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(true) },
Paul Sokolovsky71930862016-01-05 21:23:23 +0200202};
203STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table);
204
205const mp_obj_type_t esp_timer_type = {
206 { &mp_type_type },
207 .name = MP_QSTR_Timer,
208 .print = esp_timer_print,
209 .make_new = esp_timer_make_new,
210 .locals_dict = (mp_obj_t)&esp_timer_locals_dict,
211};
212
Damien George927388e2016-06-01 17:26:49 +0100213// this bit is unused in the Xtensa PS register
214#define ETS_LOOP_ITER_BIT (12)
215
Damien George9a368ae2016-05-20 13:30:33 +0100216STATIC mp_obj_t machine_disable_irq(void) {
Damien George927388e2016-06-01 17:26:49 +0100217 uint32_t state = disable_irq();
218 state = (state & ~(1 << ETS_LOOP_ITER_BIT)) | (ets_loop_iter_disable << ETS_LOOP_ITER_BIT);
219 ets_loop_iter_disable = 1;
220 return mp_obj_new_int(state);
Damien George9a368ae2016-05-20 13:30:33 +0100221}
222MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
223
Damien George927388e2016-06-01 17:26:49 +0100224STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
225 uint32_t state = mp_obj_get_int(state_in);
226 ets_loop_iter_disable = (state >> ETS_LOOP_ITER_BIT) & 1;
227 enable_irq(state & ~(1 << ETS_LOOP_ITER_BIT));
Damien George9a368ae2016-05-20 13:30:33 +0100228 return mp_const_none;
229}
230MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
231
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +0200232STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
233 { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
234 { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
235 { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
236 { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
Paul Sokolovsky71930862016-01-05 21:23:23 +0200237
Damien Georgef7be8032016-02-17 15:19:03 +0000238 { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
Paul Sokolovsky81fd5682016-04-05 00:20:25 +0300239 { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
Paul Sokolovsky050e6452016-04-15 22:07:28 +0300240 { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
Paul Sokolovskyde125022016-04-05 00:57:49 +0300241 { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
Paul Sokolovskyc2070d72016-08-07 15:51:04 +0300242 { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
Paul Sokolovsky31ad1bb2016-08-07 16:20:01 +0300243 { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
Damien George32d7cf62016-04-21 11:43:37 +0100244 { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
Damien Georgef7be8032016-02-17 15:19:03 +0000245
Damien George9a368ae2016-05-20 13:30:33 +0100246 { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
247 { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
248
Damien Georgecff2b7a2016-05-31 14:06:50 +0100249 { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
250
Damien George32d7cf62016-04-21 11:43:37 +0100251 { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
Paul Sokolovsky71930862016-01-05 21:23:23 +0200252 { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
Paul Sokolovsky263aaa72016-08-28 14:48:49 +0300253 { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&esp_wdt_type) },
Paul Sokolovsky26f06162016-02-03 15:23:16 +0200254 { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
Paul Sokolovsky287180a2017-01-01 19:17:00 +0300255 { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
Damien George632d8ef2016-03-02 13:37:27 +0000256 { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
Damien Georgeb62bead2016-03-08 22:59:58 +0000257 { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
Damien George1a0a3232016-04-06 19:45:52 +0300258 { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
Damien Georgea5254932016-04-12 13:55:20 +0100259 { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
Damien Georgead166852016-12-08 14:41:58 +1100260 { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hspi_type) },
Damien George32d7cf62016-04-21 11:43:37 +0100261
262 // wake abilities
263 { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
264
265 // reset causes
Damien Georgef3b54802016-09-08 12:50:38 +1000266 { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },
Damien George32d7cf62016-04-21 11:43:37 +0100267 { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
268 { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) },
Paul Sokolovsky1708fe32016-09-04 19:45:58 +0300269 { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(REASON_WDT_RST) },
270 { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(REASON_SOFT_RESTART) },
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +0200271};
272
273STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
274
275const mp_obj_module_t mp_module_machine = {
276 .base = { &mp_type_module },
Paul Sokolovsky5d7c4082015-12-31 00:51:08 +0200277 .globals = (mp_obj_dict_t*)&machine_module_globals,
278};
279
280#endif // MICROPY_PY_MACHINE