diff options
| -rw-r--r-- | ports/mimxrt/Makefile | 3 | ||||
| -rw-r--r-- | ports/mimxrt/machine_rtc.c | 156 | ||||
| -rw-r--r-- | ports/mimxrt/modmachine.c | 1 | ||||
| -rw-r--r-- | ports/mimxrt/modmachine.h | 1 |
4 files changed, 161 insertions, 0 deletions
diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile index 21eab51fe..732485edd 100644 --- a/ports/mimxrt/Makefile +++ b/ports/mimxrt/Makefile @@ -108,6 +108,7 @@ SRC_TINYUSB_IMX_C += \ $(MCU_DIR)/drivers/fsl_flexram.c \ $(MCU_DIR)/drivers/fsl_flexspi.c \ $(MCU_DIR)/drivers/fsl_pit.c \ + $(MCU_DIR)/drivers/fsl_snvs_lp.c \ $(MCU_DIR)/drivers/fsl_trng.c \ SRC_C = \ @@ -120,6 +121,7 @@ SRC_C = \ $(BOARD_DIR)/flash_config.c \ machine_led.c \ machine_pin.c \ + machine_rtc.c \ machine_timer.c \ mimxrt_flash.c \ modutime.c \ @@ -146,6 +148,7 @@ SRC_S = lib/utils/gchelper_m3.s \ SRC_QSTR += \ machine_led.c \ machine_pin.c \ + machine_rtc.c \ machine_timer.c \ mimxrt_flash.c \ modutime.c \ diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c new file mode 100644 index 000000000..949d0b51f --- /dev/null +++ b/ports/mimxrt/machine_rtc.c @@ -0,0 +1,156 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Damien P. George + * Copyright (c) 2021 "Robert Hammelrath" <robert@hammelrath.com> + * + * 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 "py/runtime.h" +#include "modmachine.h" +#include "ticks.h" +#include "fsl_snvs_lp.h" + +typedef struct _machine_rtc_obj_t { + mp_obj_base_t base; + mp_obj_t callback; +} machine_rtc_obj_t; + +// Singleton RTC object. +STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; + +// Calculate the weekday from the date. +// The result is zero based with 0 = Sunday. +// by Michael Keith and Tom Craver, 1990. +static int calc_weekday(int y, int m, int d) { + return (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7; +} + +STATIC mp_obj_t machine_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); + + // Start up the RTC if needed. + SNVS_LP_SRTC_StartTimer(SNVS); + + // Return constant object. + return (mp_obj_t)&machine_rtc_obj; +} + +STATIC mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args) { + if (n_args == 1) { + // Get date and time. + snvs_lp_srtc_datetime_t srtc_date; + SNVS_LP_SRTC_GetDatetime(SNVS, &srtc_date); + + mp_obj_t tuple[8] = { + mp_obj_new_int(srtc_date.year), + mp_obj_new_int(srtc_date.month), + mp_obj_new_int(srtc_date.day), + mp_obj_new_int(srtc_date.hour), + mp_obj_new_int(srtc_date.minute), + mp_obj_new_int(srtc_date.second), + mp_obj_new_int(ticks_us64() % 1000000), + mp_const_none, + }; + return mp_obj_new_tuple(8, tuple); + } else { + // Set date and time. + mp_obj_t *items; + mp_int_t year; + mp_obj_get_array_fixed_n(args[1], 8, &items); + + snvs_lp_srtc_datetime_t srtc_date; + year = mp_obj_get_int(items[0]); + srtc_date.year = year >= 100 ? year : year + 2000; // allow 21 for 2021 + srtc_date.month = mp_obj_get_int(items[1]); + srtc_date.day = mp_obj_get_int(items[2]); + srtc_date.hour = mp_obj_get_int(items[3]); + srtc_date.minute = mp_obj_get_int(items[4]); + srtc_date.second = mp_obj_get_int(items[5]); + if (SNVS_LP_SRTC_SetDatetime(SNVS, &srtc_date) != kStatus_Success) { + mp_raise_ValueError(NULL); + } + + return mp_const_none; + } +} + +STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { + return machine_rtc_datetime_helper(n_args, args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime); + +STATIC mp_obj_t machine_rtc_now(mp_obj_t self_in) { + return machine_rtc_datetime_helper(1, &self_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_now_obj, machine_rtc_now); + +STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { + mp_obj_t args[2] = {self_in, date}; + machine_rtc_datetime_helper(2, args); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); + +STATIC mp_obj_t machine_rtc_weekday(mp_obj_t self_in) { + (void)self_in; // unused + int day; + snvs_lp_srtc_datetime_t srtc_date; + SNVS_LP_SRTC_GetDatetime(SNVS, &srtc_date); + day = calc_weekday(srtc_date.year, srtc_date.month, srtc_date.day); + return MP_OBJ_NEW_SMALL_INT((day + 6) % 7); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_weekday_obj, machine_rtc_weekday); + +// calibration(cal) +// When the argument is a number in the range [-16 to 15], set the calibration value. +STATIC mp_obj_t machine_rtc_calibration(mp_obj_t self_in, mp_obj_t cal_in) { + mp_int_t cal = 0; + snvs_lp_srtc_config_t snvsSrtcConfig; + cal = mp_obj_get_int(cal_in); + if (cal < -16 || cal > 15) { + mp_raise_ValueError(MP_ERROR_TEXT("value out of range -16 to 15")); + } else { + snvsSrtcConfig.srtcCalEnable = true; + snvsSrtcConfig.srtcCalValue = cal & 0x1f; // 5 bit 2's complement + SNVS_LP_SRTC_Init(SNVS, &snvsSrtcConfig); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_calibration_obj, machine_rtc_calibration); + +STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, + { MP_ROM_QSTR(MP_QSTR_now), MP_ROM_PTR(&machine_rtc_now_obj) }, + { MP_ROM_QSTR(MP_QSTR_weekday), MP_ROM_PTR(&machine_rtc_weekday_obj) }, + { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&machine_rtc_calibration_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); + +const mp_obj_type_t machine_rtc_type = { + { &mp_type_type }, + .name = MP_QSTR_RTC, + .make_new = machine_rtc_make_new, + .locals_dict = (mp_obj_t)&machine_rtc_locals_dict, +}; diff --git a/ports/mimxrt/modmachine.c b/ports/mimxrt/modmachine.c index 75fe1cd20..ff4ca7cf9 100644 --- a/ports/mimxrt/modmachine.c +++ b/ports/mimxrt/modmachine.c @@ -56,6 +56,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, + { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/mimxrt/modmachine.h b/ports/mimxrt/modmachine.h index 8741e2058..d165c00e6 100644 --- a/ports/mimxrt/modmachine.h +++ b/ports/mimxrt/modmachine.h @@ -30,6 +30,7 @@ #include "py/obj.h" extern const mp_obj_type_t machine_timer_type; +extern const mp_obj_type_t machine_rtc_type; void machine_timer_init_PIT(void); |
