From 8c7ee88332652e7e79f6c1e4baacabe2183f7e8e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 2 Mar 2021 12:54:03 +0000 Subject: working, with hybrid FLL/PLL, new refclk input and support for max7219 displays, neo 5 and neo 7 and a bazillion other fixes --- .gitignore | 1 + app/ATTIC/gps_neo8.c | 1204 ++++++++++++++++++++++++++++++++++++++++++++++++++ app/Makefile | 33 +- app/abs.c | 121 ----- app/adc.c | 137 ++++++ app/cdcacm.c | 58 +-- app/clockv2.ld | 20 + app/dcf77.c | 17 +- app/dfu.c | 19 +- app/dummy_kb.c | 26 ++ app/events.h | 1 + app/gps.c | 60 ++- app/gps_neo8.c | 1204 -------------------------------------------------- app/lwip/lwipopts.h | 8 + app/lwip/pbuf.h | 179 ++++++++ app/lwip_glue.c | 42 +- app/main.c | 140 ++++-- app/max7219.c | 348 +++++++++++---- app/msf.c | 21 +- app/ntp.c | 40 +- app/pins.h | 4 + app/pll.c | 293 ++---------- app/project.h | 8 + app/prototypes.h | 68 ++- app/ptp.c | 274 ++++++++++++ app/ref.c | 486 ++++++++++++++++++++ app/roofclock.ld | 20 - app/stats.c | 6 +- app/steth.c | 314 +++++++------ app/sysclk.c | 3 +- app/ticker.c | 4 +- app/usart.c | 44 +- app/usb.c | 63 ++- boot/Makefile | 4 + boot/bootloader.c | 27 +- boot/delay.c | 1 + boot/dfu.c | 4 +- boot/max7219.c | 169 ++++++- boot/prototypes.h | 3 +- boot/usb.c | 4 +- st/siderial_time.c | 173 ++++++++ tools/dfuse-pack.py | 256 +++++++++++ 42 files changed, 3818 insertions(+), 2089 deletions(-) create mode 100644 app/ATTIC/gps_neo8.c create mode 100644 app/adc.c create mode 100644 app/clockv2.ld create mode 100644 app/dummy_kb.c delete mode 100644 app/gps_neo8.c create mode 100644 app/lwip/pbuf.h create mode 100644 app/ptp.c create mode 100644 app/ref.c delete mode 100644 app/roofclock.ld create mode 100644 st/siderial_time.c create mode 100755 tools/dfuse-pack.py diff --git a/.gitignore b/.gitignore index 1077c0a..142c0f0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.orig *.hex *.map +*.bin .*.swp almanac.c almanac.alp diff --git a/app/ATTIC/gps_neo8.c b/app/ATTIC/gps_neo8.c new file mode 100644 index 0000000..17118ed --- /dev/null +++ b/app/ATTIC/gps_neo8.c @@ -0,0 +1,1204 @@ +#include "project.h" + +#define PPS (GPIO9) +#define PPS_PORT GPIOC + +#define UBX_BUF_LEN 256 + +#define TIMEOUT 4000 + +static int ubx_ack = 0; +static int ubx_ack_xfer = 0; + +static int current_ref_hz = 1; + +static int gps_locked; +static int gps_happy; + +uint64_t gps_last_happy; + +static char fix, fix2; +static int32_t freq = 0; + +static const int fish[] = { 1, 2, 3, 4, 5, 6, 7 }; + +static Event_ring gps_ring; + +static char gps_info[60]; + + +void exti9_5_isr (void) +{ + uint32_t now = HW_CLOCK_REG; + int v; + + v = !!gpio_get (PPS_PORT, PPS); + + nvic_disable_irq (NVIC_EXTI9_5_IRQ); + exti_reset_request (EXTI9); + + gps_ring.events[gps_ring.tx_ptr].when = now; + gps_ring.events[gps_ring.tx_ptr].value = v; + gps_ring.tx_ptr = (gps_ring.tx_ptr + 1) & ERING_MASK; + + nvic_enable_irq (NVIC_EXTI9_5_IRQ); + +} + + + +static inline int +ubx_recv_byte (uint8_t *v) +{ + return !ring_read_byte (&usart1_rx_ring, v); +} + +static inline void +ubx_send_byte (uint8_t v) +{ + usart1_queue (v); +} + +#define ALMANAC_SIZE + +static int ubx_recv_almanac(uint8_t *ptr,unsigned len) +{ +uint32_t sv,week; +uint32_t almanac[8]; + +ptr+=ubx_get_u32(ptr,&sv); +len-=4; +ptr+=ubx_get_u32(ptr,&week); +len-=4; + +if (len>sizeof(almanac)) + len=sizeof(almanac); + +bzero(almanac,sizeof(almanac)); +memcpy(almanac,ptr,len); + +printf(" Almanac: %2d %d %06x %06x %06x %06x %06x %06x %06x %06x\r\n", + (int) sv,(int) week, + (unsigned) almanac[0], + (unsigned) almanac[1], + (unsigned) almanac[2], + (unsigned) almanac[3], + (unsigned) almanac[4], + (unsigned) almanac[5], + (unsigned) almanac[6], + (unsigned) almanac[7]); + +return 0; +} + +static int +ubx_recv_nav_status (uint8_t *ptr, unsigned len) +{ + uint8_t gps_fix, flags,fix_stat,flags2; + uint32_t d; + + if ((!ptr) || (len != 16)) + return -1; + + ptr += ubx_get_u32 (ptr, &d); //TOW + ptr += ubx_get_u8 (ptr, &gps_fix); //fix type + ptr += ubx_get_u8 (ptr, &flags); //fix type + ptr += ubx_get_u8 (ptr, &fix_stat); + ptr += ubx_get_u8 (ptr, &flags2); + + + switch (gps_fix) { + case 0: + case 1: + fix = '-'; + gps_locked = 0; + break; + + case 2: + fix = '2'; + gps_locked = 0; + break; + + case 3: + fix = 'L'; + gps_locked = 1; + break; + + case 4: + fix = 'R'; + gps_locked = 0; + break; + + case 5: + fix = 'T'; + gps_locked = 0; + break; + + default: + fix = '?'; + gps_locked = 0; + } + + switch (flags & 3) { + case 0: + case 2: + fix2 = '!'; + break; + + case 1: + fix2 = '-'; + break; + + case 3: + fix2 = 'D'; + + if (gps_locked == 1) + gps_locked = 2; + + break; + + default: + fix2 = '?'; + } + + + // printf ("fix: %c%c\r\n",fix,fix2); + + + if ((gps_locked) && (gps_happy < 10000)) + gps_happy++; + else + gps_happy = 0; + + return 0; +} + + +static int +ubx_recv_clock_stats (uint8_t *ptr, unsigned len) +{ + //char buf[40]; + int32_t drift; + uint32_t d; + + if ((!ptr) || (len != 20)) + return -1; + + ptr += ubx_get_u32 (ptr, &d); //TOW + ptr += ubx_get_u32 (ptr, &d); //bias + ptr += ubx_get_i32 (ptr, &drift); //drift + ptr += ubx_get_u32 (ptr, &d); //time acc estimate + ptr += ubx_get_i32 (ptr, &freq); //freq acc estimate + + // printf ("TCXO %+8dE-12\r\n", (int) freq); +#if 0 + sprintf (buf, "TCXO %+8dE-12", (int) freq); + lcd_erase_line (18, 0); + lcd_write (buf, 0, 0); +#endif + return 0; + +} + +static int +ubx_recv_utc (uint8_t *ptr, unsigned len) +{ + int32_t nano; + uint32_t acc; + uint16_t year; + uint8_t hour, min, sec, day, month,valid; + uint32_t d; + // char buf[40]; + + if ((!ptr) || (len != 20)) + return -1; + + ptr += ubx_get_u32 (ptr, &d); //TOW + ptr += ubx_get_u32 (ptr, &acc); //bias + ptr += ubx_get_i32 (ptr, &nano); + ptr += ubx_get_u16 (ptr, &year); + ptr += ubx_get_u8 (ptr, &month); + ptr += ubx_get_u8 (ptr, &day); + ptr += ubx_get_u8 (ptr, &hour); + ptr += ubx_get_u8 (ptr, &min); + ptr += ubx_get_u8 (ptr, &sec); + ptr += ubx_get_u8 (ptr, &valid); + +#if 0 + printf ("GPS META-DATA %04d-%02d-%02d %02d:%02d:%02d V:%02x Fix:%c%c TXCO %+8dE-12\r\n", + (int) year, + (int) month, + (int) day, + (int) hour, + (int) min, + (int) sec, + (unsigde) valid, + fix, fix2, (int) freq); +#endif + + sprintf(gps_info, " %04d-%02d-%02d %02d:%02d:%02d V:%02x Fix:%c%c TXCO %+8dE-12", + + (int )year, + (int )month, + (int )day, + (int )hour, + (int )min, + (int )sec, +(unsigned) valid, fix, fix2, (int) freq); + + + + if (gps_happy > 3) { + UTC u; + EPOCH gps_time; + uint32_t now; + uint64_t abs; + + u.jday = 0; + u.year = year; + u.month = month; + u.mday = day; + u.hour = hour; + u.minute = min; + u.second = sec; + u.nanosecond = 0; + + gps_time = time_utc_to_epoch (u); + + + now = HW_CLOCK_REG; + abs = ref_extend (now); + + gps_last_happy = make_happy (abs, 180); + + pll_set_offset (gps_time, abs); + + } + + +#if 0 + sprintf (buf, "%+6dE-12 %02d%02d%02d", (int) freq, + (int) hour, (int)min, (int) sec); + lcd_erase_line (18, 0); + lcd_write (buf, 0, 0); +#endif + + return 0; +} + + + +static int ubx_recv_nav_sbas(uint8_t *ptr,unsigned len) +{ +uint8_t prn,mode,service; +int8_t sys; +uint8_t n; + + ptr+=4; + + ptr += ubx_get_u8 (ptr, &prn); + ptr += ubx_get_u8 (ptr, &mode); + ptr += ubx_get_i8 (ptr, &sys); + ptr += ubx_get_u8 (ptr, &service); + + ptr += ubx_get_u8 (ptr, &n); + ptr+=3; + + printf("GPS SBAS PRN:%d M:%d S:%d SVC:%02x\r\n",prn,mode,sys,service); + + while (n--) { + ptr += ubx_get_u8 (ptr, &prn); + ptr+=11; + printf("GPS SBAS SV:%d\r\n",prn); + } + +return 0; +} + +static int ubx_recv_nav_sat(uint8_t *ptr,unsigned len) +{ +uint8_t gnssid,prn,cno,ver; +uint8_t n; + + ptr+=4; + + ptr += ubx_get_u8 (ptr, &ver); + ptr += ubx_get_u8 (ptr, &n); + ptr+=2; + + while (n--) { + ptr += ubx_get_u8 (ptr, &gnssid); + ptr += ubx_get_u8 (ptr, &prn); + ptr += ubx_get_u8 (ptr, &cno); + ptr+=9; + + printf("GPS GNSS:%2d PRN:%3d CNO:%3d\r\n",gnssid,prn,cno); + } + + +return 0; +} + + +static int ubx_recv_rinex (uint8_t *payload, unsigned len) +{ + + printf ("Rinex\r\n"); + return 0; +} + + + +static void +ubx_recv (uint8_t class, uint8_t id, uint8_t *payload, unsigned len) +{ + // printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); + + switch (class) { + case 1: + switch (id) { + case 0x3: + ubx_recv_nav_status (payload, len); + break; + + case 0x21: + ubx_recv_utc (payload, len); + break; + + case 0x22: + ubx_recv_clock_stats (payload, len); + break; + + case 0x32: + ubx_recv_nav_sbas(payload,len); + break; + + case 0x35: + ubx_recv_nav_sat(payload,len); + break; + + default: + printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); + hexdump (payload, len); + } + + break; + + case 2: + switch (id) { + case 0x10: + ubx_recv_rinex (payload, len); + + break; + } + + break; + + case 4: + switch (id) { + case 0x4: + break; + default: + printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); + hexdump (payload, len); + } + + break; + + + + case 5: + ubx_ack++; + printf (" %s for %02x.%02x\r\n", id ? "ACK" : "NAK", payload[0], + payload[1]); + + break; + + case 0x0b: + switch (id) { + case 0x30: + ubx_recv_almanac(payload,len); + break; + case 0x50: + printf ("xfer ack\r\n"); + ubx_ack_xfer++; + break; + + default: + printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); + hexdump (payload, len); + } + + break; + + default: + printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); + + if (class != 0x03) + hexdump (payload, len); + } + + +} + + +typedef enum { + UBX_SM_LOST = 0, + UBX_SM_S2, + UBX_SM_C, + UBX_SM_I, + UBX_SM_L1, + UBX_SM_L2, + UBX_SM_DATA, + UBX_SM_CKA, + UBX_SM_CKB +} ubx_sm_t; + + + + +static uint8_t * +ubx_dispatch_search (int s_class, int s_id, unsigned *len_ptr) +{ + static uint8_t buf[UBX_BUF_LEN]; + static ubx_sm_t sm = UBX_SM_LOST; + static uint8_t class, id; + static unsigned ptr; + static unsigned len; + static uint8_t ck_a, ck_b; + + + void ubx_ck (uint8_t v) { + ck_a += v; + ck_b = ck_b + ck_a; + } + + + uint8_t c; + + while (ubx_recv_byte (&c)) { + + switch (sm) { + case UBX_SM_LOST: + if (c == 0xb5) + sm = UBX_SM_S2; + + break; + + case UBX_SM_S2: + if (c == 0x62) + sm = UBX_SM_C; + else + sm = UBX_SM_LOST; + + break; + + case UBX_SM_C: + ck_a = ck_b = class = c; + sm = UBX_SM_I; + break; + + case UBX_SM_I: + ubx_ck (c); + id = c; + sm = UBX_SM_L1; + break; + + case UBX_SM_L1: + ubx_ck (c); + len = c; + sm = UBX_SM_L2; + break; + + case UBX_SM_L2: + ubx_ck (c); + len |= c << 8; + + ptr = 0; + + if (len) + sm = UBX_SM_DATA; + else + sm = UBX_SM_CKA; + + break; + + case UBX_SM_DATA: + ubx_ck (c); + + if (ptr < UBX_BUF_LEN) + buf[ptr] = c; + + ptr++; + + if (ptr == len) + sm = UBX_SM_CKA; + + break; + + case UBX_SM_CKA: + if (c == ck_a) + sm = UBX_SM_CKB; + else + sm = UBX_SM_LOST; + + break; + + case UBX_SM_CKB: + sm = UBX_SM_LOST; + + if (c != ck_b) + break; + + ubx_recv (class, id, buf, len); + + if ((class == s_class) && (id == s_id)) { + if (len_ptr) + *len_ptr = len; + + return buf; + } + + break; + } + + } + + return NULL; +} +static void gps_pps_dispatch (void) +{ + //char buf[80]; + uint32_t now; + uint64_t abs; + int v; + EPOCH e; + //UTC u; + + if (gps_ring.rx_ptr == gps_ring.tx_ptr) return; + + v = gps_ring.events[gps_ring.rx_ptr].value; + now = gps_ring.events[gps_ring.rx_ptr].when; + + led3_set(v); + + gps_ring.rx_ptr = (gps_ring.rx_ptr + 1) & ERING_MASK; + + + if (!v) return; + + abs = ref_extend (now); + + if (gps_happy) + pll_dispatch (gps_last_happy, abs, "GPS"); + + e = ref_decompose (abs); + + + //u = time_epoch_to_utc (e); + time_print_epoch ("GPS : ", e, gps_info); + +} + + +void +gps_dispatch (void) +{ + ubx_dispatch_search (-1, -1, NULL); + gps_pps_dispatch(); + +} + +static void +ubx_send (uint8_t class, uint8_t id, const void *_payload, unsigned len) +{ + uint8_t ck_a = 0, ck_b = 0; + uint8_t *payload = (uint8_t *) _payload; + + void ubx_send_byte_ck (uint8_t v) { + ubx_send_byte (v); + ck_a += v; + ck_b = ck_b + ck_a; + } + + + ubx_send_byte (0xb5); + ubx_send_byte (0x62); + + ubx_send_byte_ck (class); + ubx_send_byte_ck (id); + ubx_send_byte_ck (len & 0xff); + ubx_send_byte_ck (len >> 8); + + while (len--) + ubx_send_byte_ck (* (payload++)); + + ubx_send_byte (ck_a); + ubx_send_byte (ck_b); + + // printf ("TX> %02x.%02x\r\n", class, id); + +} + +static int +ubx_handshake (uint8_t class, uint8_t id, const void *payload, unsigned len) +{ + uint32_t timeout; + + ubx_ack = 0; + ubx_send (class, id, payload, len); + + + + timeout = ticks + TIMEOUT; + + while (!ubx_ack) { + + if (ticks > timeout) { + printf ("GPS timeout resending packet\r\n"); + usart1_drain(); + ubx_send (class, id, payload, len); + timeout = ticks + TIMEOUT; + } + + + + + gps_dispatch(); + } + + return 0; +} + +static int +ubx_handshake_xfer (uint8_t class, uint8_t id, const void *payload, + unsigned len) +{ + uint32_t timeout; + + ubx_ack_xfer = 0; + // usart1_drain(); + ubx_send (class, id, payload, len); + + + + timeout = ticks + TIMEOUT; + + while (!ubx_ack_xfer) { + + if (ticks > timeout) { + printf ("GPS timeout resending packet\r\n"); + // usart1_drain(); + ubx_send (class, id, payload, len); + timeout = ticks + TIMEOUT; + } + + + + + gps_dispatch(); + } + + return 0; +} + + + + +static uint8_t * +ubx_fetch (uint8_t class, uint8_t id, void *payload, unsigned len, + unsigned *len_ptr) +{ + uint8_t *ret; + + while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring)) + gps_dispatch(); + + ubx_send (class, id, payload, len); + + while (! (ret = ubx_dispatch_search (class, id, len_ptr))); + + + return ret; +} + +static int ubx_set_nav_rate (uint16_t ms) +{ + uint8_t buf[6], *ptr; + + ptr = buf; + + ptr += ubx_put_u16 (ptr, ms); + ptr += ubx_put_u16 (ptr, 1); /*1:1*/ + ptr += ubx_put_u16 (ptr, 0); /*UTC*/ + + return ubx_handshake (0x06, 0x08, buf, (unsigned) (ptr - buf)); +} + +static int +ubx_set_message_rate_port1 (uint8_t class, uint8_t id, uint8_t rate) +{ + uint8_t buf[8], *ptr; + + ptr = buf; + + ptr += ubx_put_u8 (ptr, class); + ptr += ubx_put_u8 (ptr, id); //reserved + ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c + ptr += ubx_put_u8 (ptr, rate); //rate on uart + ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 + ptr += ubx_put_u8 (ptr, 0); //nothing on usb + ptr += ubx_put_u8 (ptr, 0); //nothing on spi + ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 + + return ubx_handshake (0x06, 0x01, buf, (unsigned) (ptr - buf)); +} + + +static int +ubx_cfg_rst (uint16_t flags) +{ + uint8_t buf[8], *ptr; + + ptr = buf; + + ptr += ubx_put_u16 (ptr, flags); //Flags + ptr += ubx_put_u8 (ptr, 0x4); //Hardware reset after shutdown + ptr += ubx_put_u8 (ptr, 0); //reserved + + ubx_send (0x06, 0x04, buf, (unsigned) (ptr - buf)); + return 0; +} + + +static int +gps_set_ref (int ref_hz) +{ + uint8_t buf[80], *ptr; + int ret; + + printf ("setting gps ref to %d hz\r\n", ref_hz); + + current_ref_hz = ref_hz; + + ptr = buf; + + ptr += ubx_put_u8 (ptr, 0); //timepluse 1 + ptr += ubx_put_u8 (ptr, 0); //version 0 + ptr += ubx_put_u16 (ptr, 0); //reserved + + // ptr += ubx_put_u16 (ptr, 32); //ant cable delay ns + ptr += ubx_put_u16 (ptr, 0); //ant cable delay ns + ptr += ubx_put_u16 (ptr, 0); //rf group delay ns + ptr += ubx_put_u32 (ptr, 1000000 / ref_hz); //period unlocked/us + ptr += ubx_put_u32 (ptr, 1000000 / ref_hz); //period locked/us + + // ptr += ubx_put_u32 (ptr, 0); //pulse width unlocked/us + ptr += ubx_put_u32 (ptr, 100000 / ref_hz); //pulse width unlocked/us + ptr += ubx_put_u32 (ptr, 100000 / ref_hz); //pulse width locked/us + + ptr += ubx_put_i32 (ptr, 0); // ? delay + +#if 0 + /*Separate numbers for locked/unlocked*/ + ptr += ubx_put_u32 (ptr, 0xf7); +#else + /*Same numbers for locked/unlocked*/ + ptr += ubx_put_u32 (ptr, 0xf7); +#endif + + + ret = ubx_handshake (0x06, 0x31, buf, (unsigned) (ptr - buf)); + + return ret; +} + + +static inline int +ubx_put_gnss_cfg (uint8_t *buf, uint8_t gnss_id,uint8_t r_chan,uint8_t m_chan, +uint16_t enable, uint16_t sig_mask) +{ + uint8_t *ptr=buf; + + ptr += ubx_put_u8(ptr,gnss_id); + ptr += ubx_put_u8(ptr,r_chan); + ptr += ubx_put_u8(ptr,m_chan); + ptr += ubx_put_u8(ptr,0); + ptr += ubx_put_u16(ptr,enable); + ptr += ubx_put_u16(ptr,sig_mask); + + return (unsigned) (ptr - buf); +} + +void gps_set_gnss(void) +{ + uint8_t buf[80], *ptr; + + ptr = buf; + ptr += ubx_put_u8 (ptr, 0x0); /* Ver 0 */ + ptr += ubx_put_u8 (ptr, 0x20); + ptr += ubx_put_u8 (ptr, 0x20); + ptr += ubx_put_u8 (ptr, 0x7); + + ptr += ubx_put_gnss_cfg(ptr,0,8,16,1,0x101); + ptr += ubx_put_gnss_cfg(ptr,1,1,3,1,0x101); + ptr += ubx_put_gnss_cfg(ptr,2,4,8,0,0x101); + ptr += ubx_put_gnss_cfg(ptr,3,8,16,0,0x101); + ptr += ubx_put_gnss_cfg(ptr,4,0,7,0,0x301); + ptr += ubx_put_gnss_cfg(ptr,5,0,3,1,0x501); + ptr += ubx_put_gnss_cfg(ptr,6,8,14,1,0x101); + + ubx_handshake (0x06, 0x3e, buf, (unsigned) (ptr - buf)); + + printf ("configured SBAS\r\n"); + + ubx_handshake (0x06, 0x3e, buf, 0); +} + + +int +gps_init (void) +{ + uint8_t buf[80], *ptr; + unsigned len; + // uint16_t u2; + + usart1_drain(); + + while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring)) + gps_dispatch(); + + + printf ("Testing GNSS...\r\n"); + ubx_handshake (0x06, 0x00, NULL, 0); + printf ("GNSS there\r\n"); + + //reset GNSS + +#if 0 + ptr=buf; + ptr += ubx_put_u32 (ptr, 0xe1f ); //uart1 + ptr += ubx_put_u32 (ptr, 0 ); //uart1 + ptr += ubx_put_u32 (ptr, 0 ); //uart1 + ubx_handshake (0x06, 0x09, buf, (unsigned) (ptr - buf)); + + printf ("reset\r\n"); +#endif + + + // Set up port + ptr = buf; + ptr += ubx_put_u8 (ptr, 1); //uart1 + ptr += ubx_put_u8 (ptr, 0); //reserved + ptr += ubx_put_u16 (ptr, 0x0); //flow control off + ptr += ubx_put_u32 (ptr, 0x8c0); //no parity, 8 bits + ptr += ubx_put_u32 (ptr, 9600); // baudrate + ptr += ubx_put_u16 (ptr, 0x7); // receive RTCM, NMEA, UBX + ptr += ubx_put_u16 (ptr, 0x1); // transmit UBX + ptr += ubx_put_u16 (ptr, 0x0); // no txtimeout + ptr += ubx_put_u16 (ptr, 0x0); // reserved + ubx_handshake (0x06, 0x00, buf, (unsigned) (ptr - buf)); + + printf ("configured GNSS protocol\r\n"); + + +#if 0 + ptr = buf; + ptr += ubx_put_u16 (ptr, 0x1b); + ptr += ubx_put_u16 (ptr, 0x00); + ubx_handshake (0x06, 0x13, buf, (unsigned) (ptr - buf)); + + printf ("configured antenna pins\r\n"); +#endif + + + +#if 0 + // Check we're in WGS84 + ptr = ubx_fetch (0x06, 0x06, NULL, 0, &len); + ptr += ubx_get_u16 (ptr, &u2); + + if (u2) + return -1; + + printf ("configured GNSS datum\r\n"); +#endif + + ptr = buf; + + ptr += ubx_put_u8 (ptr, 0); //UBX + ptr += ubx_put_u8 (ptr, 0); //reserved + ptr += ubx_put_u16 (ptr, 0); //reserved + ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c + ptr += ubx_put_u8 (ptr, 0x18); //everything on uart + ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 + ptr += ubx_put_u8 (ptr, 0); //nothing on usb + ptr += ubx_put_u8 (ptr, 0); //nothing on spi + ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 + + ptr += ubx_put_u8 (ptr, 1); //NMEA + ptr += ubx_put_u8 (ptr, 0); //reserved + ptr += ubx_put_u16 (ptr, 0); //reserved + ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c + ptr += ubx_put_u8 (ptr, 0); //nothing on uart + ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 + ptr += ubx_put_u8 (ptr, 0); //nothing on usb + ptr += ubx_put_u8 (ptr, 0); //nothing on spi + ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 + + ubx_handshake (0x06, 0x02, buf, (unsigned) (ptr - buf)); + + printf ("configured GNSS data\r\n"); + + gps_set_ref (1); + + ubx_fetch (0x06, 0x31, NULL, 0, &len); + + printf ("configured GNSS 6.31\r\n"); + + + ubx_set_nav_rate(1000); + +#if 1 + ubx_set_message_rate_port1 (0x01, 0x03, 1); + ubx_set_message_rate_port1 (0x01, 0x21, 1); + ubx_set_message_rate_port1 (0x01, 0x22, 1); + ubx_set_message_rate_port1 (0x01, 0x32, 0); + + ubx_set_message_rate_port1 (0x01, 0x32, 0); /*SBAS*/ + ubx_set_message_rate_port1 (0x01, 0x35, 0); /*SV in view*/ + + ubx_set_message_rate_port1 (0x03, 0x0a, 0); + ubx_set_message_rate_port1 (0x03, 0x10, 0); + ubx_set_message_rate_port1 (0x03, 0x21, 0); + ubx_set_message_rate_port1 (0x04, 0x04, 0); + + printf ("GNSS ready\r\n"); +#else + ubx_set_message_rate_port1 (0x01, 0x03, 0); + ubx_set_message_rate_port1 (0x01, 0x21, 0); + ubx_set_message_rate_port1 (0x01, 0x22, 0); + ubx_set_message_rate_port1 (0x01, 0x32, 0); + ubx_set_message_rate_port1 (0x03, 0x0a, 0); + //ubx_set_message_rate_port1 (0x03, 0x10, 0); + printf ("GNSS ready\r\n"); +#endif + + + + // printf ("GPS ready\r\n"); + // ubx_get_clock_stats(); + + MAP_INPUT (PPS); + + exti_select_source (EXTI9, PPS_PORT); + exti_set_trigger (EXTI9, EXTI_TRIGGER_BOTH); + exti_enable_request (EXTI9); + nvic_enable_irq (NVIC_EXTI9_5_IRQ); + + return 0; +} + + +#define ALMANAC_LUMP 64 + +int +gps_almanac (void) +{ + uint32_t len = almanac_alp_len; + const uint8_t *ptr = almanac_alp; + uint32_t lumpsz; + uint8_t dummy; + + printf ("Downloading GPS almanac %x %x %x\r\n", (int) ptr[0], (int) ptr[1], + (int) ptr[2]); + + + while (len) { + printf ("%d bytes to go\r\n", (int) len); + + lumpsz = len > ALMANAC_LUMP ? ALMANAC_LUMP : len; + + ubx_handshake_xfer (0x0b, 0x50, ptr, lumpsz); + + ptr += lumpsz; + len -= lumpsz; + + } + + ubx_handshake_xfer (0x0b, 0x50, &dummy, 1); + + return 0; +} + +void gps_dump_almanac(void) +{ + ubx_send (0xb, 0x30, NULL,0); +} + + +#if 0 +int gps_bs(void) +{ + uint32_t now = HW_CLOCK_REG; + uint64_t abs = ref_extend (now); + EPOCH e = ref_decompose (abs); + UTC u = time_epoch_to_utc (e); + + uint8_t buf[80], *ptr; + int ret; + + ptr = buf; + + ptr += ubx_put_u32 (ptr, 391706007); /*19 sleaford st*/ + ptr += ubx_put_u32 (ptr, 955140); + ptr += ubx_put_u32 (ptr, 501672842); + ptr += ubx_put_u32 (ptr, 100000); /*1km std dev*/ + + ptr += ubx_put_u16 (ptr, 0); /*no time mark*/ + + ptr += ubx_put_u16 (ptr, (u.year-2000)*100 + u.month); + ptr += ubx_put_u32 (ptr, (u.mday*1000000) + (u.hour*10000) + (u.minute *100) +u.second); + ptr += ubx_put_u32 (ptr, u.nanosecond); + + ptr += ubx_put_u32 (ptr, 2000); /* time good to 2s */ + ptr += ubx_put_u32 (ptr, 0); + + ptr += ubx_put_u32 (ptr, 0); + ptr += ubx_put_u32 (ptr, 0); + + ptr += ubx_put_u32 (ptr, 0x403); + + printf("Bootstrapping GPS\r\n"); + + hexdump (buf, (unsigned) (ptr-buf)); + + ubx_send (0x0b, 0x01, buf, (unsigned) (ptr - buf)); + + + ret = 0; + + +/* + 00000: 97 f5 58 17 + 04 93 0e 00 + 8a eb e6 1d + a0 86 01 00 + 00010: 00 00 + 6f 07 19/03 + 03 cb 06 01 /17 22:24:03 + 65 ca af 02 45075045ns + + d0 07 00 00 2000ms + 00020: 00 00 00 00 0ns + 00 00 00 00 + 00 00 00 00 + 03 04 00 00 +*/ + + return ret; +} + +#endif + +int gps_bs(void) +{ + uint32_t now = HW_CLOCK_REG; + uint64_t abs = ref_extend (now); + EPOCH e = ref_decompose (abs); + UTC u = time_epoch_to_utc (e); + + uint8_t buf[80], *ptr; + int ret; + + ptr = buf; + + ptr += ubx_put_u8 (ptr, 0x0); + ptr += ubx_put_u8 (ptr, 0x0); + ptr += ubx_put_u8 (ptr, 0x0); + ptr += ubx_put_u8 (ptr, 0x0); + + ptr += ubx_put_u32 (ptr, 391706007); /*19 sleaford st*/ + ptr += ubx_put_u32 (ptr, 955140); + ptr += ubx_put_u32 (ptr, 501672842); + ptr += ubx_put_u32 (ptr, 100000); /*1km std dev*/ + + hexdump (buf, (unsigned) (ptr-buf)); + ubx_send (0x13, 0x40, buf, (unsigned) (ptr-buf)); + + + ptr = buf; + + ptr += ubx_put_u8 (ptr, 0x10); + ptr += ubx_put_u8 (ptr, 0x0); + ptr += ubx_put_u8 (ptr, 0x0); + ptr += ubx_put_u8 (ptr, 0x80); + + ptr += ubx_put_u16 (ptr,u.year-2000); + ptr += ubx_put_u8 (ptr,u.month); + ptr += ubx_put_u8 (ptr,u.mday); + + ptr += ubx_put_u8 (ptr,u.hour); + ptr += ubx_put_u8 (ptr,u.minute); + ptr += ubx_put_u8 (ptr,u.second); + ptr += ubx_put_u8 (ptr,0); + + ptr += ubx_put_u32 (ptr,u.nanosecond); + + ptr += ubx_put_u16 (ptr, 2); /* time good to 2s */ + ptr += ubx_put_u8 (ptr,0); + ptr += ubx_put_u8 (ptr,0); + + ptr += ubx_put_u32 (ptr, 0); + + hexdump (buf, (unsigned) (ptr-buf)); + ubx_send (0x13, 0x40, buf, (unsigned) (ptr-buf)); + + + ret = 0; + + return ret; +} + + +void +gps_reset (void) +{ + printf ("Restting gps..\r\n"); + +#define REPHEMERIDIES (1UL << 0) +#define RALMANAC (1UL << 1) +#define RPOS (1UL << 4) +#define RRTC (1UL << 8) + + ubx_cfg_rst (REPHEMERIDIES | RALMANAC | RPOS | RRTC); + + delay_ms (1000); + usart1_drain(); + + + printf ("Testing GNSS...\r\n"); + ubx_handshake (0x06, 0x00, NULL, 0); + printf ("GNSS there\r\n"); + + gps_init(); + + gps_set_ref (current_ref_hz); + + gps_set_gnss(); +} + +#if 0 +static int +ubx_get_clock_stats (void) +{ + uint8_t *ptr; + + unsigned len; + + ptr = ubx_fetch (0x01, 0x22, NULL, 0, &len); + + //return ubx_recv_clock_stats(ptr,len); + return ptr ? 0 : -1; +} +#endif diff --git a/app/Makefile b/app/Makefile index 4a007a6..526a58f 100644 --- a/app/Makefile +++ b/app/Makefile @@ -19,14 +19,14 @@ CPROTO=cproto -PROG=roofclock +PROG=clockv2 LDSCRIPT = ${PROG}.ld V=1 default: ${PROG}.elf -CSRCS=led.c ticker.c ring.c usart.c stdio.c lwip_glue.c steth.c msf.c abs.c pll.c main.c time_fn.c ntp.c dcf77.c util.c stats.c gps.c hexdump.c bits.c max7219.c report.c sysclk.c cdcacm.c usb.c dfu.c +CSRCS=led.c ticker.c ring.c usart.c stdio.c lwip_glue.c steth.c msf.c abs.c pll.c main.c time_fn.c ntp.c dcf77.c util.c stats.c gps.c hexdump.c bits.c max7219.c report.c sysclk.c cdcacm.c usb.c dfu.c adc.c dummy_kb.c ref.c ptp.c HSRCS= events.h gps.h project.h ring.h steth.h time_fn.h ubx.h @@ -70,7 +70,7 @@ OBJS=${MYOBJS} ${LWIP_OBJS} include ../Makefile.include CFLAGS+=-Wno-redundant-decls -Wno-unused-parameter -CPPFLAGS += -I.. -I../libopencm3-local -I${LWIP_PATH}/${LWIP}/src/include -Ilwip -I${LWIP_PATH}/${LWIP}/src/include/ipv4 -I${LWIP_LOCAL}/port/stm32f4x7 -I. +CPPFLAGS += -I.. -I. -I../libopencm3-local -Ilwip -I${LWIP_PATH}/${LWIP}/src/include -I${LWIP_PATH}/${LWIP}/src/include/ipv4 -I${LWIP_LOCAL}/port/stm32f4x7 LDLIBS+= -lm @@ -81,7 +81,6 @@ fish: ${OBJS} #HOST=clock-lnx #HOST=10.32.91.140 HOST=tick -HOST=10.32.96.46 reset: @@ -91,33 +90,19 @@ reset: -c shutdown - -test-dfu: ${PROG}.dfu - ../dfu-util/src/dfu-util -v -R -a 0 -d ${VID}:${DID} -s 0x08004000:leave -D $< - $(Q)$(OOCD) -f ../oocd/interface/$(OOCD_INTERFACE).cfg \ - -f ../oocd/board/$(OOCD_BOARD).cfg \ - -c "init" -c "dump_image readback.img 0x8004000 0x7c000" \ - -c shutdown - - hexdump -C ${PROG}.dfu > a - hexdump -C readback.img> b - diff -uN a b > c - - fl: ${PROG}.hex ssh ${HOST} flash_stm32 < ${PROG}.hex -DID=$(shell printf '\#include "id.h"\nID_PRODUCT' | ${CC} -I.. -E - | grep -v ^\# ) -VID=$(shell printf '\#include "id.h"\nID_VENDOR' | ${CC} -I.. -E - | grep -v ^\# ) +%.bin: %.elf + $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin +%.dfu:%.bin + ../tools/dfuse-pack.py -D 0x483:0xff03 -b 0x08004000:$< $@ -%.dfu: %.elf - @#printf " OBJCOPY $(*).dfu\n" - $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).dfu +dfu:${PROG}.bin + dfu-util -R -a 0 -d 0483:ff03,0483:df11 -s 0x08004000:leave -D $< -dfu:${PROG}.dfu - dfu-util -R -a 0 -d ${VID}:${DID} -s 0x08004000:leave -D $< program: ${PROG}.hex diff --git a/app/abs.c b/app/abs.c index 7a6b5d5..636b721 100644 --- a/app/abs.c +++ b/app/abs.c @@ -1,124 +1,3 @@ #include "project.h" -static uint32_t high_tick; - -#if HW_CLOCK_LEN == 32 - -#define QUARTER (1UL << 29) -#define HALF (1UL << 30) -#define THREE_QUARTERS (HALF+QUARTER) -#define ONE (~(uint32_t)0) - - -uint64_t abs_extend (uint32_t now) -{ - static int m; - uint64_t ret; - - - if (!m) { - ret = high_tick; - ret <<= 32; - ret |= now; - - - if ((now > THREE_QUARTERS) && (now <= ONE)) { - high_tick++; - m = 1; - } - - } else { - if (now < HALF) { - ret = high_tick; - ret <<= 32; - ret |= now; - } else { - ret = high_tick - 1; - ret <<= 32; - ret |= now; - } - - if ((now > QUARTER) && (now < HALF)) - m = 0; - } - - return ret; -} -#elif HW_CLOCK_LEN == 31 - -#define QUARTER (1UL << 28) -#define HALF (1UL << 29) -#define THREE_QUARTERS (HALF+QUARTER) -#define ONE (0x7fffffff) - - -uint64_t abs_extend (uint32_t now) -{ - static int m; - uint64_t ret; - - - if (!m) { - ret = high_tick; - ret <<= 31; - ret |= now; - - if ((now > THREE_QUARTERS) && (now <= ONE)) { - high_tick++; - m = 1; - } - - } else { - if (now < HALF) { - ret = high_tick; - ret <<= 31; - ret |= now; - } else { - ret = high_tick - 1; - ret <<= 31; - ret |= now; - } - - if ((now > QUARTER) && (now < HALF)) - m = 0; - } - - return ret; -} - - - - - -#else -#error unknown hardware clock length -#endif - - - - - - - - -void abs_meh (void) -{ - printf ("HT %d\n", (int) high_tick); -} - - - - - -uint64_t abs_get (void) -{ - uint32_t now = HW_CLOCK_REG; - return abs_extend (now); -} - - -void abs_slow_tick() -{ - abs_get(); -} diff --git a/app/adc.c b/app/adc.c new file mode 100644 index 0000000..821bac9 --- /dev/null +++ b/app/adc.c @@ -0,0 +1,137 @@ +#include "project.h" + + +#define POT GPIO3 +#define POT_PORT GPIOC + +#define POT_CHANNEL ADC_CHANNEL13 +#define VREF_CHANNEL ADC_CHANNEL17 + +#define ADC_TIMEOUT 1000 + +static enum { + WAIT_VREF, + WAIT_POT +} state = WAIT_VREF; + + +static uint32_t adc_stamp; +static uint16_t pot, vref; + +uint8_t pot_brightness = 0x8; + + +static void start_conversion (uint8_t ch) +{ + adc_stamp = ticks; + adc_set_regular_sequence (ADC1, 1, &ch); + adc_start_conversion_regular (ADC1); +} + +static void calculate_and_set_brightness (void) +{ + static uint32_t spot, svref; + uint32_t v; + + /* dumb IIR with 16x gain */ + spot *= 15; + spot >>= 4; + spot += pot ; + + svref *= 15; + svref >>= 4; + svref += vref ; + + + if (svref > 65535) svref = 65535; + + if (spot > 65535) spot = 65535; + + v = spot << 16; + v /= svref; + v <<= 8; + v /= 12014; // vref is 1.2v FSD is 3.3v, 15 brightness levels so (65536 * (3.3/1.2) /15 ) + + v >>= 8; + + + if (v > 15) v = 15; + + pot_brightness = v; +} + + +void adc_dispatch (void) +{ + uint32_t now = ticks; + uint32_t ago; + + ago = now - adc_stamp; + + if (ago > ADC_TIMEOUT) { + adc_off (ADC1); + adc_power_on (ADC1); + state = WAIT_VREF; + start_conversion (VREF_CHANNEL); + return; + } + + if (!adc_eoc (ADC1)) + return; + + switch (state) { + case WAIT_VREF: + vref = adc_read_regular (ADC1); + start_conversion (POT_CHANNEL); + state = WAIT_POT; + break; + + case WAIT_POT: + pot = adc_read_regular (ADC1); + start_conversion (VREF_CHANNEL); + calculate_and_set_brightness(); + + /* fall through */ + default: + state = WAIT_VREF; + } +} + + + + + + + + + + + + + + +void adc_init (void) +{ + rcc_periph_clock_enable (RCC_ADC1); + + MAP_ANALOG_INPUT (POT); + + adc_off (ADC1); + adc_disable_scan_mode (ADC1); + adc_enable_temperature_sensor(); + + adc_set_single_conversion_mode (ADC1); + adc_enable_temperature_sensor(); /*Enables reference*/ + adc_set_sample_time (ADC1, POT_CHANNEL, ADC_SMPR_SMP_480CYC); + adc_set_sample_time (ADC1, VREF_CHANNEL, ADC_SMPR_SMP_480CYC); + adc_enable_external_trigger_regular (ADC1, 0, ADC_CR2_EXTEN_DISABLED); + adc_set_right_aligned (ADC1); + adc_eoc_after_group (ADC1); + + adc_power_on (ADC1); + adc_enable_temperature_sensor(); /*Enables reference*/ + + state = WAIT_VREF; + start_conversion (VREF_CHANNEL); +} + diff --git a/app/cdcacm.c b/app/cdcacm.c index 213592e..af45ac6 100644 --- a/app/cdcacm.c +++ b/app/cdcacm.c @@ -11,11 +11,15 @@ static uint8_t cdcacm_tx_ring_buf[BUFFER_SIZE]; static int cdcacm_ready = 0; +#define COMM_EP 0x83 +#define DATA_IN 0x01 +#define DATA_OUT 0x82 + static const struct usb_endpoint_descriptor comm_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, + .bEndpointAddress = COMM_EP, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .wMaxPacketSize = 16, .bInterval = 255, @@ -26,7 +30,7 @@ static const struct usb_endpoint_descriptor data_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, + .bEndpointAddress = DATA_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, @@ -34,7 +38,7 @@ static const struct usb_endpoint_descriptor data_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, + .bEndpointAddress = DATA_OUT, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, @@ -59,7 +63,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bmCapabilities = 0, - .bDataInterface = 1, + .bDataInterface = 3, }, .acm = { .bFunctionLength = sizeof (struct usb_cdc_acm_descriptor), @@ -71,15 +75,15 @@ static const struct { .bFunctionLength = sizeof (struct usb_cdc_union_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, + .bControlInterface = 2, + .bSubordinateInterface0 = 3, } }; const struct usb_interface_descriptor comm_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, + .bInterfaceNumber = 2, .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_CDC, @@ -94,7 +98,7 @@ const struct usb_interface_descriptor comm_iface = { const struct usb_interface_descriptor data_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, + .bInterfaceNumber = 3, .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_DATA, @@ -105,21 +109,29 @@ const struct usb_interface_descriptor data_iface = { }; +const struct usb_iface_assoc_descriptor cdc_iface_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 2, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .iFunction = 6, +}; + -static int cdcacm_control_request (usbd_device *usbd_dev, - struct usb_setup_data *req, - uint8_t **buf, - uint16_t *len, - usbd_control_complete_callback *complete) +int cdcacm_control_request (usbd_device *usbd_dev, + struct usb_setup_data *req, + uint8_t **buf, + uint16_t *len, + usbd_control_complete_callback *complete) { (void) complete; (void) buf; (void) usbd_dev; - if (dfu_control_request (usbd_dev, req, buf, len, complete)) - return 1; - switch (req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { @@ -145,7 +157,7 @@ static int cdcacm_control_request (usbd_device *usbd_dev, void cdcacm_tick (void) { - unsigned ep = 0x82; + unsigned ep = DATA_OUT; uint8_t buf[16]; uint8_t *ptr = buf; size_t n = 0; @@ -184,7 +196,7 @@ static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep) { (void) ep; uint8_t buf[64]; - int len = usbd_ep_read_packet (usbd_dev, 0x01, buf, 64); + int len = usbd_ep_read_packet (usbd_dev, DATA_IN, buf, 64); if (len) ring_write (&cdcacm_rx_ring, buf, len, 0); @@ -193,14 +205,10 @@ static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep) void cdcacm_set_config (usbd_device *usbd_dev, uint16_t wValue) { (void) wValue; - usbd_ep_setup (usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); - usbd_ep_setup (usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); - usbd_ep_setup (usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - usbd_register_control_callback (usbd_dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); + usbd_ep_setup (usbd_dev, DATA_IN, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); + usbd_ep_setup (usbd_dev, DATA_OUT, USB_ENDPOINT_ATTR_BULK, 64, NULL); + usbd_ep_setup (usbd_dev, COMM_EP, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); cdcacm_ready = 1; } diff --git a/app/clockv2.ld b/app/clockv2.ld new file mode 100644 index 0000000..325e7ce --- /dev/null +++ b/app/clockv2.ld @@ -0,0 +1,20 @@ +/* Linker script for STM32F407VET6, 512K flash, 192K RAM. */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08004000, LENGTH = 496K + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32f4.ld + +dfu_shared_location = ORIGIN(ram) + LENGTH(ram) - 1024; + +SECTIONS +{ + .dfu_shared dfu_shared_location :{ + dfu_flag = .; + } +} diff --git a/app/dcf77.c b/app/dcf77.c index 71c227c..30cfd26 100644 --- a/app/dcf77.c +++ b/app/dcf77.c @@ -43,6 +43,7 @@ void exti_t_isr (void) exti_reset_request (EXTI_T); dcf77_ring.events[dcf77_ring.tx_ptr].when = now; + dcf77_ring.events[dcf77_ring.tx_ptr].ptp = ptp_get(); dcf77_ring.events[dcf77_ring.tx_ptr].value = v; dcf77_ring.tx_ptr = (dcf77_ring.tx_ptr + 1) & ERING_MASK; @@ -53,7 +54,7 @@ void exti_t_isr (void) static uint8_t bits[60]; -static void process_bits (uint64_t abs) +static void process_bits (uint64_t abs, uint64_t ptp) { UTC u; EPOCH e; @@ -95,7 +96,7 @@ static void process_bits (uint64_t abs) dcf77_last_happy = make_happy (abs, 60); - pll_set_offset (e, abs); + pll_set_offset (e, abs, ptp); @@ -107,7 +108,7 @@ static void process_bits (uint64_t abs) } -static void report_bit (uint64_t abs, int second, int b) +static void report_bit (uint64_t abs, uint64_t ptp, int second, int b) { if ((second < 0) || (second > 58)) return; @@ -115,7 +116,7 @@ static void report_bit (uint64_t abs, int second, int b) // printf("DCF77: bits[%d]=%d\r\n",second,b); - if (second == 58) process_bits (abs); + if (second == 58) process_bits (abs, ptp); } @@ -129,6 +130,7 @@ void dcf77_dispatch (void) int is_s = 0; uint32_t now; + uint64_t ptp; int v; led2_set (!!gpio_get (T_PORT, T)); @@ -139,6 +141,7 @@ void dcf77_dispatch (void) v = dcf77_ring.events[dcf77_ring.rx_ptr].value; now = dcf77_ring.events[dcf77_ring.rx_ptr].when; + ptp = dcf77_ring.events[dcf77_ring.rx_ptr].ptp; //led2_set(v); @@ -176,7 +179,7 @@ void dcf77_dispatch (void) sprintf (dcf77_info, "m=%d s=%02d b=%d", had_m, second, bit); if (had_m) - report_bit (abs, second, bit); + report_bit (abs, ptp, second, bit); last_0 = now; } @@ -185,10 +188,10 @@ void dcf77_dispatch (void) offset /= (HW_CLOCK_HZ / 1000); if (is_s) { - abs = abs_extend (now); + abs = ref_extend (now); dcf77_last_second = abs; - pll_dispatch (dcf77_last_happy, abs, "DCF77"); + pll_dispatch (dcf77_last_happy, abs, ptp, "DCF77"); report_time ("DCF", dcf77_time, abs, dcf77_info); } diff --git a/app/dfu.c b/app/dfu.c index c505585..5aebe34 100644 --- a/app/dfu.c +++ b/app/dfu.c @@ -3,7 +3,7 @@ const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof (struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -12,19 +12,30 @@ const struct usb_dfu_descriptor dfu_function = { const struct usb_interface_descriptor dfu_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 2, + .bInterfaceNumber = 1, .bAlternateSetting = 0, .bNumEndpoints = 0, .bInterfaceClass = 0xFE, .bInterfaceSubClass = 1, .bInterfaceProtocol = 1, .iInterface = 4, - .extra = &dfu_function, .extralen = sizeof (dfu_function), }; +const struct usb_iface_assoc_descriptor dfu_iface_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 1, + .bInterfaceCount = 1, + .bFunctionClass = 0xfe, + .bFunctionSubClass = 1, + .bFunctionProtocol = 1, + .iFunction = 5, +}; + + static int dfu_detach_complete (usbd_device *usbd_dev, struct usb_setup_data *req) { @@ -49,6 +60,8 @@ dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, (void) len; (void) usbd_dev; + printf ("dfu_control_request %02x %02x\n", req->bmRequestType, req->bRequest); + if ((req->bmRequestType & 0x7F) != 0x21) { return 0; /* Only accept class request. */ } diff --git a/app/dummy_kb.c b/app/dummy_kb.c new file mode 100644 index 0000000..a1d61c7 --- /dev/null +++ b/app/dummy_kb.c @@ -0,0 +1,26 @@ +#include "project.h" + +const struct usb_interface_descriptor dummy_kb_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + + +const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 1, + .bFunctionClass = 0xff, + .bFunctionSubClass = 0, + .bFunctionProtocol = 0, + .iFunction = 4, +}; + diff --git a/app/events.h b/app/events.h index 550277d..dc257f9 100644 --- a/app/events.h +++ b/app/events.h @@ -2,6 +2,7 @@ #define ERING_MASK (ERING_SIZE -1) typedef struct { + uint64_t ptp; uint32_t when; uint32_t value; } Event; diff --git a/app/gps.c b/app/gps.c index 206f0c0..f905091 100644 --- a/app/gps.c +++ b/app/gps.c @@ -11,6 +11,14 @@ #define TIMEOUT 4000 +unsigned gps_sats_searching; +unsigned gps_sats_inop; +unsigned gps_sats_locked; +unsigned gps_sats_with_e; +int gps_initting = 1; + +static int chatty_gps = 1; + static EPOCH next_sec; static int ubx_ack = 0; @@ -47,6 +55,7 @@ void exti9_5_isr (void) exti_reset_request (EXTI7); gps_ring.events[gps_ring.tx_ptr].when = now; + gps_ring.events[gps_ring.tx_ptr].ptp = ptp_get(); gps_ring.events[gps_ring.tx_ptr].value = v; gps_ring.tx_ptr = (gps_ring.tx_ptr + 1) & ERING_MASK; @@ -61,7 +70,7 @@ void exti9_5_isr (void) static inline int ubx_recv_byte (uint8_t *v) { - return !ring_read_byte (&rx1_ring, v); + return !ring_read_byte (&usart1_rx_ring, v); } static inline void @@ -311,8 +320,7 @@ ubx_recv_utc (uint8_t *ptr, unsigned len) if (gps_happy > 3) { UTC u; EPOCH gps_time; - uint32_t now; - uint64_t abs; + uint64_t abs, ptp; u.jday = 0; u.year = year; @@ -330,12 +338,12 @@ ubx_recv_utc (uint8_t *ptr, unsigned len) next_sec = gps_time; - now = HW_CLOCK_REG; - abs = abs_extend (now); + abs = ref_get(); + ptp = ptp_get(); gps_last_happy = make_happy (abs, 180); - pll_set_offset (gps_time, abs); + pll_set_offset (gps_time, abs, ptp); } else printf ("!GPS %s\r\n", gps_info); @@ -373,7 +381,7 @@ static int ubx_recv_nav_sbas (uint8_t *ptr, unsigned len) int8_t sys; uint8_t n; - if (!chatty_gps) return0 ; + if (!chatty_gps) return 0 ; ptr += ubx_get_u32 (ptr, &d4); ptr += ubx_get_u8 (ptr, &prn); @@ -411,6 +419,8 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len) ptr += ubx_get_u8 (ptr, &flags); ptr += ubx_get_u16 (ptr, &d2); + gps_sats_searching = gps_sats_inop = gps_sats_locked = gps_sats_with_e = 0; + while (n--) { ptr += ubx_get_u8 (ptr, &ch); ptr += ubx_get_u8 (ptr, &svid); @@ -419,6 +429,7 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len) ptr += ubx_get_u8 (ptr, &cno); ptr += 7; + switch (quality) { case 0: st = "idle"; @@ -426,30 +437,44 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len) case 1: st = "search"; + gps_sats_searching++; break; case 2: st = "acq"; + gps_sats_searching++; break; case 3: st = "inop"; + gps_sats_inop++; break; case 4: st = "lock"; + gps_sats_locked++; + + if (cflags & 0x04) + gps_sats_with_e++; + break; case 5: case 6: case 7: st = "good"; + gps_sats_locked++; + + if (cflags & 0x04) + gps_sats_with_e++; + break; default: st = "?"; } + printf ("GPS SVID:%3d C/N:%3d %c%c%c %s\r\n", svid, cno, (cflags & 0x01) ? 'U' : '-', @@ -743,6 +768,7 @@ static void gps_pps_dispatch (void) //char buf[80]; uint32_t now; uint64_t abs; + uint64_t ptp; int v; //EPOCH e; //UTC u; @@ -751,6 +777,7 @@ static void gps_pps_dispatch (void) v = gps_ring.events[gps_ring.rx_ptr].value; now = gps_ring.events[gps_ring.rx_ptr].when; + ptp = gps_ring.events[gps_ring.rx_ptr].ptp; if (gps_happy) led3_set (v); @@ -761,14 +788,16 @@ static void gps_pps_dispatch (void) if (!v) return; - abs = abs_extend (now); + abs = ref_extend (now); - if (gps_happy > 30) - pll_dispatch (gps_last_happy, abs, "GPS"); + if (gps_happy > 30) { + chatty_gps = 0; + pll_dispatch (gps_last_happy, abs, ptp, "GPS"); + } - //e = pll_decompose (abs); + //e = ref_decompose (abs); //u = time_epoch_to_utc (e); @@ -896,7 +925,7 @@ ubx_fetch (uint8_t class, uint8_t id, void *payload, unsigned len, { uint8_t *ret; - while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring)) + while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring)) gps_dispatch(); ubx_send (class, id, payload, len); @@ -1090,7 +1119,7 @@ gps_init (void) usart1_drain(); - while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring)) + while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring)) gps_dispatch(); @@ -1195,6 +1224,7 @@ gps_init (void) // ubx_aid_ini (522202400, 1279080, 2900, 20000); printf ("GNSS ready\r\n"); + gps_initting = 0; #else ubx_set_message_rate_port1 (0x01, 0x03, 0); ubx_set_message_rate_port1 (0x01, 0x21, 0); @@ -1267,8 +1297,8 @@ void gps_dump_almanac (void) int gps_bs (void) { uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - EPOCH e = pll_decompose (abs); + uint64_t abs = ref_extend (now); + EPOCH e = ref_decompose (abs); UTC u = time_epoch_to_utc (e); uint8_t buf[80], *ptr; diff --git a/app/gps_neo8.c b/app/gps_neo8.c deleted file mode 100644 index 9da5438..0000000 --- a/app/gps_neo8.c +++ /dev/null @@ -1,1204 +0,0 @@ -#include "project.h" - -#define PPS (GPIO9) -#define PPS_PORT GPIOC - -#define UBX_BUF_LEN 256 - -#define TIMEOUT 4000 - -static int ubx_ack = 0; -static int ubx_ack_xfer = 0; - -static int current_ref_hz = 1; - -static int gps_locked; -static int gps_happy; - -uint64_t gps_last_happy; - -static char fix, fix2; -static int32_t freq = 0; - -static const int fish[] = { 1, 2, 3, 4, 5, 6, 7 }; - -static Event_ring gps_ring; - -static char gps_info[60]; - - -void exti9_5_isr (void) -{ - uint32_t now = HW_CLOCK_REG; - int v; - - v = !!gpio_get (PPS_PORT, PPS); - - nvic_disable_irq (NVIC_EXTI9_5_IRQ); - exti_reset_request (EXTI9); - - gps_ring.events[gps_ring.tx_ptr].when = now; - gps_ring.events[gps_ring.tx_ptr].value = v; - gps_ring.tx_ptr = (gps_ring.tx_ptr + 1) & ERING_MASK; - - nvic_enable_irq (NVIC_EXTI9_5_IRQ); - -} - - - -static inline int -ubx_recv_byte (uint8_t *v) -{ - return !ring_read_byte (&rx1_ring, v); -} - -static inline void -ubx_send_byte (uint8_t v) -{ - usart1_queue (v); -} - -#define ALMANAC_SIZE - -static int ubx_recv_almanac(uint8_t *ptr,unsigned len) -{ -uint32_t sv,week; -uint32_t almanac[8]; - -ptr+=ubx_get_u32(ptr,&sv); -len-=4; -ptr+=ubx_get_u32(ptr,&week); -len-=4; - -if (len>sizeof(almanac)) - len=sizeof(almanac); - -bzero(almanac,sizeof(almanac)); -memcpy(almanac,ptr,len); - -printf(" Almanac: %2d %d %06x %06x %06x %06x %06x %06x %06x %06x\r\n", - (int) sv,(int) week, - (unsigned) almanac[0], - (unsigned) almanac[1], - (unsigned) almanac[2], - (unsigned) almanac[3], - (unsigned) almanac[4], - (unsigned) almanac[5], - (unsigned) almanac[6], - (unsigned) almanac[7]); - -return 0; -} - -static int -ubx_recv_nav_status (uint8_t *ptr, unsigned len) -{ - uint8_t gps_fix, flags,fix_stat,flags2; - uint32_t d; - - if ((!ptr) || (len != 16)) - return -1; - - ptr += ubx_get_u32 (ptr, &d); //TOW - ptr += ubx_get_u8 (ptr, &gps_fix); //fix type - ptr += ubx_get_u8 (ptr, &flags); //fix type - ptr += ubx_get_u8 (ptr, &fix_stat); - ptr += ubx_get_u8 (ptr, &flags2); - - - switch (gps_fix) { - case 0: - case 1: - fix = '-'; - gps_locked = 0; - break; - - case 2: - fix = '2'; - gps_locked = 0; - break; - - case 3: - fix = 'L'; - gps_locked = 1; - break; - - case 4: - fix = 'R'; - gps_locked = 0; - break; - - case 5: - fix = 'T'; - gps_locked = 0; - break; - - default: - fix = '?'; - gps_locked = 0; - } - - switch (flags & 3) { - case 0: - case 2: - fix2 = '!'; - break; - - case 1: - fix2 = '-'; - break; - - case 3: - fix2 = 'D'; - - if (gps_locked == 1) - gps_locked = 2; - - break; - - default: - fix2 = '?'; - } - - - // printf ("fix: %c%c\r\n",fix,fix2); - - - if ((gps_locked) && (gps_happy < 10000)) - gps_happy++; - else - gps_happy = 0; - - return 0; -} - - -static int -ubx_recv_clock_stats (uint8_t *ptr, unsigned len) -{ - //char buf[40]; - int32_t drift; - uint32_t d; - - if ((!ptr) || (len != 20)) - return -1; - - ptr += ubx_get_u32 (ptr, &d); //TOW - ptr += ubx_get_u32 (ptr, &d); //bias - ptr += ubx_get_i32 (ptr, &drift); //drift - ptr += ubx_get_u32 (ptr, &d); //time acc estimate - ptr += ubx_get_i32 (ptr, &freq); //freq acc estimate - - // printf ("TCXO %+8dE-12\r\n", (int) freq); -#if 0 - sprintf (buf, "TCXO %+8dE-12", (int) freq); - lcd_erase_line (18, 0); - lcd_write (buf, 0, 0); -#endif - return 0; - -} - -static int -ubx_recv_utc (uint8_t *ptr, unsigned len) -{ - int32_t nano; - uint32_t acc; - uint16_t year; - uint8_t hour, min, sec, day, month,valid; - uint32_t d; - // char buf[40]; - - if ((!ptr) || (len != 20)) - return -1; - - ptr += ubx_get_u32 (ptr, &d); //TOW - ptr += ubx_get_u32 (ptr, &acc); //bias - ptr += ubx_get_i32 (ptr, &nano); - ptr += ubx_get_u16 (ptr, &year); - ptr += ubx_get_u8 (ptr, &month); - ptr += ubx_get_u8 (ptr, &day); - ptr += ubx_get_u8 (ptr, &hour); - ptr += ubx_get_u8 (ptr, &min); - ptr += ubx_get_u8 (ptr, &sec); - ptr += ubx_get_u8 (ptr, &valid); - -#if 0 - printf ("GPS META-DATA %04d-%02d-%02d %02d:%02d:%02d V:%02x Fix:%c%c TXCO %+8dE-12\r\n", - (int) year, - (int) month, - (int) day, - (int) hour, - (int) min, - (int) sec, - (unsigde) valid, - fix, fix2, (int) freq); -#endif - - sprintf(gps_info, " %04d-%02d-%02d %02d:%02d:%02d V:%02x Fix:%c%c TXCO %+8dE-12", - - (int )year, - (int )month, - (int )day, - (int )hour, - (int )min, - (int )sec, -(unsigned) valid, fix, fix2, (int) freq); - - - - if (gps_happy > 3) { - UTC u; - EPOCH gps_time; - uint32_t now; - uint64_t abs; - - u.jday = 0; - u.year = year; - u.month = month; - u.mday = day; - u.hour = hour; - u.minute = min; - u.second = sec; - u.nanosecond = 0; - - gps_time = time_utc_to_epoch (u); - - - now = HW_CLOCK_REG; - abs = abs_extend (now); - - gps_last_happy = make_happy (abs, 180); - - pll_set_offset (gps_time, abs); - - } - - -#if 0 - sprintf (buf, "%+6dE-12 %02d%02d%02d", (int) freq, - (int) hour, (int)min, (int) sec); - lcd_erase_line (18, 0); - lcd_write (buf, 0, 0); -#endif - - return 0; -} - - - -static int ubx_recv_nav_sbas(uint8_t *ptr,unsigned len) -{ -uint8_t prn,mode,service; -int8_t sys; -uint8_t n; - - ptr+=4; - - ptr += ubx_get_u8 (ptr, &prn); - ptr += ubx_get_u8 (ptr, &mode); - ptr += ubx_get_i8 (ptr, &sys); - ptr += ubx_get_u8 (ptr, &service); - - ptr += ubx_get_u8 (ptr, &n); - ptr+=3; - - printf("GPS SBAS PRN:%d M:%d S:%d SVC:%02x\r\n",prn,mode,sys,service); - - while (n--) { - ptr += ubx_get_u8 (ptr, &prn); - ptr+=11; - printf("GPS SBAS SV:%d\r\n",prn); - } - -return 0; -} - -static int ubx_recv_nav_sat(uint8_t *ptr,unsigned len) -{ -uint8_t gnssid,prn,cno,ver; -uint8_t n; - - ptr+=4; - - ptr += ubx_get_u8 (ptr, &ver); - ptr += ubx_get_u8 (ptr, &n); - ptr+=2; - - while (n--) { - ptr += ubx_get_u8 (ptr, &gnssid); - ptr += ubx_get_u8 (ptr, &prn); - ptr += ubx_get_u8 (ptr, &cno); - ptr+=9; - - printf("GPS GNSS:%2d PRN:%3d CNO:%3d\r\n",gnssid,prn,cno); - } - - -return 0; -} - - -static int ubx_recv_rinex (uint8_t *payload, unsigned len) -{ - - printf ("Rinex\r\n"); - return 0; -} - - - -static void -ubx_recv (uint8_t class, uint8_t id, uint8_t *payload, unsigned len) -{ - // printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); - - switch (class) { - case 1: - switch (id) { - case 0x3: - ubx_recv_nav_status (payload, len); - break; - - case 0x21: - ubx_recv_utc (payload, len); - break; - - case 0x22: - ubx_recv_clock_stats (payload, len); - break; - - case 0x32: - ubx_recv_nav_sbas(payload,len); - break; - - case 0x35: - ubx_recv_nav_sat(payload,len); - break; - - default: - printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); - hexdump (payload, len); - } - - break; - - case 2: - switch (id) { - case 0x10: - ubx_recv_rinex (payload, len); - - break; - } - - break; - - case 4: - switch (id) { - case 0x4: - break; - default: - printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); - hexdump (payload, len); - } - - break; - - - - case 5: - ubx_ack++; - printf (" %s for %02x.%02x\r\n", id ? "ACK" : "NAK", payload[0], - payload[1]); - - break; - - case 0x0b: - switch (id) { - case 0x30: - ubx_recv_almanac(payload,len); - break; - case 0x50: - printf ("xfer ack\r\n"); - ubx_ack_xfer++; - break; - - default: - printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); - hexdump (payload, len); - } - - break; - - default: - printf ("RX> %02x.%02x (%d bytes)\r\n", class, id, len); - - if (class != 0x03) - hexdump (payload, len); - } - - -} - - -typedef enum { - UBX_SM_LOST = 0, - UBX_SM_S2, - UBX_SM_C, - UBX_SM_I, - UBX_SM_L1, - UBX_SM_L2, - UBX_SM_DATA, - UBX_SM_CKA, - UBX_SM_CKB -} ubx_sm_t; - - - - -static uint8_t * -ubx_dispatch_search (int s_class, int s_id, unsigned *len_ptr) -{ - static uint8_t buf[UBX_BUF_LEN]; - static ubx_sm_t sm = UBX_SM_LOST; - static uint8_t class, id; - static unsigned ptr; - static unsigned len; - static uint8_t ck_a, ck_b; - - - void ubx_ck (uint8_t v) { - ck_a += v; - ck_b = ck_b + ck_a; - } - - - uint8_t c; - - while (ubx_recv_byte (&c)) { - - switch (sm) { - case UBX_SM_LOST: - if (c == 0xb5) - sm = UBX_SM_S2; - - break; - - case UBX_SM_S2: - if (c == 0x62) - sm = UBX_SM_C; - else - sm = UBX_SM_LOST; - - break; - - case UBX_SM_C: - ck_a = ck_b = class = c; - sm = UBX_SM_I; - break; - - case UBX_SM_I: - ubx_ck (c); - id = c; - sm = UBX_SM_L1; - break; - - case UBX_SM_L1: - ubx_ck (c); - len = c; - sm = UBX_SM_L2; - break; - - case UBX_SM_L2: - ubx_ck (c); - len |= c << 8; - - ptr = 0; - - if (len) - sm = UBX_SM_DATA; - else - sm = UBX_SM_CKA; - - break; - - case UBX_SM_DATA: - ubx_ck (c); - - if (ptr < UBX_BUF_LEN) - buf[ptr] = c; - - ptr++; - - if (ptr == len) - sm = UBX_SM_CKA; - - break; - - case UBX_SM_CKA: - if (c == ck_a) - sm = UBX_SM_CKB; - else - sm = UBX_SM_LOST; - - break; - - case UBX_SM_CKB: - sm = UBX_SM_LOST; - - if (c != ck_b) - break; - - ubx_recv (class, id, buf, len); - - if ((class == s_class) && (id == s_id)) { - if (len_ptr) - *len_ptr = len; - - return buf; - } - - break; - } - - } - - return NULL; -} -static void gps_pps_dispatch (void) -{ - //char buf[80]; - uint32_t now; - uint64_t abs; - int v; - EPOCH e; - //UTC u; - - if (gps_ring.rx_ptr == gps_ring.tx_ptr) return; - - v = gps_ring.events[gps_ring.rx_ptr].value; - now = gps_ring.events[gps_ring.rx_ptr].when; - - led3_set(v); - - gps_ring.rx_ptr = (gps_ring.rx_ptr + 1) & ERING_MASK; - - - if (!v) return; - - abs = abs_extend (now); - - if (gps_happy) - pll_dispatch (gps_last_happy, abs, "GPS"); - - e = pll_decompose (abs); - - - //u = time_epoch_to_utc (e); - time_print_epoch ("GPS : ", e, gps_info); - -} - - -void -gps_dispatch (void) -{ - ubx_dispatch_search (-1, -1, NULL); - gps_pps_dispatch(); - -} - -static void -ubx_send (uint8_t class, uint8_t id, const void *_payload, unsigned len) -{ - uint8_t ck_a = 0, ck_b = 0; - uint8_t *payload = (uint8_t *) _payload; - - void ubx_send_byte_ck (uint8_t v) { - ubx_send_byte (v); - ck_a += v; - ck_b = ck_b + ck_a; - } - - - ubx_send_byte (0xb5); - ubx_send_byte (0x62); - - ubx_send_byte_ck (class); - ubx_send_byte_ck (id); - ubx_send_byte_ck (len & 0xff); - ubx_send_byte_ck (len >> 8); - - while (len--) - ubx_send_byte_ck (* (payload++)); - - ubx_send_byte (ck_a); - ubx_send_byte (ck_b); - - // printf ("TX> %02x.%02x\r\n", class, id); - -} - -static int -ubx_handshake (uint8_t class, uint8_t id, const void *payload, unsigned len) -{ - uint32_t timeout; - - ubx_ack = 0; - ubx_send (class, id, payload, len); - - - - timeout = ticks + TIMEOUT; - - while (!ubx_ack) { - - if (ticks > timeout) { - printf ("GPS timeout resending packet\r\n"); - usart1_drain(); - ubx_send (class, id, payload, len); - timeout = ticks + TIMEOUT; - } - - - - - gps_dispatch(); - } - - return 0; -} - -static int -ubx_handshake_xfer (uint8_t class, uint8_t id, const void *payload, - unsigned len) -{ - uint32_t timeout; - - ubx_ack_xfer = 0; - // usart1_drain(); - ubx_send (class, id, payload, len); - - - - timeout = ticks + TIMEOUT; - - while (!ubx_ack_xfer) { - - if (ticks > timeout) { - printf ("GPS timeout resending packet\r\n"); - // usart1_drain(); - ubx_send (class, id, payload, len); - timeout = ticks + TIMEOUT; - } - - - - - gps_dispatch(); - } - - return 0; -} - - - - -static uint8_t * -ubx_fetch (uint8_t class, uint8_t id, void *payload, unsigned len, - unsigned *len_ptr) -{ - uint8_t *ret; - - while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring)) - gps_dispatch(); - - ubx_send (class, id, payload, len); - - while (! (ret = ubx_dispatch_search (class, id, len_ptr))); - - - return ret; -} - -static int ubx_set_nav_rate (uint16_t ms) -{ - uint8_t buf[6], *ptr; - - ptr = buf; - - ptr += ubx_put_u16 (ptr, ms); - ptr += ubx_put_u16 (ptr, 1); /*1:1*/ - ptr += ubx_put_u16 (ptr, 0); /*UTC*/ - - return ubx_handshake (0x06, 0x08, buf, (unsigned) (ptr - buf)); -} - -static int -ubx_set_message_rate_port1 (uint8_t class, uint8_t id, uint8_t rate) -{ - uint8_t buf[8], *ptr; - - ptr = buf; - - ptr += ubx_put_u8 (ptr, class); - ptr += ubx_put_u8 (ptr, id); //reserved - ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c - ptr += ubx_put_u8 (ptr, rate); //rate on uart - ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 - ptr += ubx_put_u8 (ptr, 0); //nothing on usb - ptr += ubx_put_u8 (ptr, 0); //nothing on spi - ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 - - return ubx_handshake (0x06, 0x01, buf, (unsigned) (ptr - buf)); -} - - -static int -ubx_cfg_rst (uint16_t flags) -{ - uint8_t buf[8], *ptr; - - ptr = buf; - - ptr += ubx_put_u16 (ptr, flags); //Flags - ptr += ubx_put_u8 (ptr, 0x4); //Hardware reset after shutdown - ptr += ubx_put_u8 (ptr, 0); //reserved - - ubx_send (0x06, 0x04, buf, (unsigned) (ptr - buf)); - return 0; -} - - -static int -gps_set_ref (int ref_hz) -{ - uint8_t buf[80], *ptr; - int ret; - - printf ("setting gps ref to %d hz\r\n", ref_hz); - - current_ref_hz = ref_hz; - - ptr = buf; - - ptr += ubx_put_u8 (ptr, 0); //timepluse 1 - ptr += ubx_put_u8 (ptr, 0); //version 0 - ptr += ubx_put_u16 (ptr, 0); //reserved - - // ptr += ubx_put_u16 (ptr, 32); //ant cable delay ns - ptr += ubx_put_u16 (ptr, 0); //ant cable delay ns - ptr += ubx_put_u16 (ptr, 0); //rf group delay ns - ptr += ubx_put_u32 (ptr, 1000000 / ref_hz); //period unlocked/us - ptr += ubx_put_u32 (ptr, 1000000 / ref_hz); //period locked/us - - // ptr += ubx_put_u32 (ptr, 0); //pulse width unlocked/us - ptr += ubx_put_u32 (ptr, 100000 / ref_hz); //pulse width unlocked/us - ptr += ubx_put_u32 (ptr, 100000 / ref_hz); //pulse width locked/us - - ptr += ubx_put_i32 (ptr, 0); // ? delay - -#if 0 - /*Separate numbers for locked/unlocked*/ - ptr += ubx_put_u32 (ptr, 0xf7); -#else - /*Same numbers for locked/unlocked*/ - ptr += ubx_put_u32 (ptr, 0xf7); -#endif - - - ret = ubx_handshake (0x06, 0x31, buf, (unsigned) (ptr - buf)); - - return ret; -} - - -static inline int -ubx_put_gnss_cfg (uint8_t *buf, uint8_t gnss_id,uint8_t r_chan,uint8_t m_chan, -uint16_t enable, uint16_t sig_mask) -{ - uint8_t *ptr=buf; - - ptr += ubx_put_u8(ptr,gnss_id); - ptr += ubx_put_u8(ptr,r_chan); - ptr += ubx_put_u8(ptr,m_chan); - ptr += ubx_put_u8(ptr,0); - ptr += ubx_put_u16(ptr,enable); - ptr += ubx_put_u16(ptr,sig_mask); - - return (unsigned) (ptr - buf); -} - -void gps_set_gnss(void) -{ - uint8_t buf[80], *ptr; - - ptr = buf; - ptr += ubx_put_u8 (ptr, 0x0); /* Ver 0 */ - ptr += ubx_put_u8 (ptr, 0x20); - ptr += ubx_put_u8 (ptr, 0x20); - ptr += ubx_put_u8 (ptr, 0x7); - - ptr += ubx_put_gnss_cfg(ptr,0,8,16,1,0x101); - ptr += ubx_put_gnss_cfg(ptr,1,1,3,1,0x101); - ptr += ubx_put_gnss_cfg(ptr,2,4,8,0,0x101); - ptr += ubx_put_gnss_cfg(ptr,3,8,16,0,0x101); - ptr += ubx_put_gnss_cfg(ptr,4,0,7,0,0x301); - ptr += ubx_put_gnss_cfg(ptr,5,0,3,1,0x501); - ptr += ubx_put_gnss_cfg(ptr,6,8,14,1,0x101); - - ubx_handshake (0x06, 0x3e, buf, (unsigned) (ptr - buf)); - - printf ("configured SBAS\r\n"); - - ubx_handshake (0x06, 0x3e, buf, 0); -} - - -int -gps_init (void) -{ - uint8_t buf[80], *ptr; - unsigned len; - // uint16_t u2; - - usart1_drain(); - - while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring)) - gps_dispatch(); - - - printf ("Testing GNSS...\r\n"); - ubx_handshake (0x06, 0x00, NULL, 0); - printf ("GNSS there\r\n"); - - //reset GNSS - -#if 0 - ptr=buf; - ptr += ubx_put_u32 (ptr, 0xe1f ); //uart1 - ptr += ubx_put_u32 (ptr, 0 ); //uart1 - ptr += ubx_put_u32 (ptr, 0 ); //uart1 - ubx_handshake (0x06, 0x09, buf, (unsigned) (ptr - buf)); - - printf ("reset\r\n"); -#endif - - - // Set up port - ptr = buf; - ptr += ubx_put_u8 (ptr, 1); //uart1 - ptr += ubx_put_u8 (ptr, 0); //reserved - ptr += ubx_put_u16 (ptr, 0x0); //flow control off - ptr += ubx_put_u32 (ptr, 0x8c0); //no parity, 8 bits - ptr += ubx_put_u32 (ptr, 9600); // baudrate - ptr += ubx_put_u16 (ptr, 0x7); // receive RTCM, NMEA, UBX - ptr += ubx_put_u16 (ptr, 0x1); // transmit UBX - ptr += ubx_put_u16 (ptr, 0x0); // no txtimeout - ptr += ubx_put_u16 (ptr, 0x0); // reserved - ubx_handshake (0x06, 0x00, buf, (unsigned) (ptr - buf)); - - printf ("configured GNSS protocol\r\n"); - - -#if 0 - ptr = buf; - ptr += ubx_put_u16 (ptr, 0x1b); - ptr += ubx_put_u16 (ptr, 0x00); - ubx_handshake (0x06, 0x13, buf, (unsigned) (ptr - buf)); - - printf ("configured antenna pins\r\n"); -#endif - - - -#if 0 - // Check we're in WGS84 - ptr = ubx_fetch (0x06, 0x06, NULL, 0, &len); - ptr += ubx_get_u16 (ptr, &u2); - - if (u2) - return -1; - - printf ("configured GNSS datum\r\n"); -#endif - - ptr = buf; - - ptr += ubx_put_u8 (ptr, 0); //UBX - ptr += ubx_put_u8 (ptr, 0); //reserved - ptr += ubx_put_u16 (ptr, 0); //reserved - ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c - ptr += ubx_put_u8 (ptr, 0x18); //everything on uart - ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 - ptr += ubx_put_u8 (ptr, 0); //nothing on usb - ptr += ubx_put_u8 (ptr, 0); //nothing on spi - ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 - - ptr += ubx_put_u8 (ptr, 1); //NMEA - ptr += ubx_put_u8 (ptr, 0); //reserved - ptr += ubx_put_u16 (ptr, 0); //reserved - ptr += ubx_put_u8 (ptr, 0); //nothing on port i2c - ptr += ubx_put_u8 (ptr, 0); //nothing on uart - ptr += ubx_put_u8 (ptr, 0); //nothing on port 2 - ptr += ubx_put_u8 (ptr, 0); //nothing on usb - ptr += ubx_put_u8 (ptr, 0); //nothing on spi - ptr += ubx_put_u8 (ptr, 0); //nothing on port 5 - - ubx_handshake (0x06, 0x02, buf, (unsigned) (ptr - buf)); - - printf ("configured GNSS data\r\n"); - - gps_set_ref (1); - - ubx_fetch (0x06, 0x31, NULL, 0, &len); - - printf ("configured GNSS 6.31\r\n"); - - - ubx_set_nav_rate(1000); - -#if 1 - ubx_set_message_rate_port1 (0x01, 0x03, 1); - ubx_set_message_rate_port1 (0x01, 0x21, 1); - ubx_set_message_rate_port1 (0x01, 0x22, 1); - ubx_set_message_rate_port1 (0x01, 0x32, 0); - - ubx_set_message_rate_port1 (0x01, 0x32, 0); /*SBAS*/ - ubx_set_message_rate_port1 (0x01, 0x35, 0); /*SV in view*/ - - ubx_set_message_rate_port1 (0x03, 0x0a, 0); - ubx_set_message_rate_port1 (0x03, 0x10, 0); - ubx_set_message_rate_port1 (0x03, 0x21, 0); - ubx_set_message_rate_port1 (0x04, 0x04, 0); - - printf ("GNSS ready\r\n"); -#else - ubx_set_message_rate_port1 (0x01, 0x03, 0); - ubx_set_message_rate_port1 (0x01, 0x21, 0); - ubx_set_message_rate_port1 (0x01, 0x22, 0); - ubx_set_message_rate_port1 (0x01, 0x32, 0); - ubx_set_message_rate_port1 (0x03, 0x0a, 0); - //ubx_set_message_rate_port1 (0x03, 0x10, 0); - printf ("GNSS ready\r\n"); -#endif - - - - // printf ("GPS ready\r\n"); - // ubx_get_clock_stats(); - - MAP_INPUT (PPS); - - exti_select_source (EXTI9, PPS_PORT); - exti_set_trigger (EXTI9, EXTI_TRIGGER_BOTH); - exti_enable_request (EXTI9); - nvic_enable_irq (NVIC_EXTI9_5_IRQ); - - return 0; -} - - -#define ALMANAC_LUMP 64 - -int -gps_almanac (void) -{ - uint32_t len = almanac_alp_len; - const uint8_t *ptr = almanac_alp; - uint32_t lumpsz; - uint8_t dummy; - - printf ("Downloading GPS almanac %x %x %x\r\n", (int) ptr[0], (int) ptr[1], - (int) ptr[2]); - - - while (len) { - printf ("%d bytes to go\r\n", (int) len); - - lumpsz = len > ALMANAC_LUMP ? ALMANAC_LUMP : len; - - ubx_handshake_xfer (0x0b, 0x50, ptr, lumpsz); - - ptr += lumpsz; - len -= lumpsz; - - } - - ubx_handshake_xfer (0x0b, 0x50, &dummy, 1); - - return 0; -} - -void gps_dump_almanac(void) -{ - ubx_send (0xb, 0x30, NULL,0); -} - - -#if 0 -int gps_bs(void) -{ - uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - EPOCH e = pll_decompose (abs); - UTC u = time_epoch_to_utc (e); - - uint8_t buf[80], *ptr; - int ret; - - ptr = buf; - - ptr += ubx_put_u32 (ptr, 391706007); /*19 sleaford st*/ - ptr += ubx_put_u32 (ptr, 955140); - ptr += ubx_put_u32 (ptr, 501672842); - ptr += ubx_put_u32 (ptr, 100000); /*1km std dev*/ - - ptr += ubx_put_u16 (ptr, 0); /*no time mark*/ - - ptr += ubx_put_u16 (ptr, (u.year-2000)*100 + u.month); - ptr += ubx_put_u32 (ptr, (u.mday*1000000) + (u.hour*10000) + (u.minute *100) +u.second); - ptr += ubx_put_u32 (ptr, u.nanosecond); - - ptr += ubx_put_u32 (ptr, 2000); /* time good to 2s */ - ptr += ubx_put_u32 (ptr, 0); - - ptr += ubx_put_u32 (ptr, 0); - ptr += ubx_put_u32 (ptr, 0); - - ptr += ubx_put_u32 (ptr, 0x403); - - printf("Bootstrapping GPS\r\n"); - - hexdump (buf, (unsigned) (ptr-buf)); - - ubx_send (0x0b, 0x01, buf, (unsigned) (ptr - buf)); - - - ret = 0; - - -/* - 00000: 97 f5 58 17 - 04 93 0e 00 - 8a eb e6 1d - a0 86 01 00 - 00010: 00 00 - 6f 07 19/03 - 03 cb 06 01 /17 22:24:03 - 65 ca af 02 45075045ns - - d0 07 00 00 2000ms - 00020: 00 00 00 00 0ns - 00 00 00 00 - 00 00 00 00 - 03 04 00 00 -*/ - - return ret; -} - -#endif - -int gps_bs(void) -{ - uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - EPOCH e = pll_decompose (abs); - UTC u = time_epoch_to_utc (e); - - uint8_t buf[80], *ptr; - int ret; - - ptr = buf; - - ptr += ubx_put_u8 (ptr, 0x0); - ptr += ubx_put_u8 (ptr, 0x0); - ptr += ubx_put_u8 (ptr, 0x0); - ptr += ubx_put_u8 (ptr, 0x0); - - ptr += ubx_put_u32 (ptr, 391706007); /*19 sleaford st*/ - ptr += ubx_put_u32 (ptr, 955140); - ptr += ubx_put_u32 (ptr, 501672842); - ptr += ubx_put_u32 (ptr, 100000); /*1km std dev*/ - - hexdump (buf, (unsigned) (ptr-buf)); - ubx_send (0x13, 0x40, buf, (unsigned) (ptr-buf)); - - - ptr = buf; - - ptr += ubx_put_u8 (ptr, 0x10); - ptr += ubx_put_u8 (ptr, 0x0); - ptr += ubx_put_u8 (ptr, 0x0); - ptr += ubx_put_u8 (ptr, 0x80); - - ptr += ubx_put_u16 (ptr,u.year-2000); - ptr += ubx_put_u8 (ptr,u.month); - ptr += ubx_put_u8 (ptr,u.mday); - - ptr += ubx_put_u8 (ptr,u.hour); - ptr += ubx_put_u8 (ptr,u.minute); - ptr += ubx_put_u8 (ptr,u.second); - ptr += ubx_put_u8 (ptr,0); - - ptr += ubx_put_u32 (ptr,u.nanosecond); - - ptr += ubx_put_u16 (ptr, 2); /* time good to 2s */ - ptr += ubx_put_u8 (ptr,0); - ptr += ubx_put_u8 (ptr,0); - - ptr += ubx_put_u32 (ptr, 0); - - hexdump (buf, (unsigned) (ptr-buf)); - ubx_send (0x13, 0x40, buf, (unsigned) (ptr-buf)); - - - ret = 0; - - return ret; -} - - -void -gps_reset (void) -{ - printf ("Restting gps..\r\n"); - -#define REPHEMERIDIES (1UL << 0) -#define RALMANAC (1UL << 1) -#define RPOS (1UL << 4) -#define RRTC (1UL << 8) - - ubx_cfg_rst (REPHEMERIDIES | RALMANAC | RPOS | RRTC); - - delay_ms (1000); - usart1_drain(); - - - printf ("Testing GNSS...\r\n"); - ubx_handshake (0x06, 0x00, NULL, 0); - printf ("GNSS there\r\n"); - - gps_init(); - - gps_set_ref (current_ref_hz); - - gps_set_gnss(); -} - -#if 0 -static int -ubx_get_clock_stats (void) -{ - uint8_t *ptr; - - unsigned len; - - ptr = ubx_fetch (0x01, 0x22, NULL, 0, &len); - - //return ubx_recv_clock_stats(ptr,len); - return ptr ? 0 : -1; -} -#endif diff --git a/app/lwip/lwipopts.h b/app/lwip/lwipopts.h index c590df9..d3c16b6 100644 --- a/app/lwip/lwipopts.h +++ b/app/lwip/lwipopts.h @@ -41,6 +41,14 @@ #define LWIP_PLATFORM_DIAG(a) printf a #endif +#define LWIP_PLATFORM_DIAG(a) printf a + +#if 0 +#define LWIP_DEBUG 1 +#define TIMERS_DEBUG LWIP_DBG_ON +#else +#define LWIP_DEBUG 0 +#endif /** * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain diff --git a/app/lwip/pbuf.h b/app/lwip/pbuf.h new file mode 100644 index 0000000..e8c9691 --- /dev/null +++ b/app/lwip/pbuf.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN 20 + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; + uint64_t ptp_timestamp; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/app/lwip_glue.c b/app/lwip_glue.c index 9fed1e6..065c297 100644 --- a/app/lwip_glue.c +++ b/app/lwip_glue.c @@ -10,45 +10,7 @@ uint32_t sys_now (void) void dispatch_lwip (void) { -#if 0 - static uint32_t fine_timer,coarse_timer; - uint32_t now=ticks; -#endif - -#if 0 - - if (link_lost()) - netif_set_down (&if0); - - if (link_gained()) - netif_set_up (&if0); - -#endif - sys_check_timeouts(); - -#if 0 - /* Fine DHCP periodic process every 500ms */ - if (now - fine_timer >= DHCP_FINE_TIMER_MSECS) { - fine_timer = now; - dhcp_fine_tmr(); - - if ((DHCP_state != DHCP_ADDRESS_ASSIGNED) && (DHCP_state != DHCP_TIMEOUT)) { - /* toggle LED1 to indicate DHCP on-going process */ - //STM_EVAL_LEDToggle (LED1); - - /* process DHCP state machine */ - LwIP_DHCP_Process_Handle(); - } - } - - /* DHCP Coarse periodic process every 60s */ - if (now - coarse_timer >= DHCP_COARSE_TIMER_MSECS) { - coarse_timer = now; - dhcp_coarse_tmr(); - } -#endif - } @@ -59,14 +21,14 @@ void start_lwip (void) lwip_init(); - netif_add (&if0, NULL,NULL,NULL, NULL, steth_lwip_init, ethernet_input); + netif_add (&if0, NULL, NULL, NULL, NULL, steth_lwip_init, ethernet_input); /* Registers the default network interface.*/ netif_set_default (&if0); netif_set_up (&if0); - dhcp_start(&if0); + dhcp_start (&if0); } diff --git a/app/main.c b/app/main.c index d5b5ec4..da5ffb8 100644 --- a/app/main.c +++ b/app/main.c @@ -17,37 +17,73 @@ void exti15_10_isr (void) -static void cmd_dispatch (void) +static void process_key (uint8_t c) { - uint8_t c; - while (!ring_read_byte (&rx2_ring, &c)) { + static int unlocked; + static unsigned unlock_sm; + static uint8_t unlock[] = "unlock"; + + if (!unlocked) { + if (c == unlock[unlock_sm]) { + unlock_sm++; + + if (!unlock[unlock_sm]) { + unlocked++; + printf ("Serial now unlocked\n"); + } - printf ("KEY> %c\r\n", c); + return; - switch (c) { - case 'R': - scb_reset_system(); + } else { + unlock_sm = 0; + printf ("serial locked type unlock to unlock\r\n"); + return; + } + } - break; - case 'G': - gps_reset(); - break; + printf ("KEY> %c\r\n", c); + + + switch (c) { + case 'R': + scb_reset_system(); + break; + + case 'G': + gps_reset(); + break; + + case 'I': + gps_bs(); + break; + + case 'A': + //gps_almanac(); + gps_dump_almanac(); + break; + + case 'D': + break; - case 'I': - gps_bs(); - break; - case 'A': - //gps_almanac(); - gps_dump_almanac(); - break; - } } } +static void cmd_dispatch (void) +{ + uint8_t c; + + while (!ring_read_byte (&usart2_rx_ring, &c)) + process_key (c); + + while (!ring_read_byte (&cdcacm_rx_ring, &c)) + process_key (c); + +} + #if 0 static void pd_port (uint32_t p) { @@ -271,37 +307,20 @@ static void clock_setup (void) #define REFCLK_OUT (GPIO8) #define REFCLK_OUT_PORT GPIOA -#define REFCLK_IN (GPIO7) -#define REFCLK_IN_PORT GPIOE static void timer_setup (void) { MAP_INPUT (REFCLK_OUT); - MAP_INPUT (REFCLK_IN); MAP_AF (REFCLK_OUT, GPIO_AF0); - MAP_AF (REFCLK_IN, GPIO_AF1); - #if 0 - /* Divide by 2 to trigger TIM2 */ - timer_reset (TIM1); - timer_set_mode (TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); - timer_set_master_mode (TIM1, TIM_CR2_MMS_UPDATE); - timer_set_period (TIM1, 1); - timer_slave_set_filter (TIM1, TIM_SMCR_ETF_OFF); - timer_slave_set_prescaler (TIM1, TIM_SMCR_ETPS_OFF); - TIM1_SMCR |= TIM_SMCR_ECE; - timer_enable_counter (TIM1); + /*Old scheme 10MHz -> TIM1 ETR -> TIM2 */ - timer_reset (TIM2); - timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); - timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/ - timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */ - timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */ - timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/ - timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/ - timer_enable_counter (TIM2); -#endif +#define REFCLK_IN (GPIO7) +#define REFCLK_IN_PORT GPIOE + + MAP_INPUT (REFCLK_IN); + MAP_AF (REFCLK_IN, GPIO_AF1); @@ -338,6 +357,26 @@ static void timer_setup (void) timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/ timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/ timer_enable_counter (TIM2); +#else + /* New Scheme 10MHz -> TIM2_ETR */ + +#define REFCLK_IN (GPIO15) +#define REFCLK_IN_PORT GPIOA + + MAP_INPUT (REFCLK_IN); + MAP_AF (REFCLK_IN, GPIO_AF1); + + + timer_reset (TIM2); + timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* count up with clock*/ + timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/ + timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */ + timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */ + timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/ + timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ETRF); /*Trigger from ETRF input */ + timer_enable_counter (TIM2); +#endif + } @@ -412,12 +451,14 @@ system_init (void) ptp_clock_start(); - max7219_init (1, 8); - + max7219_init (1); + max7219_dispatch(); gps_init(); ntp_init(); + adc_init(); + } @@ -435,8 +476,8 @@ main (void) while (1) { uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - EPOCH e = pll_decompose (abs); + uint64_t abs = ref_extend (now); + EPOCH e = ref_decompose (abs); time_print_epoch ("TEST: ", e); delay_ms (100); } @@ -449,8 +490,8 @@ main (void) #if 0 { uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - EPOCH e = pll_decompose (abs); + uint64_t abs = ref_extend (now); + EPOCH e = ref_decompose (abs); time_print_epoch ("TEST: ", e); delay_ms (100); } @@ -467,6 +508,9 @@ main (void) dispatch_lwip(); max7219_dispatch(); + adc_dispatch(); + + pll_check(); } diff --git a/app/max7219.c b/app/max7219.c index 85e66a7..7d5858e 100644 --- a/app/max7219.c +++ b/app/max7219.c @@ -94,7 +94,7 @@ write_reg (uint8_t reg, uint8_t data) static void -write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3) +_write_regs (uint8_t reg, uint8_t *data) { while (lock()); @@ -102,134 +102,224 @@ write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3) set (0, 0, 0); spip_send_8 (reg); - spip_send_8 (data3); + spip_send_8 (data[2]); spip_send_8 (reg); - spip_send_8 (data2); + spip_send_8 (data[1]); spip_send_8 (reg); - spip_send_8 (data1); + spip_send_8 (data[0]); set (0, 0, 0); set (0, 1, 0); unlock(); } -static void write_triad (uint8_t reg, int d1, int d2, int d3, unsigned dm) +static void write_regs (uint8_t reg, uint8_t d1, uint8_t d2, uint8_t d3) { - write_regs (reg++, (d1 % 10) | ((dm & 0x1) ? 0x80 : 0), (d2 % 10) | ((dm & 0x4) ? 0x80 : 0), (d3 % 10) | ((dm & 0x10) ? 0x80 : 0)); - write_regs (reg, (d1 / 10) | ((dm & 0x2) ? 0x80 : 0), (d2 / 10) | ((dm & 0x8) ? 0x80 : 0), (d3 / 10) | ((dm & 0x20) ? 0x80 : 0)); + uint8_t d[3] = {d1, d2, d3}; + _write_regs (reg, d); } -#if 0 -static void st_test (void) +#define SDP 0x80 +#define SA 0x40 +#define SB 0x20 +#define SC 0x10 +#define SD 0x08 +#define SE 0x04 +#define SF 0x02 +#define SG 0x01 + +static uint8_t hex (unsigned v) { + switch (v) { + case 0: + case '0': + return SA | SF | SB | SE | SC | SD; - UTC u = { 0 }; - double local_lon = 0.0; - ST st; - double ra; + case 1: + case '1': + return SB | SC; - // LEDS: 12.13.28.00 01.01.29.05 13.27.42.05 + case 2: + case '2': + case 'z': + return SA | SB | SG | SE | SD; - u.year = 2021; - u.month = 1; - u.mday = 12; - u.hour = 13; - u.minute = 28; + case 3: + case '3': + return SA | SB | SG | SC | SD; - ra = time_utc_to_ra (u); - st = time_ra_to_st (ra + local_lon); + case 4: + case '4': + return SF | SG | SB | SC; - printf ("%d:%02d:%02d\n", st.hour, st.minute, st.second); + case 5: + case '5': + case 's': + return SA | SF | SG | SC | SD; - st = time_utc_to_lst (u, local_lon); + case 6: + case '6': + return SA | SF | SG | SE | SC | SD; - printf ("%d:%02d:%02d\n", st.hour, st.minute, st.second); + case 7: + case '7': + return SA | SB | SC; - for (;;); -} -#endif + case 8: + case '8': + return SA | SF | SB | SG | SE | SC | SD; + case 9: + case '9': + case 'g': + return SA | SF | SB | SG | SC | SD; -unsigned fix_dots, fix_dots_even; + case 0xa: + case 'a': + return SA | SF | SB | SG | SE | SC; -void max7219_report_fix (char fix, char fix2) -{ - fix_dots = 0; + case 0xb: + case 'b': + return SF | SG | SE | SC | SD; + case 0xc: + case 'c': + return SG | SE | SD; - if (fix == 'L') - fix_dots |= 0x1; + case 0xd: + case 'd': + return SB | SG | SE | SC | SD; - if (fix2 == 'D') fix_dots |= 0x4; + case 0xe: + case 'e': + return SA | SF | SG | SE | SD; - if (fix == 'T') fix_dots |= 0x11; -} + case 0xf: + case 'f': + return SA | SF | SG | SE; -void max7219_report_svin (int valid, int active) -{ - fix_dots_even = 0; + case 'h': + return SF | SG | SE | SC; + + case 'i': + return SE; + + case 'j': + return SB | SC | SD; + + case 'k': + case 'x': + return SF | SB | SG | SE | SC; + + case 'l': + return SF | SE | SD; + + case 'm': + case 'n': + return SG | SE | SC; + + case 'o': + return SG | SE | SC | SD; + + case 'p': + return SA | SF | SB | SG | SE; + + case 'q': + return SA | SF | SB | SG | SC; + + case 'r': + return SG | SE; + + case 't': + return SF | SG | SE | SD; + + case 'u': + case 'w': + return SE | SC | SD; + + case 'y': + return SF | SB | SG | SC | SD; - if (active || valid) fix_dots_even |= 0x10; + case '-': + return SG; + + case '.': + return SDP; + + } + + return 0; } -void max7219_dispatch (void) +static void _write_triad (uint8_t reg, int *d, int *dp) { - uint32_t now = HW_CLOCK_REG; - uint64_t abs = abs_extend (now); - static unsigned m; - EPOCH e; - UTC u; - UTC gu; - ST l; - unsigned last_dots; + uint8_t regs0[3] = {0x0, 0x0, 0x0}; + uint8_t regs1[3] = {0x0, 0x0, 0x0}; + unsigned i; + for (i = 0; i < 3; ++i) { - e = pll_decompose (abs); - u = time_epoch_to_utc (e); - l = time_utc_to_lst (u, gps_lon); + if (d[i] < 0) continue; - e.s += gps_utc_diff; - gu = time_epoch_to_utc (e); + if (d[i] > 99) continue; - last_dots = fix_dots; + regs0[i] = hex (d[i] % 10); + regs1[i] = hex (d[i] / 10); + } - if (u.nanosecond < 500000000) last_dots |= fix_dots_even; + for (i = 0; i < 3; ++i) + if (dp[i]) regs0[i] |= SDP; - write_triad (1, u.nanosecond / 10000000, l.nanosecond / 10000000, gu.second, last_dots); - write_triad (3, u.second, l.second, gu.minute, 0x15); - write_triad (5, u.minute, l.minute, gu.hour, 0x15); - write_triad (7, u.hour, l.hour, gps_wday, 0x15); + _write_regs (reg++, regs0); + _write_regs (reg, regs1); +} - if (u.minute == m) return; +static void write_triad (uint8_t reg, int d1, int d2, int d3, int dp1, int dp2, int dp3) +{ + int d[3] = {d1, d2, d3}; + int dp[3] = {dp1, dp2, dp3}; - m = u.minute; + _write_triad (reg, d, dp); +} - printf ("LEDS: %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d lon %.6f\r\n", - u.hour, u.minute, u.second, - u.nanosecond / 10000000, - l.hour, - l.minute, - l.second, - l.nanosecond / 10000000, - gps_wday, - gu.hour, - gu.minute, - gu.second, - gps_lon); +static void write_string_over_numbers (char *str, int d1, int d2, int d3, int d4) +{ + unsigned reg; + + uint8_t digits[9] = { + 0, + hex (d4 % 10), + hex (d4 / 10), + hex (d3 % 10) | SDP, + hex (d3 / 10), + hex (d2 % 10) | SDP, + hex (d2 / 10), + hex (d1 % 10) | SDP, + hex (d1 / 10) + }; + + for (reg = 8; reg && *str; reg--, str++) + write_regs (reg, hex (*str) | (!str[1] ? SDP : 0), digits[reg], 0); + + for (; reg; reg--) + write_regs (reg, 0, digits[reg], 0); +} -} void -max7219_init (int on, int brightness) +max7219_init (int on) { + uint8_t d[3] = {0xf, 0xf, 0xf}; + unsigned i; + MAP_OUTPUT_PP (SCK); MAP_OUTPUT_PP (NCS); MAP_OUTPUT_PP (MOSI); @@ -242,17 +332,119 @@ max7219_init (int on, int brightness) write_reg (0xc, 0x1); //Power up write_reg (0xf, 0x0); //normal mode - write_reg (0x9, 0xff); //BCD decode + write_reg (0x9, 0x0); //no decode write_reg (0xb, 0x7); //8 digits - write_regs (0xa, brightness, brightness, brightness); + write_reg (0xa, pot_brightness); + + for (i = 1; i <= 8; ++i) + _write_regs (i, d); + + } else { write_reg (0xc, 0x0); //Power up } +} + + + +static int have_lock, have_dgps, have_time_lock, time_lock_enabled; + +void max7219_report_fix (char fix, char fix2) +{ + + have_lock = 0; + + if (fix == 'L') + have_lock = 1; + + if (fix2 == 'D') have_dgps = 1; + else have_dgps = 0; + + if (fix == 'T') { + have_lock = 1; + have_time_lock = 1; + } +} + +void max7219_report_svin (int valid, int active) +{ + time_lock_enabled = 0; + + if (active || valid) time_lock_enabled = 1; } +void max7219_dispatch (void) +{ + uint64_t abs = ref_get(); + static uint8_t last_brightness = 255; + int wday; + EPOCH e; + UTC u; + UTC gu; + ST l; + + + + if (last_brightness != pot_brightness) { + last_brightness = pot_brightness; + write_reg (0xa, last_brightness); + } + + if (gps_initting) + write_string_over_numbers ("gps init", 0, 0, 0, 0); + else if (!ref_valid) + write_string_over_numbers ("gps acq", gps_sats_searching, gps_sats_inop, gps_sats_locked, gps_sats_with_e); + + else { + static unsigned m; + + e = ref_decompose (abs); + u = time_epoch_to_utc (e); + l = time_utc_to_lst (u, gps_lon); + + if (have_lock) { + e.s += 86400; + e.s += gps_utc_diff; + gu = time_epoch_to_utc (e); + wday = gps_wday; + } else { + wday = 100; + gu.hour = 100; + gu.minute = 100; + gu.second = 100; + } + + write_triad (1, u.nanosecond / 10000000, l.nanosecond / 10000000, gu.second, time_lock_enabled, have_time_lock, have_dgps); + write_triad (3, u.second, l.second, gu.minute, 1, 1, 1); + write_triad (5, u.minute, l.minute, gu.hour, 1, 1, 1); + write_triad (7, u.hour, l.hour, wday, 1, 1, 1); + + if (u.minute == m) return; + + m = u.minute; + + printf ("LEDS: %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d lon %.6f\r\n", + u.hour, u.minute, u.second, + u.nanosecond / 10000000, + l.hour, + l.minute, + l.second, + l.nanosecond / 10000000, + gps_wday, + gu.hour, + gu.minute, + gu.second, + gps_lon); + + } + + +} + + diff --git a/app/msf.c b/app/msf.c index ab85cfe..bf7c376 100644 --- a/app/msf.c +++ b/app/msf.c @@ -42,6 +42,7 @@ void exti_t_isr (void) 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; @@ -79,7 +80,7 @@ static int check_min_ident (uint8_t *i) -static void process_bits (uint64_t abs) +static void process_bits (uint64_t abs, uint64_t ptp) { UTC u; EPOCH e; @@ -112,7 +113,7 @@ static void process_bits (uint64_t abs) msf_last_happy = make_happy (abs, 0); - pll_set_offset (e, abs); + pll_set_offset (e, abs, ptp); dump_bits ("msfa", bitsa); dump_bits ("msfb", bitsb); @@ -126,14 +127,14 @@ static void process_bits (uint64_t abs) } -static void report_bits (uint64_t abs, int second, int a, int b) +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); + if (second == 59) process_bits (abs, ptp); } @@ -146,6 +147,7 @@ void msf_dispatch (void) int is_s = 0; uint32_t now; + uint64_t ptp; int v; @@ -153,6 +155,7 @@ void msf_dispatch (void) 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); @@ -160,8 +163,8 @@ void msf_dispatch (void) #if 0 { - abs = abs_extend (now); - EPOCH e = pll_decompose (abs); + 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)); @@ -198,16 +201,16 @@ void msf_dispatch (void) if (is_s) { - abs = abs_extend (now); + abs = ref_extend (now); msf_last_second = abs; - pll_dispatch (msf_last_happy, abs, "MSF"); + 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, second, bita, bitb); + report_bits (abs, ptp, second, bita, bitb); second++; } diff --git a/app/ntp.c b/app/ntp.c index 0bdda4d..2b9e6f3 100644 --- a/app/ntp.c +++ b/app/ntp.c @@ -30,7 +30,7 @@ typedef struct { #if 0 packet (uint8_t *_p) { - EPOCH reftime = pll_decompose (pll_last_update); + EPOCH reftime = ref_decompose (pll_last_update); ntp_packet_t rx = (uint8_t *)_p; ntp_packet_t tx; @@ -52,10 +52,26 @@ packet (uint8_t *_p) } #endif -static uint64_t ntp_ts (uint64_t v) +static uint64_t ntp_ts_ref (uint64_t v) { uint64_t ret; - EPOCH e = pll_decompose (v); + EPOCH e = ref_decompose (v); + + ret = e.ns; + ret <<= 32; + ret = ret / 1000000000; + ret = htonl (ret); + ret <<= 32; + ret |= htonl (2208988800UL + e.s); + + return ret; +} + + +static uint64_t ntp_ts_ptp (uint64_t v) +{ + uint64_t ret; + EPOCH e = ptp_decompose (v); ret = e.ns; ret <<= 32; @@ -69,7 +85,7 @@ static uint64_t ntp_ts (uint64_t v) static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr *src_addr, u16_t port) { - uint32_t now = HW_CLOCK_REG; + uint64_t ref = ref_get_irq(); struct ip_addr dst_addr = *src_addr; ntp_packet_t pkt; @@ -78,7 +94,7 @@ static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr if (p->len < sizeof (ntp_packet_t)) break; - if (!pll_valid) break; + if (!ref_valid) break; if (!time_known) break; @@ -99,13 +115,19 @@ static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr pkt.reference_id = htonl (0x47505300); pkt.origin_ts = pkt.transmit_ts; - pkt.receive_ts = ntp_ts (abs_extend (now)); - pkt.reference_ts = ntp_ts (pll_last_update); +#if 0 + pkt.receive_ts = ntp_ts_ref (ref); +#else + pkt.receive_ts = ntp_ts_ptp (p->ptp_timestamp); +#endif - now = HW_CLOCK_REG; - pkt.transmit_ts = ntp_ts (abs_extend (now)); + pkt.receive_ts = ntp_ts_ref (ref); + pkt.reference_ts = ntp_ts_ref (ref_last_update); memcpy (p->payload, &pkt, sizeof (ntp_packet_t)); + compiler_mb(); + ref = ref_get_irq(); + pkt.transmit_ts = ntp_ts_ref (ref); udp_sendto (s, p, &dst_addr, port); } while (0); diff --git a/app/pins.h b/app/pins.h index 723ca82..9892cf1 100644 --- a/app/pins.h +++ b/app/pins.h @@ -49,6 +49,10 @@ gpio_mode_setup( a ## _PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, a ); \ } while (0) +#define MAP_ANALOG_INPUT(a) do { \ + gpio_mode_setup( a ## _PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, a ); \ + } while (0) + #define CLEAR(a) gpio_clear( a ## _PORT, a) #define SET(a) gpio_set( a ## _PORT, a) diff --git a/app/pll.c b/app/pll.c index 19681d8..d2d1495 100644 --- a/app/pll.c +++ b/app/pll.c @@ -1,293 +1,80 @@ #include "project.h" - -#define JUMP_THRESH 0.1 -#define JUMP_TICKS 30 -#define FEEDBACK 0.0001 #define WARM_UP 30 - -static int64_t offset; -static int64_t phase; -int64_t pll_freq = HW_CLOCK_HZ; - -static int out_of_lock = JUMP_TICKS + 1; - -uint64_t pll_last_update; -int pll_valid = 0; - -int pll_ready = 0; - - -# if 0 -#define PLL_BW 0.01 -#define PLL_DAMP 0.707 -#define PLL_GAIN 0.001 - -#define F_T1 ((PLL_GAIN)/((PLL_BW)*(PLL_BW))) -#define F_T2 ((2*(PLL_DAMP))/(PLL_BW)) - - -#define F_B0 (((4*(PLL_GAIN))/(F_T1))*(1.0+((F_T2)/(2.0)))) -#define F_B1 ((8*(PLL_GAIN))/(F_T1)) -#define F_B2 (((4*(PLL_GAIN))/(F_T1))*(1.0-((F_T2)/(2.0)))) - -#define F_A0 (1.0) -#define F_A1 (-2.0) -#define F_A2 (1.0) - -void pll_dump_filter (void) -{ - printf ("%g %g %g\n", F_A0, F_A1, F_A2); - printf ("%g %g %g\n", F_B0, F_B1, F_B2); -} - - - -static double filter (double in) -{ - static double v[3]; - double ret; - - v[2] = v[1]; - v[1] = v[0]; - v[0] = in - (v[1] * F_A1) - (v[2] * F_A2); - - return (v[0] * F_B0) + (v[1] * F_B1) + (v[2] * F_B2); - -} -#endif - - -#define PLL_ALPHA (0.005) -#define PLL_BETA (0.5*PLL_ALPHA*PLL_ALPHA) - - - - - - - -void pll_meh (void) -{ - printf (" %"PRId64" %"PRId64" %" PRId64 "\r\n", - pll_freq, offset, phase); - -} - - -static void modify_pll_freq (uint64_t now, int d) -{ - int64_t pd1, pd2, te; - - pd1 = now - phase; - te = pd1 / pll_freq; - pd1 %= pll_freq; - - if (pd1 > (pll_freq >> 1)) { - te++; - pd1 = pd1 - pll_freq; - } - - - if (d > 0) - pll_freq += d; - else - pll_freq -= -d; - - - pd2 = pd1 + (te * pll_freq); - - phase = now - pd2; -} - -uint64_t make_happy (uint64_t abs, int64_t shift) +void pll_set_offset (EPOCH epoch, uint64_t abs, uint64_t ptp) { - shift *= HW_CLOCK_HZ; - - if (shift < 0) { - shift = -shift; - - if (abs < (uint64_t) shift) return 0; - else - return abs - shift; - } - - return abs + shift; - + ref_set_offset (epoch, abs); + ptp_set_offset (epoch, ptp); } -void pll_dispatch (uint64_t happy, uint64_t edge, const char *src) +void pll_dispatch (uint64_t happy, uint64_t edge, uint64_t ptp_edge, const char *src) { - double f, g; - int64_t pd; - - - -#if 0 - { - int h1, h2, h3, h4; - EPOCH e; - UTC u; - char s1[80]; - char s2[80]; - char s3[80]; - char s4[80]; - - - e = pll_decompose (happy); - u = time_epoch_to_utc (e); - utc_to_str (s1, u); - h1 = e.s; + // int64_t delta_f; - e = pll_decompose (gps_last_happy); - u = time_epoch_to_utc (e); - utc_to_str (s2, u); - h2 = e.s; - - e = pll_decompose (dcf77_last_happy); - u = time_epoch_to_utc (e); - utc_to_str (s3, u); - h3 = e.s; - - e = pll_decompose (msf_last_happy); - u = time_epoch_to_utc (e); - utc_to_str (s4, u); - h4 = e.s; - - printf ("H %d %d %d %d\r\n", h1 - h2, h2 - h2, h3 - h2, h4 - h2); - // printf ("H %s %s %s %s\r\n",s1,s2,s3,s4); - } -#endif - - - if ((!gps_last_happy) && (!dcf77_last_happy) && (!msf_last_happy)) return; - - if (happy < gps_last_happy) return; - - if (happy < dcf77_last_happy) return; - - if (happy < msf_last_happy) return; - - if (!pll_ready && (edge < ((uint64_t) WARM_UP * (uint64_t) HW_CLOCK_HZ))) + if (((!gps_last_happy) && (!dcf77_last_happy) && (!msf_last_happy)) || + (happy < gps_last_happy) || + (happy < dcf77_last_happy) || + (happy < msf_last_happy) || + (edge < ((uint64_t) WARM_UP * (uint64_t) HW_CLOCK_HZ))) return; led_blink (100); -#if 0 - printf ("EDGE %08x%08x\r\n", - (unsigned) (edge >> 32), - (unsigned) (edge & 0xffffffff)); -#endif - - { - int diff, hf; - - pd = edge - phase; - pd %= pll_freq; - - hf = (int) (pll_freq >> 1); - - diff = (int) pd; - - if (diff > hf) - diff = diff - (int) pll_freq; - - - f = (double) diff; - g = f / (double) pll_freq; - } - - if ((g > (JUMP_THRESH)) || (g < - (JUMP_THRESH))) - out_of_lock++; - else if (out_of_lock <= JUMP_TICKS) - out_of_lock = 0; - - printf ("PLL pd %.3f %.1f pll_freq %d phase %d %s\r\n", (float) g, (float)f, (int) pll_freq, (int) phase, src); - - if ((out_of_lock > JUMP_TICKS) || !pll_ready) { - phase += pd; - out_of_lock = 0; - printf ("PLL - jumping\r\n"); - pll_freq = HW_CLOCK_HZ; - pll_ready = 1; - } else { - - phase += (int) (f * PLL_BETA); - modify_pll_freq (edge, (int) (f * PLL_ALPHA)); - - } - - pll_last_update = edge; + ref_dispatch (edge, src); + ptp_dispatch (ptp_edge, src); } - - -void pll_set_offset (EPOCH epoch, uint64_t abs) +void pll_check (void) { - int64_t new_offset; - int diff; + uint64_t ptp = ptp_get(); + uint64_t ref = ref_get(); + EPOCH re, pe; + UTC ru, pu; + static unsigned m; - /* Find nearest second to abs*/ - abs += pll_freq >> 2; - abs -= phase; - abs /= pll_freq; - new_offset = epoch.s - abs; + re = ref_decompose (ref); + ru = time_epoch_to_utc (re); - if (new_offset != offset) { - diff = (int) (new_offset - offset); + if (m == ru.minute) return; - printf ("PLL wallclock offset moved by %d\r\n", diff); - offset = new_offset; - } + m = ru.minute; - pll_valid = 1; - time_known = 1; -} + pe = ptp_decompose (ptp); + pu = time_epoch_to_utc (pe); -EPOCH _pll_decompose (uint64_t abs) -{ - EPOCH ret; - ret.s = abs / pll_freq; - abs -= pll_freq * ret.s; + printf ("PLL checks: R %04d-%02d-%02d %02d:%02d:%02d.%09d P %04d-%02d-%02d %02d:%02d:%02d.%09d\r\n", + ru.year, + ru.month + 1, + ru.mday, + ru.hour, + ru.minute, + ru.second, + ru.nanosecond, + pu.year, + pu.month + 1, + pu.mday, + pu.hour, + pu.minute, + pu.second, + pu.nanosecond); - ret.s += offset; - abs *= (uint64_t) 1000000000; - abs = abs / pll_freq; - ret.ns = abs; - return ret; -} -EPOCH pll_decompose_diff (int64_t diff) -{ - EPOCH ret; - if (diff >= 0) - return _pll_decompose (diff); - ret = _pll_decompose (-diff); - ret.s = -ret.s; - ret.ns = -ret.ns; - - return ret; -} -EPOCH pll_decompose (uint64_t abs) -{ +} - abs -= phase; - return _pll_decompose (abs); -} diff --git a/app/project.h b/app/project.h index ca623de..fcf16ce 100644 --- a/app/project.h +++ b/app/project.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "id.h" @@ -61,7 +62,9 @@ #include "prototypes.h" //#define HZ 10000000 + #define HW_CLOCK_HZ 10000000 +#define PTP_CLOCK_HZ 168000000 //#define HZ 167999973 //#define HZ 168000000 @@ -83,6 +86,11 @@ #define TRACE do { stdio_drain(); printf("%s:%d\r\n",__FUNCTION__,__LINE__); } while (0) +static inline void compiler_mb (void) +{ + asm volatile ("":::"memory"); +} + extern const unsigned char almanac_alp[]; extern unsigned int almanac_alp_len; diff --git a/app/prototypes.h b/app/prototypes.h index 4b20c86..e6b631b 100644 --- a/app/prototypes.h +++ b/app/prototypes.h @@ -21,10 +21,10 @@ extern int ring_read_byte(volatile ring_t *r, uint8_t *c); extern int ring_write(volatile ring_t *r, uint8_t *buf, size_t len, int blocking); extern int ring_empty(volatile ring_t *r); /* usart.c */ -extern volatile ring_t rx2_ring; -extern volatile ring_t tx2_ring; -extern volatile ring_t rx1_ring; -extern volatile ring_t tx1_ring; +extern volatile ring_t usart2_rx_ring; +extern volatile ring_t usart2_tx_ring; +extern volatile ring_t usart1_rx_ring; +extern volatile ring_t usart1_tx_ring; extern void usart2_isr(void); extern void usart2_queue(uint8_t d); extern void usart2_drain(void); @@ -62,22 +62,10 @@ extern void exti1_isr(void); extern void msf_dispatch(void); extern void msf_init(void); /* abs.c */ -extern uint64_t abs_extend(uint32_t now); -extern void abs_meh(void); -extern uint64_t abs_get(void); -extern void abs_slow_tick(void); /* pll.c */ -extern int64_t pll_freq; -extern uint64_t pll_last_update; -extern int pll_valid; -extern int pll_ready; -extern void pll_meh(void); -extern uint64_t make_happy(uint64_t abs, int64_t shift); -extern void pll_dispatch(uint64_t happy, uint64_t edge, const char *src); -extern void pll_set_offset(EPOCH epoch, uint64_t abs); -extern EPOCH _pll_decompose(uint64_t abs); -extern EPOCH pll_decompose_diff(int64_t diff); -extern EPOCH pll_decompose(uint64_t abs); +extern void pll_set_offset(EPOCH epoch, uint64_t abs, uint64_t ptp); +extern void pll_dispatch(uint64_t happy, uint64_t edge, uint64_t ptp_edge, const char *src); +extern void pll_check(void); /* main.c */ extern int time_known; extern int main(void); @@ -104,6 +92,11 @@ extern unsigned bcd(uint8_t *d, unsigned s, unsigned e); extern unsigned le_bcd(uint8_t *d, unsigned s, unsigned e); /* stats.c */ /* gps.c */ +extern unsigned gps_sats_searching; +extern unsigned gps_sats_inop; +extern unsigned gps_sats_locked; +extern unsigned gps_sats_with_e; +extern int gps_initting; extern uint64_t gps_last_happy; extern void exti9_5_isr(void); extern double gps_lat; @@ -121,12 +114,10 @@ extern void hexdump(void *_d, int len); /* bits.c */ extern void dump_bits(char *wot, uint8_t *bits); /* max7219.c */ -extern unsigned fix_dots; -extern unsigned fix_dots_even; +extern void max7219_init(int on); extern void max7219_report_fix(char fix, char fix2); extern void max7219_report_svin(int valid, int active); extern void max7219_dispatch(void); -extern void max7219_init(int on, int brightness); /* report.c */ extern void report_time(const char *src, EPOCH e, uint64_t abs, const char *info); /* sysclk.c */ @@ -138,6 +129,8 @@ extern ring_t cdcacm_rx_ring; extern ring_t cdcacm_tx_ring; extern const struct usb_interface_descriptor comm_iface; extern const struct usb_interface_descriptor data_iface; +extern const struct usb_iface_assoc_descriptor cdc_iface_assoc; +extern int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete); extern void cdcacm_tick(void); extern int cdcacm_write(char *ptr, int len, int blocking); extern void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue); @@ -150,4 +143,35 @@ extern void usb_init(void); /* dfu.c */ extern const struct usb_dfu_descriptor dfu_function; extern const struct usb_interface_descriptor dfu_iface; +extern const struct usb_iface_assoc_descriptor dfu_iface_assoc; extern int dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete); +/* adc.c */ +extern uint8_t pot_brightness; +extern void adc_dispatch(void); +extern void adc_init(void); +/* dummy_kb.c */ +extern const struct usb_interface_descriptor dummy_kb_iface; +extern const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc; +/* ref.c */ +extern uint64_t ref_last_update; +extern int ref_valid; +extern int ref_offset_known; +extern uint64_t ref_extend_irq(uint32_t now); +extern uint64_t ref_extend(uint32_t now); +extern uint64_t ref_get_irq(void); +extern uint64_t ref_get(void); +extern void ref_slow_tick(void); +extern uint64_t make_happy(uint64_t abs, int64_t shift); +extern void ref_dispatch(uint64_t edge, const char *src); +extern void ref_set_offset(EPOCH epoch, uint64_t abs); +extern EPOCH ref_decompose_diff(int64_t diff); +extern EPOCH ref_decompose(uint64_t abs); +/* ptp.c */ +extern int ptp_offset_known; +extern uint64_t ptp_to_u64(uint32_t l, uint32_t h); +extern uint64_t ptp_get(void); +extern void ptp_dispatch(uint64_t edge, const char *src); +extern void ptp_set_offset(EPOCH epoch, uint64_t abs); +extern EPOCH ptp_decompose_diff(int64_t diff); +extern EPOCH ptp_decompose(uint64_t abs); +extern void ptp_slow_tick(void); diff --git a/app/ptp.c b/app/ptp.c new file mode 100644 index 0000000..264918f --- /dev/null +++ b/app/ptp.c @@ -0,0 +1,274 @@ +#include "project.h" + +static volatile unsigned us_ptp_idx; +static volatile uint64_t us_ptp_freq[2]; +static volatile uint64_t us_ptp_offset[2]; +static volatile uint64_t us_ptp_phase[2]; + + +static int64_t ptp_phase; +static int64_t ptp_freq = PTP_CLOCK_HZ; +static int64_t ptp_offset; + +int ptp_offset_known; + + + +static void us_put (void) +{ + unsigned i = us_ptp_idx; + + i ^= 1; + us_ptp_freq[i] = ptp_freq; + us_ptp_offset[i] = ptp_offset; + us_ptp_phase[i] = ptp_phase; + + compiler_mb(); + us_ptp_idx = i; +} + +static void us_get (uint64_t *f, uint64_t *o, uint64_t *p) +{ + unsigned i; + + do { + i = us_ptp_idx; + *f = us_ptp_freq[i]; + *o = us_ptp_offset[i]; + *p = us_ptp_phase[i]; + compiler_mb(); + } while (i != us_ptp_idx); +} + +static void modify_ptp_freq (uint64_t now, uint64_t new) +{ + int64_t pd1, pd2, te; + + pd1 = now - ptp_phase; + te = pd1 / ptp_freq; + pd1 %= ptp_freq; + + if (pd1 > (ptp_freq >> 1)) { + te++; + pd1 = pd1 - ptp_freq; + } + + ptp_freq = new; + + pd2 = pd1 + (te * ptp_freq); + + ptp_phase = now - pd2; + +} + + + + + +uint64_t ptp_to_u64 (uint32_t l, uint32_t h) +{ + uint64_t ret; + + ret = h; + ret <<= 31; + ret |= l; + + return ret; +} + +uint64_t ptp_get (void) +{ + uint32_t pl, ph; + + ph = ETH_PTPTSHR; + + do { + compiler_mb(); + pl = ETH_PTPTSLR; + } while (ph != ETH_PTPTSHR); + + return ptp_to_u64 (pl, ph); +} + + + +#define FF_B 16 +#define FF_A ((FF_B)-1) +#define FF_C 16 + +static uint64_t fff; + +static void fll_init (uint64_t start_freq) +{ + fff = start_freq * FF_C; +} + +static uint64_t fll (uint64_t obs_freq) +{ + uint64_t new_freq; + + + + fff *= FF_A; + fff += obs_freq * FF_C; + fff += FF_B / 2; + fff /= FF_B; + + new_freq = fff; + new_freq += FF_C / 2; + new_freq /= FF_C; + + + return new_freq; +} + + +static int64_t edge_to_phase (uint64_t edge) +{ + int64_t obs_phase; + obs_phase = edge - ptp_phase; + obs_phase %= ptp_freq; + + if (obs_phase > ptp_freq / 2) + obs_phase -= ptp_freq; + + return obs_phase; +} + +#define PF_A 16 +static uint64_t pll (int64_t obs_phase) +{ + int64_t pd ; + + + pd = obs_phase / PF_A; + + if (!pd) { + if (obs_phase < 0) pd--; + + if (obs_phase > 0) pd++; + } + + + return pd; +} + + + + +void ptp_dispatch (uint64_t edge, const char *src) +{ + static uint64_t last_edge; + uint64_t obs_freq, obs_phase, new_freq; + static int jump_start = 1; + + obs_freq = edge - last_edge; + last_edge = edge; + obs_phase = edge_to_phase (edge); + + printf ("PTP PLL: obs_f=%9d delta_phi=%5d f=%9d %s\r\n", + (int) obs_freq, + (int) obs_phase, + (int) ptp_freq, src); + + /*Ignore bogus observations*/ + if (obs_freq > (PTP_CLOCK_HZ + (PTP_CLOCK_HZ / 2))) + return; + + if (obs_freq < (PTP_CLOCK_HZ - (PTP_CLOCK_HZ / 2))) + return; + + if (jump_start) { + new_freq = obs_freq; + fll_init (new_freq); + modify_ptp_freq (edge, new_freq); + ptp_phase += obs_phase; + jump_start = 0; + } else { + new_freq = fll (obs_freq); + modify_ptp_freq (edge, new_freq); + ptp_phase += pll (obs_phase); + } + + us_put(); + +} + +void ptp_set_offset (EPOCH epoch, uint64_t abs) +{ + int64_t new_offset; + int diff; + + + /* Find nearest second to abs*/ + abs += ptp_freq >> 2; + abs -= ptp_phase; + abs /= ptp_freq; + + new_offset = epoch.s - abs; + + if (new_offset != ptp_offset) { + diff = (int) (new_offset - ptp_offset); + + + printf ("PTP wallclock offset moved by %d\r\n", diff); + ptp_offset = new_offset; + us_put(); + } + + ptp_offset_known = 1; +} + +static EPOCH _ptp_decompose (uint64_t abs, uint64_t f, uint64_t o) +{ + EPOCH ret; + + + ret.s = abs / f; + abs -= f * ret.s; + + ret.s += o; + + abs *= (uint64_t) 1000000000; + abs = abs / f; + + ret.ns = abs; + + return ret; +} + +EPOCH ptp_decompose_diff (int64_t diff) +{ + EPOCH ret; + uint64_t f, o, p; + + us_get (&f, &o, &p); + + if (diff >= 0) + return _ptp_decompose (diff, f, o); + + ret = _ptp_decompose (-diff, f, o); + ret.s = -ret.s; + ret.ns = -ret.ns; + + return ret; +} + + +EPOCH ptp_decompose (uint64_t abs) +{ + uint64_t f, o, p; + us_get (&f, &o, &p); + + abs -= p; + + return _ptp_decompose (abs, f, o); +} + +void ptp_slow_tick (void) +{ +} + + + + diff --git a/app/ref.c b/app/ref.c new file mode 100644 index 0000000..a131fda --- /dev/null +++ b/app/ref.c @@ -0,0 +1,486 @@ +#include "project.h" + +static volatile unsigned us_ref_idx; +static volatile uint64_t us_ref_freq[2]; +static volatile uint64_t us_ref_offset[2]; +static volatile uint64_t us_ref_phase[2]; + +static volatile unsigned us_ro_idx; +static volatile uint32_t us_ro_high_tick[2]; +static volatile int us_ro_mm[2]; + + +static int64_t ref_offset; +static int64_t ref_phase; +static int64_t ref_freq = HW_CLOCK_HZ; + +uint64_t ref_last_update; +int ref_valid = 0; +int ref_offset_known = 0; + + +static void us_put (void) +{ + unsigned i = us_ref_idx; + + i ^= 1; + us_ref_freq[i] = ref_freq; + us_ref_offset[i] = ref_offset; + us_ref_phase[i] = ref_phase; + + compiler_mb(); + us_ref_idx = i; +} + +static void us_get (uint64_t *f, uint64_t *o, uint64_t *p) +{ + unsigned i; + + do { + i = us_ref_idx; + *f = us_ref_freq[i]; + *o = us_ref_offset[i]; + *p = us_ref_phase[i]; + compiler_mb(); + } while (i != us_ref_idx); +} + +#if HW_CLOCK_LEN == 32 + +#define QUARTER (1UL << 29) +#define HALF (1UL << 30) +#define THREE_QUARTERS (HALF+QUARTER) +#define ONE (~(uint32_t)0) + +uint64_t ref_extend_irq (uint32_t now) +{ + uint64_t ret; + uint32_t ht; + int m; + + ht = us_ro_high_tick[us_ro_idx]; + m = us_ro_mm[us_ro_idx]; + + if (!m) { + ret = ht; + ret <<= 32; + ret |= now; + } else { + if (now < HALF) { + ret = ht; + ret <<= 32; + ret |= now; + } else { + ret = ht - 1; + ret <<= 32; + ret |= now; + } + } + + return ret; +} + +uint64_t ref_extend (uint32_t now) +{ + uint64_t ret; + + uint32_t ht, oht; + int m, om; + unsigned i = us_ro_idx; + + oht = ht = us_ro_high_tick[i]; + om = m = us_ro_mm[i]; + + + if (!m) { + ret = ht; + ret <<= 32; + ret |= now; + + + if ((now > THREE_QUARTERS) && (now <= ONE)) { + ht++; + m = 1; + } + + } else { + if (now < HALF) { + ret = ht; + ret <<= 32; + ret |= now; + } else { + ret = ht - 1; + ret <<= 32; + ret |= now; + } + + if ((now > QUARTER) && (now < HALF)) + m = 0; + } + + + if ((ht != oht) || (m != om)) { + i ^= 1; + us_ro_high_tick[i] = ht; + us_ro_mm[i] = m; + compiler_mb(); + us_ro_idx = i; + } + + return ret; +} +#elif HW_CLOCK_LEN == 31 + +#define QUARTER (1UL << 28) +#define HALF (1UL << 29) +#define THREE_QUARTERS (HALF+QUARTER) +#define ONE (0x7fffffff) + + +uint64_t ref_extend_irq (uint32_t now) +{ + uint64_t ret; + + + uint32_t ht; + int m; + + ht = us_ro_high_tick[us_ro_idx]; + m = us_ro_mm[us_ro_idx]; + + + if (!m) { + ret = ht; + ret <<= 31; + ret |= now; + } else { + if (now < HALF) { + ret = ht; + ret <<= 31; + ret |= now; + } else { + ret = ht - 1; + ret <<= 31; + ret |= now; + } + } + + return ret; +} + + +uint64_t ref_extend (uint32_t now) +{ + uint64_t ret; + + + uint32_t ht, oht; + int m, om; + unsigned i = us_ro_idx; + + oht = ht = us_ro_high_tick[i]; + om = m = us_ro_mm[i]; + + + + + if (!m) { + ret = ht; + ret <<= 31; + ret |= now; + + if ((now > THREE_QUARTERS) && (now <= ONE)) { + ht++; + m = 1; + } + + } else { + if (now < HALF) { + ret = ht; + ret <<= 31; + ret |= now; + } else { + ret = ht - 1; + ret <<= 31; + ret |= now; + } + + if ((now > QUARTER) && (now < HALF)) + m = 0; + } + + + + if ((ht != oht) || (m != om)) { + i ^= 1; + us_ro_high_tick[i] = ht; + us_ro_mm[i] = m; + compiler_mb(); + us_ro_idx = i; + } + + return ret; +} + + + + + +#else +#error unknown hardware clock length +#endif + + +uint64_t ref_get_irq (void) +{ + uint32_t now = HW_CLOCK_REG; + return ref_extend_irq (now); +} + + +uint64_t ref_get (void) +{ + uint32_t now = HW_CLOCK_REG; + return ref_extend (now); +} + + +void ref_slow_tick() +{ + ref_get(); +} + + + +static void modify_ref_freq (uint64_t now, uint64_t new) +{ + int64_t pd1, pd2, te; + + pd1 = now - ref_phase; + te = pd1 / ref_freq; + pd1 %= ref_freq; + + if (pd1 > (ref_freq >> 1)) { + te++; + pd1 = pd1 - ref_freq; + } + + ref_freq = new; + + pd2 = pd1 + (te * ref_freq); + + ref_phase = now - pd2; + +} + +uint64_t make_happy (uint64_t abs, int64_t shift) +{ + shift *= HW_CLOCK_HZ; + + if (shift < 0) { + shift = -shift; + + if (abs < (uint64_t) shift) return 0; + else + return abs - shift; + } + + return abs + shift; + + +} + +#define FF_B 16 +#define FF_A ((FF_B)-1) +#define FF_C 16 + +static uint64_t fff; + +static void fll_init (uint64_t start_freq) +{ + fff = start_freq * FF_C; +} + +static uint64_t fll (uint64_t obs_freq) +{ + uint64_t new_freq; + + + + fff *= FF_A; + fff += obs_freq * FF_C; + fff += FF_B / 2; + fff /= FF_B; + + new_freq = fff; + new_freq += FF_C / 2; + new_freq /= FF_C; + + + return new_freq; +} + + +static int64_t edge_to_phase (uint64_t edge) +{ + int64_t obs_phase; + obs_phase = edge - ref_phase; + obs_phase %= ref_freq; + + if (obs_phase > ref_freq / 2) + obs_phase -= ref_freq; + + return obs_phase; +} + +#define PF_A 16 +static uint64_t pll (int64_t obs_phase) +{ + int64_t pd ; + + + pd = obs_phase / PF_A; + + if (!pd) { + if (obs_phase < 0) pd--; + + if (obs_phase > 0) pd++; + } + + + return pd; +} + + + +void ref_dispatch (uint64_t edge, const char *src) +{ + static uint64_t last_edge; + uint64_t obs_freq, obs_phase, new_freq; + static int jump_start = 1; + + if (!last_edge) { + last_edge = edge; + return; + } + + + obs_freq = edge - last_edge; + last_edge = edge; + obs_phase = edge_to_phase (edge); + + + + // delta_f = obs_freq - ref_freq; + + + + printf ("REF PLL: obs_f=%9d delta_phi=%5d f=%9d %s\r\n", + (int) obs_freq, + (int) obs_phase, + (int) ref_freq, src); + + + /*Ignore bogus observations*/ + if (obs_freq > (HW_CLOCK_HZ + (HW_CLOCK_HZ / 2))) + return; + + if (obs_freq < (HW_CLOCK_HZ - (HW_CLOCK_HZ / 2))) + return; + + if (jump_start) { + new_freq = obs_freq; + fll_init (new_freq); + modify_ref_freq (edge, new_freq); + ref_phase += obs_phase; + + jump_start = 0; + } else { + new_freq = fll (obs_freq); + modify_ref_freq (edge, new_freq); + ref_phase += pll (obs_phase); + } + + if (ref_offset_known) + ref_valid = 1; + + us_put(); + ref_last_update = edge; +} + + + +void ref_set_offset (EPOCH epoch, uint64_t abs) +{ + int64_t new_offset; + int diff; + + + /* Find nearest second to abs*/ + abs += ref_freq >> 2; + abs -= ref_phase; + abs /= ref_freq; + + new_offset = epoch.s - abs; + + if (new_offset != ref_offset) { + diff = (int) (new_offset - ref_offset); + + + printf ("REF wallclock offset moved by %d\r\n", diff); + ref_offset = new_offset; + } + + us_put(); + ref_offset_known = 1; + time_known = 1; +} + + + + +static EPOCH _ref_decompose (uint64_t abs, uint64_t f, uint64_t o) +{ + EPOCH ret; + + + ret.s = abs / f; + abs -= f * ret.s; + + ret.s += o; + + abs *= (uint64_t) 1000000000; + abs = abs / f; + + ret.ns = abs; + + return ret; +} + +EPOCH ref_decompose_diff (int64_t diff) +{ + EPOCH ret; + uint64_t f, o, p; + + us_get (&f, &o, &p); + + if (diff >= 0) + return _ref_decompose (diff, f, o); + + ret = _ref_decompose (-diff, f, o); + ret.s = -ret.s; + ret.ns = -ret.ns; + + return ret; +} + + +EPOCH ref_decompose (uint64_t abs) +{ + uint64_t f, o, p; + us_get (&f, &o, &p); + + abs -= p; + + return _ref_decompose (abs, f, o); +} diff --git a/app/roofclock.ld b/app/roofclock.ld deleted file mode 100644 index 325e7ce..0000000 --- a/app/roofclock.ld +++ /dev/null @@ -1,20 +0,0 @@ -/* Linker script for STM32F407VET6, 512K flash, 192K RAM. */ - -/* Define memory regions. */ -MEMORY -{ - rom (rx) : ORIGIN = 0x08004000, LENGTH = 496K - ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K -} - -/* Include the common ld script. */ -INCLUDE libopencm3_stm32f4.ld - -dfu_shared_location = ORIGIN(ram) + LENGTH(ram) - 1024; - -SECTIONS -{ - .dfu_shared dfu_shared_location :{ - dfu_flag = .; - } -} diff --git a/app/stats.c b/app/stats.c index 1764b70..0edea5d 100644 --- a/app/stats.c +++ b/app/stats.c @@ -12,9 +12,9 @@ void stats (void) d = msf_last_second; d -= (int64_t) dcf77_last_second; - g = time_epoch_to_utc (pll_decompose (dcf77_last_second)); - m = time_epoch_to_utc (pll_decompose (msf_last_second)); - e = pll_decompose_diff (d); + g = time_epoch_to_utc (ref_decompose (dcf77_last_second)); + m = time_epoch_to_utc (ref_decompose (msf_last_second)); + e = ref_decompose_diff (d); ms = (float) e.ns; ms = ms / 1000000.0; diff --git a/app/steth.c b/app/steth.c index 5b94e1d..9d56529 100644 --- a/app/steth.c +++ b/app/steth.c @@ -20,87 +20,131 @@ extern uint32_t TxBD; extern uint32_t RxBD; -#define FOO(a) \ - do { static uint32_t w; \ - uint32_t v=a; \ - if (v!=w) {\ - printf (" " #a": %08x (%08x +%08x -%08x)\r\n", \ - (unsigned) v,(unsigned) (v^w),(unsigned) ((v^w) &v),(unsigned) ((v^w)&w)); \ - }\ - w=v; \ - } while (0) +static void eth_smi_transact_wtimeo (void) +{ + int timeout = 200; + /* Begin transaction. */ + ETH_MACMIIAR |= ETH_MACMIIAR_MB; + /* Wait for not busy. */ + while (ETH_MACMIIAR & ETH_MACMIIAR_MB) { + if (! (timeout--)) return; -void steth_calculate_mac(void) + delay_us (10); + } +} + +static void eth_smi_write_wtimeo (uint8_t phy, uint8_t reg, uint16_t data) { - uint32_t uid[3]; - uint8_t *ptr; - unsigned i; - desig_get_unique_id (uid); + /* Write operation MW=1*/ + ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */ + (phy << ETH_MACMIIAR_PA_SHIFT) | + (reg << ETH_MACMIIAR_MR_SHIFT) | + ETH_MACMIIAR_MW; - ptr=(uint8_t *)uid; + ETH_MACMIIDR = data & ETH_MACMIIDR_MD; - for (i=0;inext) return ERR_IF; - while (!eth_tx (p->payload, p->len)); + + while (!eth_tx (p->payload, p->len)) { + delay_us (10); + + if (! (tries--)) return ERR_IF; + } + return ERR_OK; } + +static bool eth_rx_ptp (uint8_t *ppkt, uint32_t *len, uint32_t maxlen, uint64_t *tstamp) +{ + bool fs = false; + bool ls = false; + bool overrun = false; + uint32_t l = 0; + + while (! (ETH_DES0 (RxBD) & ETH_RDES0_OWN) && !ls) { + l = (ETH_DES0 (RxBD) & ETH_RDES0_FL) >> ETH_RDES0_FL_SHIFT; + + fs |= ETH_DES0 (RxBD) & ETH_RDES0_FS; + ls |= ETH_DES0 (RxBD) & ETH_RDES0_LS; + /* frame buffer overrun ?*/ + overrun |= fs && (maxlen < l); + + if (fs && !overrun) { + memcpy (ppkt, (void *)ETH_DES2 (RxBD), l); + ppkt += l; + *len += l; + maxlen -= l; + } + + *tstamp = ptp_to_u64 (ETH_DES6 (RxBD), ETH_DES7 (RxBD)); + + ETH_DES0 (RxBD) = ETH_RDES0_OWN; + RxBD = ETH_DES3 (RxBD); + } + + if (ETH_DMASR & ETH_DMASR_RBUS) { + ETH_DMASR = ETH_DMASR_RBUS; + ETH_DMARPDR = 0; + } + + return fs && ls && !overrun; +} + + static err_t steth_rx (void) { struct pbuf *p; uint32_t len; - p = pbuf_alloc (PBUF_RAW, MTU, PBUF_POOL); if (!p) return ERR_MEM; len = 0; - if (!eth_rx (p->payload, &len, MTU)) { + p->ptp_timestamp = 0; //get_ptp(); + + if (!eth_rx_ptp (p->payload, &len, MTU, &p->ptp_timestamp)) { pbuf_free (p); return ERR_IF; } pbuf_realloc (p, len); + return if0.input (p, &if0); } @@ -239,36 +331,6 @@ static void my_eth_init (uint8_t phy, enum eth_clk clock) } - -#if 0 -static void phy_set_ignore_address (void) -{ - unsigned i; - - i = 0; - - while (eth_smi_read (PHY0, 0) == 0xffff) { - delay_us (1000); - i++; - - if (i > 10) break; - } - - eth_smi_write (PHY, 0x11, 0x8); - - i = 0; - - while (eth_smi_read (PHY1, 0) == 0xffff) { - delay_us (1000); - i++; - - if (i > 10) break; - } - - eth_smi_write (PHY1, 0x11, 0x8); -} -#endif - static void eth_reset (void) { unsigned i; @@ -286,18 +348,6 @@ static void eth_reset (void) rcc_periph_reset_release (RST_ETHMAC); -#ifdef NRST -#if 0 - delay_us (1000); - CLEAR (NRST); - delay_us (1); - SET (NRST); - delay_us (1000); -#endif -#endif - - - TRACE; ETH_DMABMR |= ETH_DMABMR_SR; i = 0; @@ -306,20 +356,18 @@ static void eth_reset (void) delay_us (1000); i++; - if (i > 1000) { + if (i > 10) { printf ("No 50MHz clock to ethernet MAC\n"); return; } } /*MDC = HCLK / 102 (0b100) => 1.6MHz */ - TRACE; - my_eth_init (PHY, ETH_CLK_150_168MHZ); + //phy_set_ignore_address(); - TRACE; - phy_stat(); + phy_debug(); eth_set_mac (sa); eth_desc_init (eth_buf, TX_BUFS, RX_BUFS, FRAME_SZ, FRAME_SZ, 1); @@ -328,19 +376,15 @@ static void eth_reset (void) eth_irq_enable (ETH_DMAIER_NISE); eth_irq_enable (ETH_DMAIER_RIE); eth_irq_enable (ETH_DMASR_TS); - - } static void eth_start_an (void) { printf ("starting autonegociation\r\n"); - eth_smi_write (PHY, PHY_REG_ANTX, 0x1e1); - phy_autoneg_enable (PHY); + eth_smi_write_wtimeo (PHY, PHY_REG_ANTX, 0x1e1); + phy_autoneg_enable_wtimeo (PHY); } - - void steth_init (void) { @@ -393,37 +437,23 @@ steth_init (void) MAP_AF_100 (RXD1, GPIO_AF11); - /* The switch to RMII has be done with steth under reset, with no clock */ - eth_reset(); - - phy_stat(); - mac_stat(); - - - - -#if 0 - eth_smi_write (PHY, PHY_REG_BCR, 0x2100); - printf ("Waiting for link\r\n"); - - while (!phy_link_isup (phy)) { - phy_stat(); - delay_ms (1000); - } - -#endif + phy_debug(); + eth_debug(); eth_start_an(); nvic_enable_irq (NVIC_ETH_IRQ); + /* Fire up timestamping hardware */ - ready++; - + ETH_PTPTSCR |= ETH_PTPTSCR_TSE | ETH_PTPTSCR_TSSARFE; + ETH_PTPTSCR &= ~ETH_PTPTSCR_TSFCU; + ETH_PTPSSIR = 1; + ready++; } @@ -438,27 +468,28 @@ static void eth_stop (void) void steth_slow_tick (void) { - phy_stat(); + //printf("eth slow tick an_clock=%d\r\n",an_clock); + + phy_debug(); + #if 0 - mac_stat(); + eth_debug(); #endif if (!ready) return; an_happy = phy_link_an_done (PHY); - if ((!phy_link_isup (PHY) || !an_happy) && running) { + if ((!phy_link_isup_wtimeo (PHY) || !an_happy) && running) { printf ("stopping nic\r\n"); //eth_reset(); ETH_MACCR |= ETH_MACCR_RD; - running = 0; - } - if (!phy_link_isup (PHY) && an_happy) { + if (!phy_link_isup_wtimeo (PHY) && an_happy) { eth_start_an(); an_clock = 0; } @@ -475,11 +506,11 @@ void steth_slow_tick (void) an_clock = 0; - if (phy_link_isup (PHY) && an_happy && !running) { + if (phy_link_isup_wtimeo (PHY) && an_happy && !running) { printf ("autonegociation done\r\n"); printf ("phy link status %x\r\n", phy_link_status (PHY)); - switch (phy_link_status (PHY)) { + switch (phy_link_status_wtimeo (PHY)) { case LINK_HD_10M: TRACE; break; @@ -496,11 +527,12 @@ void steth_slow_tick (void) ETH_MACCR &= ~ETH_MACCR_RD; eth_start(); + + printf ("starting nic\r\n"); running++; } - - + // printf("end slow tick\r\n"); } diff --git a/app/sysclk.c b/app/sysclk.c index 1847c28..98b5ed8 100644 --- a/app/sysclk.c +++ b/app/sysclk.c @@ -11,6 +11,7 @@ void sysclk_event (void) sysclk_ring.events[sysclk_ring.tx_ptr].when = refclk_now; + sysclk_ring.events[sysclk_ring.tx_ptr].ptp = ptp_get(); sysclk_ring.events[sysclk_ring.tx_ptr].value = sysclk_now; sysclk_ring.tx_ptr = (sysclk_ring.tx_ptr + 1) & ERING_MASK; @@ -71,7 +72,7 @@ void sysclk_dispatch (void) refclk_now = sysclk_ring.events[sysclk_ring.rx_ptr].when; sysclk_ring.rx_ptr = (sysclk_ring.rx_ptr + 1) & ERING_MASK; - refclk_abs = abs_extend (refclk_now); + refclk_abs = ref_extend (refclk_now); e.s = sysclk_extend (sysclk_now); e.ns = 0; diff --git a/app/ticker.c b/app/ticker.c index bf7cf51..791839e 100644 --- a/app/ticker.c +++ b/app/ticker.c @@ -34,7 +34,9 @@ sys_tick_handler (void) slow = 0; - abs_slow_tick(); + ptp_slow_tick(); + + ref_slow_tick(); steth_slow_tick(); led_slow_tick(); } diff --git a/app/usart.c b/app/usart.c index 26616da..b01f09f 100644 --- a/app/usart.c +++ b/app/usart.c @@ -4,17 +4,17 @@ #define BIG_BUFFER_SIZE 600 -volatile ring_t rx2_ring; -static uint8_t rx2_ring_buf[BUFFER_SIZE]; +volatile ring_t usart2_rx_ring; +static uint8_t usart2_rx_ring_buf[BUFFER_SIZE]; -volatile ring_t tx2_ring; -static uint8_t tx2_ring_buf[BUFFER_SIZE]; +volatile ring_t usart2_tx_ring; +static uint8_t usart2_tx_ring_buf[BUFFER_SIZE]; -volatile ring_t rx1_ring; -static uint8_t rx1_ring_buf[BUFFER_SIZE]; +volatile ring_t usart1_rx_ring; +static uint8_t usart1_rx_ring_buf[BUFFER_SIZE]; -volatile ring_t tx1_ring; -static uint8_t tx1_ring_buf[BUFFER_SIZE]; +volatile ring_t usart1_tx_ring; +static uint8_t usart1_tx_ring_buf[BUFFER_SIZE]; #define TX1 GPIO9 @@ -43,7 +43,7 @@ void usart2_isr (void) /* Retrieve the data from the peripheral. */ data = usart_recv (USART2); - ring_write_byte (&rx2_ring, data); + ring_write_byte (&usart2_rx_ring, data); //usart6_queue(data); } @@ -51,7 +51,7 @@ void usart2_isr (void) if (((USART_CR1 (USART2) & USART_CR1_TXEIE) != 0) && ((USART_SR (USART2) & USART_SR_TXE) != 0)) { - if (ring_read_byte (&tx2_ring, &data)) { + if (ring_read_byte (&usart2_tx_ring, &data)) { /*No more data, Disable the TXE interrupt, it's no longer needed. */ usart_disable_tx_interrupt (USART2); } else @@ -63,14 +63,14 @@ void usart2_isr (void) void usart2_queue (uint8_t d) { - ring_write_byte (&tx2_ring, d); + ring_write_byte (&usart2_tx_ring, d); usart_enable_tx_interrupt (USART2); } void usart2_drain (void) { - while (!ring_empty (&tx2_ring)); + while (!ring_empty (&usart2_tx_ring)); } @@ -79,7 +79,7 @@ usart2_write (char *ptr, int len, int blocking) { int ret; - ret = ring_write (&tx2_ring, (uint8_t *) ptr, len, blocking); + ret = ring_write (&usart2_tx_ring, (uint8_t *) ptr, len, blocking); usart_enable_tx_interrupt (USART2); return ret; } @@ -97,14 +97,14 @@ void usart1_isr (void) /* Retrieve the data from the peripheral. */ data = usart_recv (USART1); - ring_write_byte (&rx1_ring, data); + ring_write_byte (&usart1_rx_ring, data); } /* Check if we were called because of TXE. */ if (((USART_CR1 (USART1) & USART_CR1_TXEIE) != 0) && ((USART_SR (USART1) & USART_SR_TXE) != 0)) { - if (ring_read_byte (&tx1_ring, &data)) { + if (ring_read_byte (&usart1_tx_ring, &data)) { /*No more data, Disable the TXE interrupt, it's no longer needed. */ usart_disable_tx_interrupt (USART1); } else @@ -116,14 +116,14 @@ void usart1_isr (void) void usart1_queue (uint8_t d) { - ring_write_byte (&tx1_ring, d); + ring_write_byte (&usart1_tx_ring, d); usart_enable_tx_interrupt (USART1); } void usart1_drain (void) { - while (!ring_empty (&tx1_ring)); + while (!ring_empty (&usart1_tx_ring)); } @@ -132,17 +132,17 @@ usart1_write (char *ptr, int len, int blocking) { int ret; - ret = ring_write (&tx1_ring, (uint8_t *) ptr, len, blocking); + ret = ring_write (&usart1_tx_ring, (uint8_t *) ptr, len, blocking); usart_enable_tx_interrupt (USART1); return ret; } void usart_rings_init (void) { - ring_init (&rx1_ring, rx1_ring_buf, sizeof (rx1_ring_buf)); - ring_init (&tx1_ring, tx1_ring_buf, sizeof (tx1_ring_buf)); - ring_init (&rx2_ring, rx2_ring_buf, sizeof (rx2_ring_buf)); - ring_init (&tx2_ring, tx2_ring_buf, sizeof (tx2_ring_buf)); + ring_init (&usart1_rx_ring, usart1_rx_ring_buf, sizeof (usart1_rx_ring_buf)); + ring_init (&usart1_tx_ring, usart1_tx_ring_buf, sizeof (usart1_tx_ring_buf)); + ring_init (&usart2_rx_ring, usart2_rx_ring_buf, sizeof (usart2_rx_ring_buf)); + ring_init (&usart2_tx_ring, usart2_tx_ring_buf, sizeof (usart2_tx_ring_buf)); } void diff --git a/app/usb.c b/app/usb.c index 053f126..ea432ef 100644 --- a/app/usb.c +++ b/app/usb.c @@ -13,12 +13,12 @@ static const struct usb_device_descriptor dev = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_CDC, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, + .bDeviceClass = 0xef, + .bDeviceSubClass = 0x02, + .bDeviceProtocol = 0x01, .bMaxPacketSize0 = 64, - .idVendor = ID_VENDOR, - .idProduct = ID_PRODUCT, + .idVendor = 0x0483, + .idProduct = 0xff03, .bcdDevice = 0x0200, .iManufacturer = 1, .iProduct = 2, @@ -30,15 +30,22 @@ static const struct usb_device_descriptor dev = { static const struct usb_interface ifaces[] = { { .num_altsetting = 1, - .altsetting = &comm_iface, + .altsetting = &dummy_kb_iface, + .iface_assoc = &dummy_kb_iface_assoc, }, { .num_altsetting = 1, - .altsetting = &data_iface, + .altsetting = &dfu_iface, + .iface_assoc = &dfu_iface_assoc, }, { .num_altsetting = 1, - .altsetting = &dfu_iface, + .altsetting = &comm_iface, + .iface_assoc = &cdc_iface_assoc, + }, + { + .num_altsetting = 1, + .altsetting = &data_iface, }, }; @@ -46,7 +53,7 @@ static const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, - .bNumInterfaces = 3, + .bNumInterfaces = 4, .bConfigurationValue = 1, .iConfiguration = 0, .bmAttributes = 0x80, @@ -55,10 +62,12 @@ static const struct usb_config_descriptor config = { }; static const char *usb_strings[] = { - VENDOR_NAME, - PRODUCT_NAME, - SERIAL_NUMBER, - "DFU", + VENDOR_NAME, /*1*/ + PRODUCT_NAME, /*2*/ + SERIAL_NUMBER, /*3*/ + "dummy device", /*4*/ + "Dfu iface", /*5*/ + "Clock iface", /*6*/ }; void otg_fs_isr (void) @@ -67,6 +76,30 @@ void otg_fs_isr (void) } +static int control_request (usbd_device *usbd_dev, + struct usb_setup_data *req, + uint8_t **buf, + uint16_t *len, + usbd_control_complete_callback *complete) +{ + if (dfu_control_request (usbd_dev, req, buf, len, complete)) + return 1; + + return cdcacm_control_request (usbd_dev, req, buf, len, complete); +} + +static void set_config (usbd_device *usbd_dev, uint16_t wValue) +{ + + cdcacm_set_config (usbd_dev, wValue); + + usbd_register_control_callback (usbd_dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + control_request); + +} + void usb_init (void) @@ -79,7 +112,7 @@ void usb_init (void) &dev, &config, usb_strings, - 4, + 6, usbd_control_buffer, sizeof (usbd_control_buffer)); @@ -89,7 +122,7 @@ void usb_init (void) OTG_FS_GCCFG &= ~OTG_GCCFG_VBUSASEN; OTG_FS_GCCFG &= ~OTG_GCCFG_VBUSBSEN; - usbd_register_set_config_callback (usb_device, cdcacm_set_config); + usbd_register_set_config_callback (usb_device, set_config); nvic_enable_irq (NVIC_OTG_FS_IRQ); diff --git a/boot/Makefile b/boot/Makefile index e744d9a..b4d340c 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -21,6 +21,8 @@ CSRCS=bootloader.c usb.c dfu.c delay.c usart.c max7219.c PROG = bootloader +HOST=tick + CPROTO=cproto V=1 BINARY = ${PROG} @@ -44,6 +46,8 @@ protos: ${CSRCS} ${CPROTO} -E "${CPP} $(CPPFLAGS)" -e -v ${CSRCS} > prototypes.h.tmp /bin/mv -f prototypes.h.tmp prototypes.h +fl: ${PROG}.hex + ssh ${HOST} flash_stm32 < ${PROG}.hex tidy: astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} diff --git a/boot/bootloader.c b/boot/bootloader.c index 27b6b98..a5932f0 100644 --- a/boot/bootloader.c +++ b/boot/bootloader.c @@ -20,7 +20,7 @@ #include "project.h" -#define BOOTLOADER_BUTTON GPIO15 +#define BOOTLOADER_BUTTON GPIO12 #define BOOTLOADER_BUTTON_PORT GPIOE @@ -92,12 +92,22 @@ int main (void) { rcc_periph_clock_enable (RCC_GPIOE); + rcc_periph_clock_enable (RCC_GPIOB); + rcc_periph_clock_enable (RCC_GPIOG); MAP_INPUT_PU (BOOTLOADER_BUTTON); + if ((dfu_flag != 0xfee1dead) && (GET (BOOTLOADER_BUTTON))) { + - if ((dfu_flag != 0xfee1dead) && (GET(BOOTLOADER_BUTTON))) { /* Boot the application if it's valid. */ if ((* (volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20020000) { + + max7219 ("boot"); + + rcc_periph_clock_disable (RCC_GPIOE); + rcc_periph_clock_disable (RCC_GPIOB); + rcc_periph_clock_disable (RCC_GPIOG); + /* Set vector table base address. */ SCB_VTOR = APP_ADDRESS & 0xFFFF; /* Initialise master stack pointer. */ @@ -106,17 +116,15 @@ int main (void) "g" (* (volatile uint32_t *)APP_ADDRESS), "r" (* (uint32_t *) (APP_ADDRESS + 4)) : "memory"); - } - } - - + } else + max7219 ("nofw dfu"); + } else + max7219 ("dfu"); dfu_flag = 0; rcc_periph_clock_enable (RCC_SYSCFG); - rcc_periph_clock_enable (RCC_GPIOB); - rcc_periph_clock_enable (RCC_GPIOG); rcc_clock_setup_hsi_3v3 (&hsi_16mhz_3v3_48); @@ -126,10 +134,9 @@ int main (void) RCC_AHB2RSTR &= ~RCC_AHB2RSTR_OTGFSRST; RCC_AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST; - max7219_init(); usart_init(); - usart2_xmit_str("\r\nDFU Bootloader\r\n"); + usart2_xmit_str ("\r\nDFU Bootloader\r\n"); delay_ms (100); usart_init(); usart2_xmit_str ("Ready\r\n"); diff --git a/boot/delay.c b/boot/delay.c index 132081a..d30b6ca 100644 --- a/boot/delay.c +++ b/boot/delay.c @@ -36,6 +36,7 @@ delay_ms (uint32_t d) delay_ms_count = d; while (delay_ms_count); + ticker_off(); } diff --git a/boot/dfu.c b/boot/dfu.c index f931a6e..4054520 100644 --- a/boot/dfu.c +++ b/boot/dfu.c @@ -36,7 +36,7 @@ static struct { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof (struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -115,6 +115,8 @@ static int usbdfu_getstatus_complete (usbd_device *usbd_dev, struct usb_setup_da uint32_t *dat = (uint32_t *) (prog.buf + i); flash_program_word (baseaddr + i, *dat); } + + max7219_report_addr (baseaddr); } flash_lock(); diff --git a/boot/max7219.c b/boot/max7219.c index 3e06562..7a374eb 100644 --- a/boot/max7219.c +++ b/boot/max7219.c @@ -91,32 +91,173 @@ write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3) set (0, 1, 0); } +#define SDP 0x80 +#define SA 0x40 +#define SB 0x20 +#define SC 0x10 +#define SD 0x08 +#define SE 0x04 +#define SF 0x02 +#define SG 0x01 + +static uint8_t hex (unsigned v) +{ + switch (v) { + case 0: + case '0': + return SA | SF | SB | SE | SC | SD; + + case 1: + case '1': + return SB | SC; + + case 2: + case '2': + case 'z': + return SA | SB | SG | SE | SD; + + case 3: + case '3': + return SA | SB | SG | SC | SD; + + case 4: + case '4': + return SF | SG | SB | SC; + + case 5: + case '5': + case 's': + return SA | SF | SG | SC | SD; + + case 6: + case '6': + return SA | SF | SG | SE | SC | SD; + + case 7: + case '7': + return SA | SB | SC; + + case 8: + case '8': + return SA | SF | SB | SG | SE | SC | SD; + + case 9: + case '9': + case 'g': + return SA | SF | SB | SG | SC | SD; + + case 0xa: + case 'a': + return SA | SF | SB | SG | SE | SC; + + case 0xb: + case 'b': + return SF | SG | SE | SC | SD; + + case 0xc: + case 'c': + return SG | SE | SD; + + case 0xd: + case 'd': + return SB | SG | SE | SC | SD; + + case 0xe: + case 'e': + return SA | SF | SG | SE | SD; + + case 0xf: + case 'f': + return SA | SF | SG | SE; + + case 'h': + return SF | SG | SE | SC; + + case 'i': + return SE; + + case 'j': + return SB | SC | SD; + + case 'k': + case 'x': + return SF | SB | SG | SE | SC; + + case 'l': + return SF | SE | SD; + + case 'm': + case 'n': + return SG | SE | SC; + + case 'o': + return SG | SE | SC | SD; + + case 'p': + return SA | SF | SB | SG | SE; + + case 'q': + return SA | SF | SB | SG | SC; + + case 'r': + return SG | SE; + + case 't': + return SF | SG | SE | SD; + + case 'u': + case 'w': + return SE | SC | SD; + + case 'y': + return SF | SB | SG | SC | SD; + + case '-': + return SG; + + case '.': + return SDP; + + } + + return 0; +} + +void max7219_report_addr (uint32_t baseaddr) +{ + unsigned i; + + for (i = 1; i <= 8; ++i) { + write_regs (i, hex (baseaddr & 0xf), 0, 0); + baseaddr >>= 4; + } +} + + void -max7219_init (void) +max7219 (const char *str) { MAP_OUTPUT_PP (SCK); MAP_OUTPUT_PP (NCS); MAP_OUTPUT_PP (MOSI); + unsigned reg; set (0, 1, 0); - write_reg (0xc, 0x1); //Power up - write_reg (0xf, 0x0); //normal mode + write_reg (0xc, 0x1); //Power up + write_reg (0xf, 0x0); //normal mode + + write_reg (0x9, 0x0); //No decode + write_reg (0xb, 0x7); //8 digits + write_regs (0xa, 15, 15, 15); //max brightness - write_reg (0x9, 0x0); //No decode - write_reg (0xb, 0x7); //8 digits - write_regs (0xa,15,15,15); //max brightness - write_reg (1,0); - write_reg (2,0); - write_reg (3,0); - write_reg (4,0); - write_reg (5,0); - write_regs (6,0xbe,0,0); - write_regs (7,0x47,0,0); - write_regs (8,0x3d,0,0); + for (reg = 8; reg && *str; reg--, str++) + write_regs (reg, hex (*str) | (!str[1] ? SDP : 0), 0, 0); + for (; reg; reg--) + write_reg (reg, 0); } diff --git a/boot/prototypes.h b/boot/prototypes.h index 17cc0fa..74f6b60 100644 --- a/boot/prototypes.h +++ b/boot/prototypes.h @@ -24,4 +24,5 @@ extern void usart2_xmit_xdigit(unsigned d); extern void usart2_xmit_uint32(uint32_t v); extern void usart_init(void); /* max7219.c */ -extern void max7219_init(void); +extern void max7219_report_addr(uint32_t baseaddr); +extern void max7219(const char *str); diff --git a/boot/usb.c b/boot/usb.c index e8d2e20..1454750 100644 --- a/boot/usb.c +++ b/boot/usb.c @@ -15,8 +15,8 @@ const struct usb_device_descriptor dev = { .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = 64, - .idVendor = ID_VENDOR, - .idProduct = ID_PRODUCT, + .idVendor = 0x0483, + .idProduct = 0xdf11, .bcdDevice = 0x0200, .iManufacturer = 1, .iProduct = 2, diff --git a/st/siderial_time.c b/st/siderial_time.c new file mode 100644 index 0000000..5175511 --- /dev/null +++ b/st/siderial_time.c @@ -0,0 +1,173 @@ +#include +#include + +typedef struct +{ + unsigned year; + unsigned is_leap; + unsigned jday; + unsigned month; + unsigned mday; + unsigned wday; + unsigned hour; + unsigned minute; + unsigned second; + unsigned nanosecond; +} UTC; + +typedef struct +{ + unsigned hour; + unsigned minute; + unsigned second; + unsigned nanosecond; +} ST; + +static int +is_leap (unsigned year) +{ + if (year % 4) + return 0; + + if (year % 100) + return 1; + + if (year % 400) + return 0; + + return 1; +} + + +double +time_utc_to_tjd (UTC u) +{ + unsigned y400; + unsigned y100; + unsigned y4; + + double ret, fd; + unsigned jd; + + static int const mdays[] = + { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + static int const lmdays[] = + { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + + u.is_leap = is_leap (u.year); + + if (u.year < 100) + u.year += 2000; + + + if (!u.jday) + { + if (u.is_leap) + u.jday = u.mday + lmdays[u.month]; + else + u.jday = u.mday + mdays[u.month]; + } + + u.year -= 1601; + y400 = u.year / 400; + u.year -= y400 * 400; + y100 = u.year / 100; + u.year -= y100 * 100; + y4 = u.year / 4; + u.year -= y4 * 4; + + jd = u.jday - 1; + jd += u.year * 365; + jd += y4 * 1461; + jd += y100 * 36524; + jd += y400 * 146097; + + + jd += 2305813; + jd -= 2451545; + + + + ret = (double) u.nanosecond; + ret /= 1000000000.; + ret = (double) u.second; + ret /= 60.; + ret += (double) u.minute; + ret /= 60.; + ret += (double) u.hour; + ret /= 24.; + + ret += .5; + + ret += (double) jd; + + return ret; +} + +double +time_utc_to_ra (UTC u) +{ + double tjd = time_utc_to_tjd (u); + double T = tjd / 36525.; + double theta0 = + 280.46061837 + (360.98564736629 * tjd) + (0.000387933 * T * T) - + (T * T * T / 38710000.0); + + return remainder (theta0, 360.); +} + + +ST +time_ra_to_st (double ra) +{ + ST ret; + unsigned i; + + while (ra < 0.) + ra += 360.; + if (ra >= 360.0) + ra = remainder (ra, 360.); + + ra *= 240.0; + + i = (int) (floor (ra) + .5); + ra -= (double) i; + ra *= 1000000000.; + + ret.nanosecond = (unsigned) (ra + .5); + ret.second = i % 60; + i /= 60; + ret.minute = i % 60; + i /= 60; + ret.hour = i; + + return ret; +} + + + + +int +main (int argc, char *argv[]) +{ + + UTC u = { 0 }; + double local_lon = 0.0; + ST st; + double ra; + + u.year = 2021; + u.month = 2; + u.mday = 12; + u.hour = 13; + u.minute =28; + + + ra = time_utc_to_ra (u); + st = time_ra_to_st (ra + local_lon); + + printf ("%d:%02d:%02d\n", st.hour, st.minute, st.second); + return 0; +} + + diff --git a/tools/dfuse-pack.py b/tools/dfuse-pack.py new file mode 100755 index 0000000..c0a5f0a --- /dev/null +++ b/tools/dfuse-pack.py @@ -0,0 +1,256 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +import binascii +from optparse import OptionParser + +try: + from intelhex import IntelHex +except ImportError: + IntelHex = None + +DEFAULT_DEVICE="0x0483:0xdf11" +DEFAULT_NAME=b'ST...' + +# Prefix and Suffix sizes are derived from ST's DfuSe File Format Specification (UM0391), DFU revision 1.1a +PREFIX_SIZE=11 +SUFFIX_SIZE=16 + +def named(tuple,names): + return dict(list(zip(names.split(),tuple))) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(bytestring): + return bytestring.partition(b'\0')[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print('File: "%s"' % file) + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix) + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix) + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print(' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix) + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print(' DUMPED IMAGE TO "%s"' % out) + if len(target): + print("target %d: PARSE ERROR" % t) + suffix = named(struct.unpack('<4H3sBI',data[:SUFFIX_SIZE]),'device product vendor dfu ufd len crc') + print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) + if crc != suffix['crc']: + print("CRC ERROR: computed crc32 is 0x%08x" % crc) + data = data[SUFFIX_SIZE:] + if data: + print("PARSE ERROR") + +def checkbin(binfile): + data = open(binfile,'rb').read() + if (len(data) < SUFFIX_SIZE): + return + crc = compute_crc(data[:-4]) + suffix = named(struct.unpack('<4H3sBI',data[-SUFFIX_SIZE:]),'device product vendor dfu ufd len crc') + if crc == suffix['crc'] and suffix['ufd'] == b'UFD': + print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) + print("It looks like the file %s has a DFU suffix!" % binfile) + print("Please remove any DFU suffix and retry.") + sys.exit(1) + +def build(file,targets,name=DEFAULT_NAME,device=DEFAULT_DEVICE): + data = b'' + for t,target in enumerate(targets): + tdata = b'' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + ealt = image['alt'] + tdata = struct.pack('<6sBI255s2I',b'Target',ealt,1,name,len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB',b'DfuSe',1,PREFIX_SIZE + len(data) + SUFFIX_SIZE,len(targets)) + data + v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)] + data += struct.pack('<4H3sB',0,d,v,0x011a,b'UFD',SUFFIX_SIZE) + crc = compute_crc(data) + data += struct.pack('