diff options
author | root <root@ka-ata-killa.ourano.james.local> | 2021-03-02 12:54:03 +0000 |
---|---|---|
committer | root <root@ka-ata-killa.ourano.james.local> | 2021-03-02 12:54:03 +0000 |
commit | 8c7ee88332652e7e79f6c1e4baacabe2183f7e8e (patch) | |
tree | a26ca60a089015822fa81ef44567927c1d8e334d | |
parent | 3d48137c00511b3f2d35511482d1a76f8d06382d (diff) | |
download | clock-8c7ee88332652e7e79f6c1e4baacabe2183f7e8e.tar.gz clock-8c7ee88332652e7e79f6c1e4baacabe2183f7e8e.tar.bz2 clock-8c7ee88332652e7e79f6c1e4baacabe2183f7e8e.zip |
working, with hybrid FLL/PLL, new refclk input and support for max7219 displays, neo 5 and neo 7 and a bazillion other fixes
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | app/ATTIC/gps_neo8.c (renamed from app/gps_neo8.c) | 20 | ||||
-rw-r--r-- | app/Makefile | 33 | ||||
-rw-r--r-- | app/abs.c | 121 | ||||
-rw-r--r-- | app/adc.c | 137 | ||||
-rw-r--r-- | app/cdcacm.c | 58 | ||||
-rw-r--r-- | app/clockv2.ld (renamed from app/roofclock.ld) | 0 | ||||
-rw-r--r-- | app/dcf77.c | 17 | ||||
-rw-r--r-- | app/dfu.c | 19 | ||||
-rw-r--r-- | app/dummy_kb.c | 26 | ||||
-rw-r--r-- | app/events.h | 1 | ||||
-rw-r--r-- | app/gps.c | 60 | ||||
-rw-r--r-- | app/lwip/lwipopts.h | 8 | ||||
-rw-r--r-- | app/lwip/pbuf.h | 179 | ||||
-rw-r--r-- | app/lwip_glue.c | 42 | ||||
-rw-r--r-- | app/main.c | 140 | ||||
-rw-r--r-- | app/max7219.c | 348 | ||||
-rw-r--r-- | app/msf.c | 21 | ||||
-rw-r--r-- | app/ntp.c | 40 | ||||
-rw-r--r-- | app/pins.h | 4 | ||||
-rw-r--r-- | app/pll.c | 293 | ||||
-rw-r--r-- | app/project.h | 8 | ||||
-rw-r--r-- | app/prototypes.h | 68 | ||||
-rw-r--r-- | app/ptp.c | 274 | ||||
-rw-r--r-- | app/ref.c | 486 | ||||
-rw-r--r-- | app/stats.c | 6 | ||||
-rw-r--r-- | app/steth.c | 314 | ||||
-rw-r--r-- | app/sysclk.c | 3 | ||||
-rw-r--r-- | app/ticker.c | 4 | ||||
-rw-r--r-- | app/usart.c | 44 | ||||
-rw-r--r-- | app/usb.c | 63 | ||||
-rw-r--r-- | boot/Makefile | 4 | ||||
-rw-r--r-- | boot/bootloader.c | 27 | ||||
-rw-r--r-- | boot/delay.c | 1 | ||||
-rw-r--r-- | boot/dfu.c | 4 | ||||
-rw-r--r-- | boot/max7219.c | 169 | ||||
-rw-r--r-- | boot/prototypes.h | 3 | ||||
-rw-r--r-- | boot/usb.c | 4 | ||||
-rw-r--r-- | st/siderial_time.c | 173 | ||||
-rwxr-xr-x | tools/dfuse-pack.py | 256 |
40 files changed, 2604 insertions, 875 deletions
@@ -4,6 +4,7 @@ *.orig *.hex *.map +*.bin .*.swp almanac.c almanac.alp diff --git a/app/gps_neo8.c b/app/ATTIC/gps_neo8.c index 9da5438..17118ed 100644 --- a/app/gps_neo8.c +++ b/app/ATTIC/gps_neo8.c @@ -50,7 +50,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 @@ -267,7 +267,7 @@ ubx_recv_utc (uint8_t *ptr, unsigned len) now = HW_CLOCK_REG; - abs = abs_extend (now); + abs = ref_extend (now); gps_last_happy = make_happy (abs, 180); @@ -587,12 +587,12 @@ static void gps_pps_dispatch (void) if (!v) return; - abs = abs_extend (now); + abs = ref_extend (now); if (gps_happy) pll_dispatch (gps_last_happy, abs, "GPS"); - e = pll_decompose (abs); + e = ref_decompose (abs); //u = time_epoch_to_utc (e); @@ -711,7 +711,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); @@ -865,7 +865,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(); @@ -1041,8 +1041,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; @@ -1104,8 +1104,8 @@ int gps_bs(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/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 @@ -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/roofclock.ld b/app/clockv2.ld index 325e7ce..325e7ce 100644 --- a/app/roofclock.ld +++ b/app/clockv2.ld 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); } @@ -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; @@ -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/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 <adam@sics.se> + * + */ + +#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); } @@ -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); + + } + + +} + + @@ -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++; } @@ -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); @@ -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) @@ -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 <libopencm3/usb/usbd.h> #include <libopencm3/usb/cdc.h> #include <libopencm3/usb/dfu.h> +#include <libopencm3/usb/hid.h> #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/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;i<ETHARP_HWADDR_LEN;++i) - sa[i]^=*(ptr++); - for (i=0;i<ETHARP_HWADDR_LEN;++i) - sa[i]^=*(ptr++); + eth_smi_transact_wtimeo(); +} - sa[0]&=0xfe; /*Clear I/G */ - sa[0]|=0x2; /*Set U/L */ +static uint16_t eth_smi_read_wtimeo (uint8_t phy, uint8_t reg) +{ + /* Read operation MW=0*/ + ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */ + (phy << ETH_MACMIIAR_PA_SHIFT) | + (reg << ETH_MACMIIAR_MR_SHIFT); + + eth_smi_transact_wtimeo(); -printf("MAC ADDRESS is %02x:%02x:%02x:%02x:%02x:%02x\r\n",sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + return (uint16_t) (ETH_MACMIIDR & ETH_MACMIIDR_MD); } +static void eth_smi_bit_set_wtimeo (uint8_t phy, uint8_t reg, uint16_t setbits) +{ + uint16_t val = eth_smi_read_wtimeo (phy, reg); + eth_smi_write_wtimeo (phy, reg, val | setbits); +} -static void mac_stat (void) +static bool phy_link_isup_wtimeo (uint8_t phy) { - //uint32_t d, s; + return eth_smi_read (phy, PHY_REG_BSR) & PHY_REG_BSR_UP; +} - printf ("Net:\r\n"); +static enum phy_status phy_link_status_wtimeo (uint8_t phy) +{ +#define PHY_REG_CR1 0x1E + return eth_smi_read_wtimeo (phy, PHY_REG_CR1) & 0x07; +} - FOO (ETH_MACCR); - FOO (ETH_MACFFR); - FOO (ETH_MACFCR); - FOO (ETH_MACDBGR); - FOO (ETH_MACSR); - FOO (ETH_DMAOMR); - FOO (ETH_DMASR); - FOO (ETH_DMAIER); - FOO (ETH_DMACHTDR); - FOO (ETH_DMACHRDR); - FOO (ETH_DMAOMR); - FOO (ETH_DMATDLAR); - FOO (ETH_DMARDLAR); - FOO (ETH_DMABMR); +static void phy_autoneg_enable_wtimeo (uint8_t phy) +{ + eth_smi_bit_set_wtimeo (phy, PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST); +} -#if 0 - s = d = RxBD; +void steth_calculate_mac (void) +{ + uint32_t uid[3]; + uint8_t *ptr; + unsigned i; + desig_get_unique_id (uid); + + ptr = (uint8_t *)uid; - if (running) - do { - printf (" %08" PRIx32 ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" - PRIx32 "\r\n", d, ETH_DES0 (d), ETH_DES1 (d), ETH_DES2 (d), - ETH_DES3 (d)); + for (i = 0; i < ETHARP_HWADDR_LEN; ++i) + sa[i] ^= * (ptr++); - d = ETH_DES3 (d); + for (i = 0; i < ETHARP_HWADDR_LEN; ++i) + sa[i] ^= * (ptr++); - } while (d != s); + sa[0] &= 0xfe; /*Clear I/G */ + sa[0] |= 0x2; /*Set U/L */ -#endif + printf ("MAC ADDRESS is %02x:%02x:%02x:%02x:%02x:%02x\r\n", sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); +} + + + +#define ETH_DEBUG(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_debug (void) +{ + printf ("Net:\r\n"); + ETH_DEBUG (ETH_MACCR); + ETH_DEBUG (ETH_MACFFR); + ETH_DEBUG (ETH_MACFCR); + ETH_DEBUG (ETH_MACDBGR); + ETH_DEBUG (ETH_MACSR); + ETH_DEBUG (ETH_DMAOMR); + ETH_DEBUG (ETH_DMASR); + ETH_DEBUG (ETH_DMAIER); + ETH_DEBUG (ETH_DMACHTDR); + ETH_DEBUG (ETH_DMACHRDR); + ETH_DEBUG (ETH_DMAOMR); + ETH_DEBUG (ETH_DMATDLAR); + ETH_DEBUG (ETH_DMARDLAR); + ETH_DEBUG (ETH_DMABMR); } #define PHY_REGS 0x20 -static void phy_stat_reg (unsigned i) +static void phy_show_reg (unsigned i) { static uint16_t last_phy[PHY_REGS]; - uint16_t cur = eth_smi_read (PHY, i); + uint16_t cur = eth_smi_read_wtimeo (PHY, i); if (cur == last_phy[i]) return; @@ -114,51 +158,99 @@ static void phy_stat_reg (unsigned i) } -static void phy_stat (void) +static void phy_debug (void) { unsigned i; for (i = 0; i < PHY_REGS; ++i) - phy_stat_reg (i); + phy_show_reg (i); } static bool phy_link_an_done (uint8_t phy) { - return eth_smi_read (phy, PHY_REG_BSR) & PHY_REG_BSR_ANDONE; + return eth_smi_read_wtimeo (phy, PHY_REG_BSR) & PHY_REG_BSR_ANDONE; } static err_t steth_tx (struct netif *netif, struct pbuf *p) { + unsigned tries = 3; + if (p->next) 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 @@ -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(); } @@ -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); @@ -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 <stdio.h> +#include <math.h> + +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('<I',crc) + open(file,'wb').write(data) + +if __name__=="__main__": + usage = """ +%prog [-d|--dump] infile.dfu +%prog {-b|--build} address:file.bin [-b address:file.bin ...] [{-D|--device}=vendor:device] outfile.dfu +%prog {-s|--build-s19} file.s19 [{-D|--device}=vendor:device] outfile.dfu +%prog {-i|--build-ihex} file.hex [-i file.hex ...] [{-D|--device}=vendor:device] outfile.dfu""" + parser = OptionParser(usage=usage) + parser.add_option("-b", "--build", action="append", dest="binfiles", + help="Include a raw binary file, to be loaded at the specified address. The BINFILES argument is of the form address:path-to-file. The address can have @X appended where X is the alternate interface number for this binary file. Note that the binary files must not have any DFU suffix!", metavar="BINFILES") + parser.add_option("-i", "--build-ihex", action="append", dest="hexfiles", + help="build a DFU file from given Intel HEX HEXFILES", metavar="HEXFILES") + parser.add_option("-s", "--build-s19", type="string", dest="s19files", + help="build a DFU file from given S19 S-record S19FILE", metavar="S19FILE") + parser.add_option("-D", "--device", action="store", dest="device", + help="build for DEVICE, defaults to %s" % DEFAULT_DEVICE, metavar="DEVICE") + parser.add_option("-a", "--alt-intf", action="store", dest="alt", + help="build for alternate interface number ALTINTF, defaults to 0", metavar="ALTINTF") + parser.add_option("-d", "--dump", action="store_true", dest="dump_images", + default=False, help="dump contained images to current directory") + (options, args) = parser.parse_args() + + targets = [] + + if options.alt: + try: + default_alt = int(options.alt) + except ValueError: + print("Alternate interface option argument %s invalid." % options.alt) + sys.exit(1) + else: + default_alt = 0 + + if (options.binfiles or options.hexfiles) and len(args)==1: + target = [] + old_ealt = None + + if options.binfiles: + for arg in options.binfiles: + try: + address,binfile = arg.split(':',1) + except ValueError: + print("Address:file couple '%s' invalid." % arg) + sys.exit(1) + try: + address,alts = address.split('@',1) + if alts: + try: + ealt = int(alts) + except ValueError: + print("Alternate interface number %s invalid." % alts) + sys.exit(1) + else: + ealt = default_alt + except ValueError: + ealt = default_alt + try: + address = int(address,0) & 0xFFFFFFFF + except ValueError: + print("Address %s invalid." % address) + sys.exit(1) + if not os.path.isfile(binfile): + print("Unreadable file '%s'." % binfile) + sys.exit(1) + checkbin(binfile) + if old_ealt is not None and ealt != old_ealt: + targets.append(target) + target = [] + target.append({ 'address': address, 'alt': ealt, 'data': open(binfile,'rb').read() }) + old_ealt = ealt + targets.append(target) + + if options.hexfiles: + if not IntelHex: + print("Error: IntelHex python module could not be found") + sys.exit(1) + for hexf in options.hexfiles: + ih = IntelHex(hexf) + for (address,end) in ih.segments(): + try: + address = address & 0xFFFFFFFF + except ValueError: + print("Address %s invalid." % address) + sys.exit(1) + target.append({ 'address': address, 'alt': default_alt, 'data': ih.tobinstr(start=address, end=end-1)}) + targets.append(target) + + outfile = args[0] + device = DEFAULT_DEVICE + if options.device: + device=options.device + try: + v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)] + except: + print("Invalid device '%s'." % device) + sys.exit(1) + build(outfile,targets,DEFAULT_NAME,device) + elif options.s19files and len(args)==1: + address = 0 + data = "" + target = [] + name = DEFAULT_NAME + with open(options.s19files) as f: + lines = f.readlines() + for line in lines: + curaddress = 0 + curdata = "" + line = line.rstrip() + if line.startswith ( "S0" ): + name = binascii.a2b_hex(line[8:len(line) - 2]) + elif line.startswith ( "S3" ): + try: + curaddress = int(line[4:12], 16) & 0xFFFFFFFF + except ValueError: + print("Address %s invalid." % address) + sys.exit(1) + curdata = binascii.unhexlify(line[12:-2]) + elif line.startswith ( "S2" ): + try: + curaddress = int(line[4:10], 16) & 0xFFFFFFFF + except ValueError: + print("Address %s invalid." % address) + sys.exit(1) + curdata = binascii.unhexlify(line[10:-2]) + elif line.startswith ( "S1" ): + try: + curaddress = int(line[4:8], 16) & 0xFFFFFFFF + except ValueError: + print("Address %s invalid." % address) + sys.exit(1) + curdata = binascii.unhexlify(line[8:-2]) + if address == 0: + address = curaddress + data = curdata + elif address + len(data) != curaddress: + target.append({ 'address': address, 'alt': default_alt, 'data': data }) + address = curaddress + data = curdata + else: + data += curdata + outfile = args[0] + device = DEFAULT_DEVICE + if options.device: + device=options.device + try: + v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)] + except: + print("Invalid device '%s'." % device) + sys.exit(1) + build(outfile,[target],name,device) + elif len(args)==1: + infile = args[0] + if not os.path.isfile(infile): + print("Unreadable file '%s'." % infile) + sys.exit(1) + parse(infile, dump_images=options.dump_images) + else: + parser.print_help() + if not IntelHex: + print("Note: Intel hex files support requires the IntelHex python module") + sys.exit(1) |