#include "project.h" #define J2(a,b) a ## b #define J3(a,b,c) a ## b ## c #define P1 (GPIO3) #define P1_PORT GPIOE #define T_BIT 1 #define T_PORT GPIOE #define T_EXTI_LINE T_BIT #define M_T(a) J2(GPIO,a) #define T M_T(T_BIT) #define M_EXTI_T(a) J2(EXTI,a) #define EXTI_T M_EXTI_T(T_EXTI_LINE) #define M_exti_t_isr(a) J3(exti,a,_isr) #define exti_t_isr M_exti_t_isr(T_EXTI_LINE) #define M_NVIC_EXTI_T_IRQ(a) J3(NVIC_EXTI,a,_IRQ) #define NVIC_EXTI_T_IRQ M_NVIC_EXTI_T_IRQ(T_EXTI_LINE) static Event_ring msf_ring; static uint64_t msf_last_second; uint64_t msf_last_happy; static char msf_info[40]; static EPOCH msf_time; void exti_t_isr (void) { uint32_t now = HW_CLOCK_REG; int v; v = !!gpio_get (T_PORT, T); nvic_disable_irq (NVIC_EXTI_T_IRQ); exti_reset_request (EXTI_T); msf_ring.events[msf_ring.tx_ptr].when = now; msf_ring.events[msf_ring.tx_ptr].ptp = ptp_get(); msf_ring.events[msf_ring.tx_ptr].value = v; msf_ring.tx_ptr = (msf_ring.tx_ptr + 1) & ERING_MASK; nvic_enable_irq (NVIC_EXTI_T_IRQ); } static uint8_t bitsa[60], bitsb[60]; 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, uint64_t ptp) { UTC u; EPOCH e; 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 = 0; u.nanosecond = 0; /* This is always valid a check_min_ident will fail for leap seconds*/ e = time_utc_to_epoch (u); if (bitsb[58]) e.s -= 3600; /*BST*/ msf_last_happy = make_happy (abs, 0); pll_set_offset (e, abs, ptp); dump_bits ("msfa", bitsa); dump_bits ("msfb", bitsb); printf ("MSF: Next minute is: %02d-%02d-%02d %02d:%02d\r\n", u.year, u.month, u.mday, u.hour, u.minute); msf_time = e; msf_time.s -= 1; //time_print_epoch (e); } static void report_bits (uint64_t abs, uint64_t ptp, int second, int a, int b) { if ((!second) || (second > 59)) return; bitsa[second] = a; bitsb[second] = b; if (second == 59) process_bits (abs, ptp); } void msf_dispatch (void) { static uint32_t last_0, last_1, last_s; static int second, bita, bitb, had_m; uint32_t pulse_w, offset; uint64_t abs; int is_s = 0; uint32_t now; uint64_t ptp; int v; if (msf_ring.rx_ptr == msf_ring.tx_ptr) return; v = msf_ring.events[msf_ring.rx_ptr].value; now = msf_ring.events[msf_ring.rx_ptr].when; ptp = msf_ring.events[msf_ring.rx_ptr].ptp; led1_set (v); msf_ring.rx_ptr = (msf_ring.rx_ptr + 1) & ERING_MASK; #if 0 { abs = ref_extend (now); EPOCH e = ref_decompose (abs); UTC u = time_epoch_to_utc (e); printf (" MSF %d %02d:%02d.%06d\r\n", v, u.minute, u.second, (int) (u.nanosecond / 1000)); } #endif if (v) { pulse_w = now - last_0; pulse_w /= (HW_CLOCK_HZ / 1000); if (pulse_w > 300) { last_s = now; is_s = 1; msf_time.s++; } last_1 = now; } else { pulse_w = now - last_1; pulse_w /= (HW_CLOCK_HZ / 1000); if (pulse_w > 400) { had_m = 1; second = 0; } last_0 = now; } offset = now - last_s; offset /= (HW_CLOCK_HZ / 1000); if (is_s) { abs = ref_extend (now); msf_last_second = abs; pll_dispatch (msf_last_happy, abs, ptp, "MSF"); sprintf (msf_info, "m=%d s=%02d b=%d%d", had_m, second, bita, bitb); if (had_m) { report_bits (abs, ptp, second, bita, bitb); second++; } report_time ("MSF", msf_time, abs, msf_info); // stats(); } 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; } } void msf_init (void) { MAP_INPUT (T); MAP_OUTPUT_PP (P1); gpio_set (P1_PORT, P1); delay_ms (50); gpio_clear (P1_PORT, P1); exti_select_source (EXTI_T, T_PORT); exti_set_trigger (EXTI_T, EXTI_TRIGGER_BOTH); exti_enable_request (EXTI_T); nvic_enable_irq (NVIC_EXTI_T_IRQ); }