From a1567d590c68c15f3d14b71f0b1b1c65481956e6 Mon Sep 17 00:00:00 2001
From: schneider <schneider@blinkenlichts.net>
Date: Sat, 27 Jul 2019 19:15:12 +0200
Subject: [PATCH] feat(rtc): Initial Python RTC support

---
 epicardium/epicardium.h        | 14 ++++++++++++++
 epicardium/modules/meson.build |  1 +
 epicardium/modules/rtc.c       |  8 ++++++++
 lib/card10/card10.c            |  6 ++++++
 lib/micropython/meson.build    |  1 +
 pycardium/modules/qstrdefs.h   |  1 +
 pycardium/modules/utime.c      | 35 ++++++++++++++++++++++++++++++++++
 7 files changed, 66 insertions(+)
 create mode 100644 epicardium/modules/rtc.c

diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 26bdceb7..b90c04bb 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -57,6 +57,8 @@ typedef unsigned int size_t;
 #define API_FILE_SEEK          0x36
 #define API_FILE_TELL          0x37
 #define API_FILE_STAT          0x38
+
+#define API_RTC_GET_SECONDS    0x40
 /* clang-format on */
 
 typedef uint32_t api_int_id_t;
@@ -518,4 +520,16 @@ typedef struct epic_stat_t {
  */
 API(API_FILE_STAT, int epic_file_stat(const char* path, epic_stat_t* stat));
 
+/**
+ * RTC
+ * ===
+ */
+
+/**
+ * Read the current RTC value.
+ *
+ * :return: Unix time in seconds
+ */
+API(API_RTC_GET_SECONDS, uint32_t epic_rtc_get_seconds(void));
+
 #endif /* _EPICARDIUM_H */
diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build
index 68c1b9d9..807e9b8c 100644
--- a/epicardium/modules/meson.build
+++ b/epicardium/modules/meson.build
@@ -8,4 +8,5 @@ module_sources = files(
   'stream.c',
   'vibra.c',
   'light_sensor.c',
+  'rtc.c'
 )
diff --git a/epicardium/modules/rtc.c b/epicardium/modules/rtc.c
new file mode 100644
index 00000000..e87b1cd9
--- /dev/null
+++ b/epicardium/modules/rtc.c
@@ -0,0 +1,8 @@
+#include "rtc.h"
+
+#include <stdint.h>
+
+uint32_t epic_rtc_get_seconds(void)
+{
+	return RTC_GetSecond();
+}
diff --git a/lib/card10/card10.c b/lib/card10/card10.c
index 92ddee1b..0056aef0 100644
--- a/lib/card10/card10.c
+++ b/lib/card10/card10.c
@@ -57,11 +57,17 @@ void card10_init(void)
 	pmic_set_led(2, 0);
 	TMR_Delay(MXC_TMR0, MSEC(1000), 0);
 
+	RTC_EnableRTCE(MXC_RTC);
 	// Enable 32 kHz output
 	RTC_SquareWave(
 		MXC_RTC, SQUARE_WAVE_ENABLED, F_32KHZ, NOISE_IMMUNE_MODE, NULL
 	);
 
+	if (RTC_GetSecond() < 1546300800UL) {
+		while (RTC_Init(MXC_RTC, 1546300800UL, 0, NULL) == E_BUSY)
+			;
+	}
+
 	// Enable SPI
 	sys_cfg_spi_t spi17y_master_cfg;
 
diff --git a/lib/micropython/meson.build b/lib/micropython/meson.build
index 1bb6488d..dbd9c8fd 100644
--- a/lib/micropython/meson.build
+++ b/lib/micropython/meson.build
@@ -177,6 +177,7 @@ micropython_additional_sources = files(
   'micropython/lib/utils/stdout_helpers.c',
   'micropython/lib/utils/pyexec.c',
   'micropython/lib/mp-readline/readline.c',
+  'micropython/lib/timeutils/timeutils.c'
 )
 
 micropython_extmod_sources = files(
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index e8ac9dac..f2be2453 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -21,6 +21,7 @@ Q(ticks_us)
 Q(ticks_cpu)
 Q(ticks_add)
 Q(ticks_diff)
+Q(localtime)
 
 /* vibra */
 Q(vibra)
diff --git a/pycardium/modules/utime.c b/pycardium/modules/utime.c
index 856ab9e2..7633797f 100644
--- a/pycardium/modules/utime.c
+++ b/pycardium/modules/utime.c
@@ -1,10 +1,45 @@
 #include "mxc_delay.h"
 
+#include "epicardium.h"
 #include "extmod/utime_mphal.h"
 #include "py/mpconfig.h"
 
+#include <sys/time.h>
+#include <stdint.h>
+
+// Needs to be after the stdint include ...
+#include "lib/timeutils/timeutils.h"
+
+STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args)
+{
+	mp_int_t seconds;
+
+	if (n_args == 0 || args[0] == mp_const_none) {
+		seconds = epic_rtc_get_seconds() - 946684800UL;
+	} else {
+		seconds = mp_obj_get_int(args[0]);
+	}
+
+	timeutils_struct_time_t tm;
+	timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
+	mp_obj_t tuple[8] = {
+		tuple[0] = mp_obj_new_int(tm.tm_year),
+		tuple[1] = mp_obj_new_int(tm.tm_mon),
+		tuple[2] = mp_obj_new_int(tm.tm_mday),
+		tuple[3] = mp_obj_new_int(tm.tm_hour),
+		tuple[4] = mp_obj_new_int(tm.tm_min),
+		tuple[5] = mp_obj_new_int(tm.tm_sec),
+		tuple[6] = mp_obj_new_int(tm.tm_wday),
+		tuple[7] = mp_obj_new_int(tm.tm_yday),
+	};
+	return mp_obj_new_tuple(8, tuple);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
+
 static const mp_rom_map_elem_t time_module_globals_table[] = {
 	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
+	{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
-- 
GitLab