Files

670 lines
22 KiB
C
Raw Permalink Normal View History

2018-01-03 14:18:06 +01:00
/*
* This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo
2018-01-03 14:18:06 +01:00
*
* The MIT License (MIT)
*
* Copyright (c) 2013 2014 Damien P. George
2018-01-03 14:18:06 +01:00
* Copyright (c) 2015 Daniel Campora
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
* Copyright (c) 2018 LoBo (https://github.com/loboris)
2018-01-03 14:18:06 +01:00
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <time.h>
#include <stdio.h>
#include <string.h>
2018-12-04 14:06:15 +08:00
#include "sdkconfig.h"
2018-01-03 14:18:06 +01:00
#include "apps/sntp/sntp.h"
2018-12-04 14:06:15 +08:00
#include "driver/rtc_io.h"
#include "esp_log.h"
#include "rom/crc.h"
2018-01-03 14:18:06 +01:00
#include "py/nlr.h"
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "machine_rtc.h"
#include "mphalport.h"
2018-12-04 14:06:15 +08:00
#include "modmachine.h"
#include "mpsleep.h"
2018-01-03 14:18:06 +01:00
#define RTC_MEM_INT_SIZE 64
#define RTC_MEM_STR_SIZE 2048
2018-12-04 14:06:15 +08:00
extern int MainTaskCore;
2018-01-03 14:18:06 +01:00
2018-12-04 14:06:15 +08:00
char mpy_time_zone[64] = {'\0'};
2018-01-03 14:18:06 +01:00
static int RTC_DATA_ATTR rtc_mem_int[RTC_MEM_INT_SIZE] = { 0 };
static char RTC_DATA_ATTR rtc_mem_str[RTC_MEM_STR_SIZE] = { 0 };
static uint16_t RTC_DATA_ATTR rtc_mem_int_crc;
static uint16_t RTC_DATA_ATTR rtc_mem_str_crc;
2018-01-17 16:04:14 +01:00
static TaskHandle_t sntp_handle = NULL;
xSemaphoreHandle sntp_mutex = NULL;
2018-01-03 14:18:06 +01:00
#define DEFAULT_SNTP_SERVER "pool.ntp.org"
//------------------------------
typedef struct _mach_rtc_obj_t {
mp_obj_base_t base;
bool synced;
2018-01-17 16:04:14 +01:00
uint32_t sntp_update_period;
char sntp_server_name[64];
2018-01-03 14:18:06 +01:00
} mach_rtc_obj_t;
static RTC_DATA_ATTR uint64_t seconds_at_boot;
2018-01-17 16:04:14 +01:00
static mach_rtc_obj_t mach_rtc_obj;
2018-01-03 14:18:06 +01:00
const mp_obj_type_t mach_rtc_type;
//------------------------
static void rtc_init_mem()
{
memset(rtc_mem_int, 0, sizeof(rtc_mem_int));
memset(rtc_mem_str, 0, sizeof(rtc_mem_str));
rtc_mem_int_crc = 0;
rtc_mem_str_crc = 0;
}
//--------------------
void rtc_init0(void) {
2018-12-04 14:06:15 +08:00
mpsleep_reset_cause_t rstc = mpsleep_get_reset_cause();
if ((rstc != MPSLEEP_DEEPSLEEP_RESET) && (rstc != MPSLEEP_SOFT_RESET) && (rstc != MPSLEEP_SOFT_CPU_RESET)) {
seconds_at_boot = 0;
setTicks_base(0);
rtc_init_mem();
}
2018-01-03 14:18:06 +01:00
}
2018-12-04 14:06:15 +08:00
// Set system date time
2018-01-03 14:18:06 +01:00
//-------------------------------------------------------
STATIC mp_obj_t mach_rtc_datetime(const mp_obj_t *args) {
struct tm tm_info;
// set date and time
mp_obj_t *items;
uint len;
mp_obj_get_array(args[1], &len, &items);
// verify the tuple
if (len < 3 || len > 8) {
mp_raise_ValueError("Invalid arguments");
}
tm_info.tm_year = mp_obj_get_int(items[0]) - 1900;
tm_info.tm_mon = mp_obj_get_int(items[1]) - 1;
tm_info.tm_mday = mp_obj_get_int(items[2]);
if (len < 6) {
tm_info.tm_sec = 0;
} else {
tm_info.tm_sec = mp_obj_get_int(items[5]);
}
if (len < 5) {
tm_info.tm_min = 0;
} else {
tm_info.tm_min = mp_obj_get_int(items[4]);
}
if (len < 4) {
tm_info.tm_hour = 0;
} else {
tm_info.tm_hour = mp_obj_get_int(items[3]);
}
int seconds = mktime(&tm_info);
if (seconds == -1) seconds = 0;
struct timeval now;
gettimeofday(&now, NULL);
uint64_t ticks_us = ((((uint64_t)now.tv_sec * 1000000) + (uint64_t)now.tv_usec) - getTicks_base());
now.tv_sec = seconds;
2018-01-03 14:18:06 +01:00
now.tv_usec = 0;
settimeofday(&now, NULL);
// Set new base for ticks counting
setTicks_base((((uint64_t)now.tv_sec * 1000000) - ticks_us));
2018-01-03 14:18:06 +01:00
2018-12-04 14:06:15 +08:00
seconds_at_boot = seconds;
2018-01-03 14:18:06 +01:00
return mp_const_none;
}
//--------------------------------------------------------------------------------------------------------------
STATIC mp_obj_t mach_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// setup the object
mach_rtc_obj_t *self = &mach_rtc_obj;
self->base.type = &mach_rtc_type;
// return constant object
return (mp_obj_t)&mach_rtc_obj;
}
//--------------------------------------------------------------
STATIC mp_obj_t mach_rtc_init(mp_obj_t self_in, mp_obj_t date) {
mp_obj_t args[2] = {self_in, date};
mach_rtc_datetime(args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mach_rtc_init_obj, mach_rtc_init);
//-----------------------------------------------
STATIC mp_obj_t mach_rtc_now (mp_obj_t self_in) {
// get the time from the RTC
time_t now;
time(&now);
struct tm *tm_info;
tm_info = localtime(&now);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm_info->tm_year + 1900),
mp_obj_new_int(tm_info->tm_mon + 1),
mp_obj_new_int(tm_info->tm_mday),
mp_obj_new_int(tm_info->tm_hour),
mp_obj_new_int(tm_info->tm_min),
mp_obj_new_int(tm_info->tm_sec),
mp_obj_new_int(tm_info->tm_wday + 1),
mp_obj_new_int(tm_info->tm_yday + 1)
};
return mp_obj_new_tuple(8, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mach_rtc_now_obj, mach_rtc_now);
2018-01-17 16:04:14 +01:00
//------------------------------------
static void start_sntp(char *srv_name)
{
if (sntp_enabled()) sntp_stop();
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, srv_name);
sntp_is_synced = false;
sntp_init();
}
//---------------------------------
void sntp_task (void *pvParameters)
{
2018-01-17 16:04:14 +01:00
mach_rtc_obj_t *rtc = (mach_rtc_obj_t *)pvParameters;
struct timeval tv;
2018-01-17 16:04:14 +01:00
uint32_t ellapsed=0, start_time;
uint64_t ticks_us;
int check_interval = 100;
gettimeofday(&tv, NULL);
2018-01-17 16:04:14 +01:00
start_time = tv.tv_sec;
// get current ticks_us
ticks_us = ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base());
2018-01-17 16:04:14 +01:00
ESP_LOGD("SNTP_TASK", "start synchronization");
2018-01-17 16:04:14 +01:00
start_sntp(rtc->sntp_server_name);
while (1) {
vTaskDelay(check_interval / portTICK_PERIOD_MS);
2018-01-17 16:04:14 +01:00
gettimeofday(&tv, NULL);
ticks_us += check_interval * 1000;
ellapsed += check_interval;
2018-01-17 16:04:14 +01:00
if (sntp_is_synced) {
sntp_stop();
sntp_is_synced = false;
ESP_LOGD("SNTP_TASK", "time synchronized");
// Set new base for ticks counting
setTicks_base((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec - ticks_us));
2018-01-17 16:04:14 +01:00
if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) {
rtc->synced = true;
seconds_at_boot = tv.tv_sec;
xSemaphoreGive(sntp_mutex);
}
// Terminate the task if periodic update is not requested
if (rtc->sntp_update_period <= 10) break;
// else prepare for next update
ESP_LOGD("SNTP_TASK", "next update in %d seconds", rtc->sntp_update_period);
start_time = tv.tv_sec;
ticks_us = ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base());
ellapsed = 0;
check_interval = 1000;
2018-01-17 16:04:14 +01:00
}
else {
ellapsed = tv.tv_sec - start_time;
if (ellapsed >= rtc->sntp_update_period) {
// Update period expired, update time from server
check_interval = 100;
2018-01-17 16:04:14 +01:00
start_time = tv.tv_sec;
ESP_LOGD("SNTP_TASK", "start synchronization");
2018-01-17 16:04:14 +01:00
start_sntp(rtc->sntp_server_name);
}
}
}
// Terminate the task
2018-01-17 16:04:14 +01:00
sntp_handle = NULL;
vTaskDelete(NULL);
}
2018-12-04 14:06:15 +08:00
//--------------------------------------------
void tz_fromto_NVS(char *gettzs, char *settzs)
{
size_t len = 0;
char value[64] = {'\0'};
if (gettzs) {
gettzs[0] = '\0';
esp_err_t ret = nvs_get_str(mpy_nvs_handle, "MpyTimeZone", NULL, &len);
if ((ret == ESP_OK ) && (len > 0) && (len < 64)) {
esp_err_t ret = nvs_get_str(mpy_nvs_handle, "MpyTimeZone", value, &len);
if ((ret == ESP_OK ) && (len > 0) && (len < 64)) {
if (gettzs) strcpy(gettzs, value);
}
}
}
if (settzs) {
esp_err_t esp_err = nvs_set_str(mpy_nvs_handle, "MpyTimeZone", settzs);
if (ESP_OK == esp_err) {
nvs_commit(mpy_nvs_handle);
}
}
}
2018-01-03 14:18:06 +01:00
//---------------------------------------------------------------------------------------------
STATIC mp_obj_t mach_rtc_ntp_sync(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_server, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
2018-01-17 16:04:14 +01:00
{ MP_QSTR_update_period, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_tz, MP_ARG_OBJ, {.u_obj = mp_const_none} },
2018-01-03 14:18:06 +01:00
};
mach_rtc_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
2018-01-17 16:04:14 +01:00
int period = args[1].u_int;
if (period < 300) period = 10;
2018-01-03 14:18:06 +01:00
2018-01-17 16:04:14 +01:00
char srv_name[64];
sprintf(srv_name, "%s", DEFAULT_SNTP_SERVER);
if (args[0].u_obj != mp_const_none) {
const char *srvn = mp_obj_str_get_str(args[0].u_obj);
if ((strlen(srvn) > 3) && (strlen(srvn) < 64)) sprintf(srv_name, "%s", srvn);
}
2018-12-04 14:06:15 +08:00
if (strlen(mpy_time_zone) == 0) {
// Try to get tz from NVS
tz_fromto_NVS(mpy_time_zone, NULL);
if (strlen(mpy_time_zone) == 0) {
#ifdef MICROPY_TIMEZONE
// ===== Set default time zone ======
snprintf(mpy_time_zone, sizeof(mpy_time_zone)-1, "%s", MICROPY_TIMEZONE);
#endif
}
}
2018-01-17 16:04:14 +01:00
if (args[2].u_obj != mp_const_none) {
2018-12-04 14:06:15 +08:00
// get TZ argument
2018-01-17 16:04:14 +01:00
const char *tzs = mp_obj_str_get_str(args[2].u_obj);
2018-12-04 14:06:15 +08:00
if ((strlen(tzs) > 2) && (strlen(tzs) < 64)) {
sprintf(mpy_time_zone, "%s", tzs);
tz_fromto_NVS(NULL, mpy_time_zone);
}
else {
mp_raise_ValueError("tz string length must be 3 - 63");
2018-01-17 16:04:14 +01:00
}
}
2018-12-04 14:06:15 +08:00
setenv("TZ", mpy_time_zone, 1);
2018-01-03 14:18:06 +01:00
tzset();
2018-01-17 16:04:14 +01:00
if (sntp_mutex == NULL) {
// Create sntp mutex
sntp_mutex = xSemaphoreCreateMutex();
if (sntp_mutex == NULL) {
mp_raise_msg(&mp_type_OSError, "Error creating SNTP mutex");
}
}
2018-01-03 14:18:06 +01:00
2018-01-17 16:04:14 +01:00
if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) {
sprintf(self->sntp_server_name, "%s", srv_name);
self->sntp_update_period = period;
self->synced = false;
xSemaphoreGive(sntp_mutex);
}
else {
mp_raise_msg(&mp_type_OSError, "Error acquiring SNTP mutex");
}
2018-01-03 14:18:06 +01:00
2018-01-17 16:04:14 +01:00
if (sntp_handle == NULL) {
// Create and start sntp task
2018-12-04 14:06:15 +08:00
#if CONFIG_MICROPY_USE_BOTH_CORES
int tres = xTaskCreate(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &sntp_handle);
#else
int tres = xTaskCreatePinnedToCore(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &sntp_handle, MainTaskCore);
#endif
if (tres != pdTRUE) {
2018-01-17 16:04:14 +01:00
mp_raise_msg(&mp_type_OSError, "Error creating SNTP task");
}
}
2018-01-03 14:18:06 +01:00
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mach_rtc_ntp_sync_obj, 1, mach_rtc_ntp_sync);
//------------------------------------------------------
STATIC mp_obj_t mach_rtc_has_synced (mp_obj_t self_in) {
2018-01-17 16:04:14 +01:00
if (sntp_mutex == NULL) return mp_const_false;
mach_rtc_obj_t *self = MP_OBJ_TO_PTR(self_in);
bool snc = false;
if (xSemaphoreTake(sntp_mutex, 5000 / portTICK_PERIOD_MS) == pdTRUE) {
snc = self->synced;
xSemaphoreGive(sntp_mutex);
}
if (snc) return mp_const_true;
else return mp_const_false;
2018-01-03 14:18:06 +01:00
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mach_rtc_has_synced_obj, mach_rtc_has_synced);
2018-01-17 16:04:14 +01:00
//------------------------------------------------------
STATIC mp_obj_t mach_rtc_sntp_state (mp_obj_t self_in) {
if (sntp_mutex == NULL) return mp_const_false;
mach_rtc_obj_t *self = MP_OBJ_TO_PTR(self_in);
int period = 0;
if (sntp_handle == NULL) return mp_const_false;
if (xSemaphoreTake(sntp_mutex, 5000 / portTICK_PERIOD_MS) == pdTRUE) {
period = self->sntp_update_period;
xSemaphoreGive(sntp_mutex);
}
if (period == 0) return mp_const_false;
else return mp_obj_new_int(period);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mach_rtc_sntp_state_obj, mach_rtc_sntp_state);
2018-01-03 14:18:06 +01:00
//----------------------------------------------------------------------------------------------------
STATIC mp_obj_t machine_rtc_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
2018-12-04 14:06:15 +08:00
enum {ARG_pin, ARG_level, ARG_count};
2018-01-03 14:18:06 +01:00
const mp_arg_t allowed_args[] = {
2018-12-04 14:06:15 +08:00
{ MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} },
{ MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} },
{ MP_QSTR_count, MP_ARG_INT, {.u_int = 0} },
2018-01-03 14:18:06 +01:00
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_pin].u_obj == mp_const_none) {
machine_rtc_config.ext0_pin = -1; // "None"
2018-12-04 14:06:15 +08:00
}
else {
int pin_id = machine_pin_get_gpio(args[ARG_pin].u_obj);
2018-01-03 14:18:06 +01:00
if (pin_id != machine_rtc_config.ext0_pin) {
2018-12-04 14:06:15 +08:00
if (!rtc_gpio_is_valid_gpio(pin_id)) {
mp_raise_ValueError("Invalid ext0 pin");
2018-01-03 14:18:06 +01:00
}
2018-12-04 14:06:15 +08:00
rtc_gpio_init(pin_id);
rtc_gpio_set_direction(pin_id, RTC_GPIO_MODE_INPUT_ONLY);
if (args[ARG_level].u_bool) {
rtc_gpio_pulldown_en(pin_id);
rtc_gpio_pullup_dis(pin_id);
}
else {
rtc_gpio_pulldown_dis(pin_id);
rtc_gpio_pullup_en(pin_id);
}
rtc_gpio_hold_en(pin_id);
machine_rtc_config.ext0_pin = (int8_t)pin_id;
machine_rtc_config.ext0_rtcpin = rtc_gpio_desc[pin_id].rtc_num;
2018-01-03 14:18:06 +01:00
}
}
machine_rtc_config.ext0_level = args[ARG_level].u_bool;
2018-12-04 14:06:15 +08:00
machine_rtc_config.ext0_count = args[ARG_count].u_int;
machine_rtc_config.pulse_count = 0;
2018-01-03 14:18:06 +01:00
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rtc_wake_on_ext0_obj, 1, machine_rtc_wake_on_ext0);
//----------------------------------------------------------------------------------------------------
STATIC mp_obj_t machine_rtc_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {ARG_pins, ARG_level};
const mp_arg_t allowed_args[] = {
2018-12-04 14:06:15 +08:00
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_level, MP_ARG_INT, {.u_int = machine_rtc_config.ext1_level} },
2018-01-03 14:18:06 +01:00
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
2018-12-04 14:06:15 +08:00
uint8_t ext1_pins[EXT1_WAKEUP_MAX_PINS] = {-1};
uint32_t ext1_rtcpins[EXT1_WAKEUP_MAX_PINS] = {0};
for (int i=0; i<EXT1_WAKEUP_MAX_PINS; i++) {
ext1_pins[i] = machine_rtc_config.ext1_pins[i];
ext1_rtcpins[i] = machine_rtc_config.ext1_rtcpins[i];
}
int ext1_level = args[ARG_level].u_int;
if ((ext1_level < 0) || (ext1_level > 2)) {
mp_raise_ValueError("Invalid ext1 level !");
}
2018-01-03 14:18:06 +01:00
// Check that all pins are allowed
if (args[ARG_pins].u_obj != mp_const_none) {
mp_uint_t len = 0;
mp_obj_t *elem;
mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem);
2018-12-04 14:06:15 +08:00
int pins = (len > EXT1_WAKEUP_MAX_PINS) ? EXT1_WAKEUP_MAX_PINS : len;
2018-01-03 14:18:06 +01:00
2018-12-04 14:06:15 +08:00
for (int i = 0; i < pins; i++) {
int pin_id = machine_pin_get_gpio(elem[i]);
2018-01-03 14:18:06 +01:00
2018-12-04 14:06:15 +08:00
if (!rtc_gpio_is_valid_gpio(pin_id)) {
mp_raise_ValueError("Invalid ext1 pin");
2018-01-03 14:18:06 +01:00
break;
}
2018-12-04 14:06:15 +08:00
rtc_gpio_init(pin_id);
rtc_gpio_set_direction(pin_id, RTC_GPIO_MODE_INPUT_ONLY);
if (args[ARG_level].u_bool) {
rtc_gpio_pulldown_en(pin_id);
rtc_gpio_pullup_dis(pin_id);
}
else {
rtc_gpio_pulldown_dis(pin_id);
rtc_gpio_pullup_en(pin_id);
}
rtc_gpio_hold_en(pin_id);
ext1_pins[i] = pin_id;
ext1_rtcpins[i] = rtc_gpio_desc[pin_id].rtc_num;
}
}
else {
for (int i=0; i<EXT1_WAKEUP_MAX_PINS; i++) {
ext1_pins[i] = -1;
ext1_rtcpins[i] = 0;
2018-01-03 14:18:06 +01:00
}
}
2018-12-04 14:06:15 +08:00
machine_rtc_config.ext1_level = (uint8_t)ext1_level;
for (int i=0; i<EXT1_WAKEUP_MAX_PINS; i++) {
machine_rtc_config.ext1_pins[i] = ext1_pins[i];
machine_rtc_config.ext1_rtcpins[i] = ext1_rtcpins[i];
}
2018-01-03 14:18:06 +01:00
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rtc_wake_on_ext1_obj, 1, machine_rtc_wake_on_ext1);
// ====== RTC memory functions ============================
//--------------------------------------------------------------------------------
STATIC mp_obj_t esp_rtcmem_write(mp_obj_t self_in, mp_obj_t _pos, mp_obj_t _val) {
int pos = mp_obj_get_int(_pos);
int val = mp_obj_get_int(_val);
if (pos >= RTC_MEM_INT_SIZE) {
//mp_raise_msg(&mp_type_IndexError, "Index out of range");
return mp_const_false;
}
rtc_mem_int[pos] = val;
// Set CRC
rtc_mem_int_crc = crc16_le(0, (uint8_t const *)rtc_mem_int, RTC_MEM_INT_SIZE*sizeof(int));
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_rtcmem_write_obj, esp_rtcmem_write);
//----------------------------------------------------------------
STATIC mp_obj_t esp_rtcmem_read(mp_obj_t self_in, mp_obj_t _pos) {
int pos = mp_obj_get_int(_pos);
if (pos >= RTC_MEM_INT_SIZE) {
//mp_raise_msg(&mp_type_IndexError, "Index out of range");
return mp_const_none;
}
if (rtc_mem_int_crc != crc16_le(0, (uint8_t const *)rtc_mem_int, RTC_MEM_INT_SIZE*sizeof(int))) {
return mp_const_none;
}
return mp_obj_new_int(rtc_mem_int[pos]);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_rtcmem_read_obj, esp_rtcmem_read);
//--------------------------------------------------------------------------
STATIC mp_obj_t esp_rtcmem_write_string(mp_obj_t self_in, mp_obj_t str_in) {
const char *str = mp_obj_str_get_str(str_in);
if (strlen(str) >= RTC_MEM_STR_SIZE) {
//mp_raise_msg(&mp_type_ValueError, "String length too big");
return mp_const_false;
}
memset(rtc_mem_str, 0, sizeof(rtc_mem_str));
strcpy(rtc_mem_str, str);
// Set CRC
rtc_mem_str_crc = crc16_le(0, (uint8_t const *)rtc_mem_str, RTC_MEM_STR_SIZE);
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_rtcmem_write_string_obj, esp_rtcmem_write_string);
//--------------------------------------------------------
STATIC mp_obj_t esp_rtcmem_read_string(mp_obj_t self_in) {
if (rtc_mem_str_crc != crc16_le(0, (uint8_t const *)rtc_mem_str, RTC_MEM_STR_SIZE)) {
return mp_const_none;
}
2018-12-04 14:06:15 +08:00
return mp_obj_new_str(rtc_mem_str, strlen(rtc_mem_str));
2018-01-03 14:18:06 +01:00
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_rtcmem_read_string_obj, esp_rtcmem_read_string);
//--------------------------------------------------
STATIC mp_obj_t esp_rtcmem_clear(mp_obj_t self_in) {
rtc_init_mem();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_rtcmem_clear_obj, esp_rtcmem_clear);
2018-12-04 14:06:15 +08:00
//--------------------------------------------------------------------------------------------
STATIC void machine_rtc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
char ext0[64] = {'\0'};
char ext1[32 + (EXT1_WAKEUP_MAX_PINS*3)] = {'\0'};
if (machine_rtc_config.ext0_pin >= 0) {
sprintf(ext0, "Wake on EXT0: Pin=%d, Level=%s, Count=%d",
machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? "High" : "Low", machine_rtc_config.ext0_count);
}
int has_ext1_pins = 0;
for (int i=0; i<EXT1_WAKEUP_MAX_PINS; i++) {
if (machine_rtc_config.ext1_pins[i] >= 0) has_ext1_pins++;
}
if (has_ext1_pins) {
if (strlen(ext0) > 0) strcat(ext0, "; ");
sprintf(ext1, "Wake on EXT1: Pins (");
char stemp[16];
for (int i=0; i<EXT1_WAKEUP_MAX_PINS; i++) {
if (machine_rtc_config.ext1_pins[i] >= 0) {
sprintf(stemp, "%d,", machine_rtc_config.ext1_pins[i]);
strcat(ext1, stemp);
}
}
if (ext1[strlen(ext1)-1] == ',') ext1[strlen(ext1)-1] = '\0';
strcat(ext1, ")");
stemp[0] = '\0';
if (machine_rtc_config.ext1_level == ESP_EXT1_WAKEUP_ANY_HIGH) sprintf(stemp, "Any High");
else if (machine_rtc_config.ext1_level == ESP_EXT1_WAKEUP_ALL_LOW) sprintf(stemp, "All Low");
else if (machine_rtc_config.ext1_level == EXT1_WAKEUP_ALL_HIGH) sprintf(stemp, "All High");
if (strlen(stemp) > 0) {
strcat(ext1, ", Level: ");
strcat(ext1, stemp);
}
}
mp_printf(print, "RTC (");
if (strlen(ext0) > 0) mp_printf(print, " %s", ext0);
if (strlen(ext1) > 0) mp_printf(print, "%s", ext1);
mp_printf(print, " )");
}
2018-01-03 14:18:06 +01:00
//=========================================================
STATIC const mp_map_elem_t mach_rtc_locals_dict_table[] = {
2018-12-04 14:06:15 +08:00
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mach_rtc_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_now), (mp_obj_t)&mach_rtc_now_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ntp_sync), (mp_obj_t)&mach_rtc_ntp_sync_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ntp_state), (mp_obj_t)&mach_rtc_sntp_state_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_synced), (mp_obj_t)&mach_rtc_has_synced_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext0), (mp_obj_t)&machine_rtc_wake_on_ext0_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext1), (mp_obj_t)&machine_rtc_wake_on_ext1_obj },
2018-01-03 14:18:06 +01:00
2018-12-04 14:06:15 +08:00
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&esp_rtcmem_write_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&esp_rtcmem_read_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&esp_rtcmem_clear_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_string), (mp_obj_t)&esp_rtcmem_write_string_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_read_string), (mp_obj_t)&esp_rtcmem_read_string_obj},
// Constants
{ MP_ROM_QSTR(MP_QSTR_EXT1_ANYHIGH), MP_ROM_INT(ESP_EXT1_WAKEUP_ANY_HIGH) },
{ MP_ROM_QSTR(MP_QSTR_EXT1_ALLLOW), MP_ROM_INT(ESP_EXT1_WAKEUP_ALL_LOW) },
{ MP_ROM_QSTR(MP_QSTR_EXT1_ALLHIGH), MP_ROM_INT(EXT1_WAKEUP_ALL_HIGH) },
2018-01-03 14:18:06 +01:00
};
STATIC MP_DEFINE_CONST_DICT(mach_rtc_locals_dict, mach_rtc_locals_dict_table);
//===================================
const mp_obj_type_t mach_rtc_type = {
{ &mp_type_type },
.name = MP_QSTR_RTC,
2018-12-04 14:06:15 +08:00
.print = machine_rtc_print,
2018-01-03 14:18:06 +01:00
.make_new = mach_rtc_make_new,
.locals_dict = (mp_obj_t)&mach_rtc_locals_dict,
};