summaryrefslogtreecommitdiffstats
path: root/app/msf.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/msf.c')
-rw-r--r--app/msf.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/app/msf.c b/app/msf.c
new file mode 100644
index 0000000..392bfe7
--- /dev/null
+++ b/app/msf.c
@@ -0,0 +1,226 @@
+#include "project.h"
+
+#define P1 (GPIO1)
+#define P1_PORT GPIOB
+
+#define T (GPIO0)
+#define T_PORT GPIOB
+
+static uint8_t bitsa[60], bitsb[60];
+
+static int time_known;
+static int check_parity (uint8_t *d, unsigned s, unsigned e, uint8_t p)
+{
+ unsigned i;
+
+ for (i = s; i <= e; ++i)
+ p ^= d[i];
+
+ return !p;
+}
+
+
+static unsigned bcd (uint8_t *d, unsigned s, unsigned e)
+{
+ unsigned ret = 0, c, b, i;
+
+ for (i = e, c = 1, b = 0; i >= s; --i, b++) {
+
+ if (d[i]) ret += c;
+
+
+ switch (b & 3) {
+ case 0:
+ case 1:
+ case 2:
+ c <<= 1;
+ break;
+
+ default:
+ c >>= 3;
+ c *= 10;
+ }
+ }
+
+ return ret;
+}
+
+
+
+static int check_min_ident (uint8_t *i)
+{
+ if (i[0]) return 1;
+
+ if (!i[1]) return 1;
+
+ if (!i[2]) return 1;
+
+ if (!i[3]) return 1;
+
+ if (!i[4]) return 1;
+
+ if (!i[5]) return 1;
+
+ if (!i[6]) return 1;
+
+ if (i[7]) return 1;
+
+ return 0;
+}
+
+
+
+static void process_bits (uint64_t abs)
+{
+ UTC u;
+ EPOCH msf_time;
+
+
+ if (check_min_ident (&bitsa[52])) return;
+
+ if (check_parity (bitsa, 17, 24, bitsb[54])) return;
+
+ if (check_parity (bitsa, 25, 35, bitsb[55])) return;
+
+ if (check_parity (bitsa, 36, 38, bitsb[56])) return;
+
+ if (check_parity (bitsa, 39, 51, bitsb[57])) return;
+
+ u.jday = 0;
+ u.year = bcd (bitsa, 17, 24);
+ u.month = bcd (bitsa, 25, 29);
+ u.mday = bcd (bitsa, 30, 35);
+ u.hour = bcd (bitsa, 39, 44);
+ u.minute = bcd (bitsa, 45, 51);
+ u.second = 59;
+ u.nanosecond = 0;
+
+ /* This is always valid a check_min_ident will fail for leap seconds*/
+
+ msf_time = time_utc_to_epoch (u);
+ msf_time.s -= 59;
+
+ pll_set_offset (msf_time, abs);
+ time_known = 1;
+
+ printf ("Next minute is: %02d-%02d-%02d %02d:%02d\r\n", u.year, u.month, u.mday, u.hour, u.minute);
+ time_print_epoch (msf_time);
+}
+
+
+static void report_bits (uint64_t abs, int second, int a, int b)
+{
+ if ((!second) || (second > 59)) return;
+
+ bitsa[second] = a;
+ bitsb[second] = b;
+
+ if (second == 59) process_bits (abs);
+
+}
+
+static void report_time (uint64_t abs)
+{
+ EPOCH e = pll_decompose (abs);
+ time_print_epoch (e);
+ printf ("%d\r\n", (unsigned) e.s);
+}
+
+void exti0_isr (void)
+{
+ static uint32_t last_0;
+ static uint32_t last_1;
+ static uint32_t last_s;
+ static int second, bita, bitb, had_m;
+
+ uint32_t now = SCS_DWT_CYCCNT;
+ uint64_t abs;
+
+ uint32_t pulse_w, offset;
+ int is_s = 0;
+ int v;
+
+ nvic_disable_irq (NVIC_EXTI0_IRQ);
+ exti_reset_request (EXTI0);
+
+ v = !!gpio_get (T_PORT, T);
+
+ if (v) {
+ pulse_w = now - last_0;
+ pulse_w /= (HZ / 1000);
+
+ if (pulse_w > 300) {
+ last_s = now;
+ is_s = 1;
+ }
+
+ last_1 = now;
+
+ } else {
+ pulse_w = now - last_1;
+ pulse_w /= (HZ / 1000);
+
+ if (pulse_w > 400) {
+ had_m = 1;
+ second = 0;
+ }
+
+ last_0 = now;
+ }
+
+ offset = now - last_s;
+ offset /= (HZ / 1000);
+
+
+ if (is_s) {
+ abs = abs_extend (now);
+ pll_dispatch (abs);
+
+ if (had_m) {
+ report_bits (abs, second, bita, bitb);
+ second++;
+
+ }
+
+ if (time_known)
+ report_time (abs);
+ }
+
+
+
+ if (!v) { /* 1->0 transition */
+ if (offset < 150) {
+ bita = 0;
+ bitb = 0;
+ }
+
+ if (offset < 250)
+ bitb = 0;
+ } else { /* 0->1 transition*/
+ if (is_s) {
+ bita = 1;
+ bitb = 1;
+ } else if (offset < 250)
+ bitb = 1;
+ }
+
+
+
+ nvic_enable_irq (NVIC_EXTI0_IRQ);
+}
+
+void
+radio_init (void)
+{
+ MAP_INPUT (T);
+ MAP_OUTPUT_PP (P1);
+
+ gpio_clear (P1_PORT, P1);
+
+ exti_select_source (EXTI0, T_PORT);
+ exti_set_trigger (EXTI0, EXTI_TRIGGER_BOTH);
+ exti_enable_request (EXTI0);
+ nvic_enable_irq (NVIC_EXTI0_IRQ);
+}
+
+